From 31f18b776d001752a193a7cec8bb49033c1a904c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fabian=20Gr=C3=BCnbichler?= Date: Tue, 27 Jun 2017 09:46:02 +0200 Subject: [PATCH] update sources to v12.1.0 --- Makefile | 4 +- ceph/.gitmodules | 3 + ceph/.mailmap | 16 +- ceph/.organizationmap | 21 +- ceph/AUTHORS | 15 +- ceph/CMakeLists.txt | 121 +- ceph/COPYING | 4 - ceph/PendingReleaseNotes | 121 +- ceph/alpine/APKBUILD | 13 +- ceph/alpine/APKBUILD.in | 7 +- ceph/ceph.spec | 380 +- ceph/ceph.spec.in | 374 +- ceph/cmake/modules/BuildBoost.cmake | 184 + ceph/cmake/modules/Findatomic_ops.cmake | 28 - ceph/cmake/modules/Findpmem.cmake | 15 + ceph/cmake/modules/SIMDExt.cmake | 60 +- ceph/debian/ceph-base.install | 2 - ceph/debian/ceph-base.maintscript | 2 + ceph/debian/ceph-common.install | 1 + ceph/debian/ceph-osd.install | 1 - ceph/debian/ceph-test.install | 2 - ceph/debian/changelog | 6 + ceph/debian/control | 14 +- ceph/debian/copyright | 4 - ceph/debian/radosgw.install | 1 + ceph/debian/rules | 11 +- ceph/do_cmake.sh | 9 +- ceph/doc/api/index.rst | 8 - ceph/doc/architecture.rst | 24 +- ceph/doc/cephfs/administration.rst | 37 + ceph/doc/cephfs/eviction.rst | 200 +- ceph/doc/cephfs/file-layouts.rst | 8 + ceph/doc/cephfs/multimds.rst | 3 + ceph/doc/dev/blkin.rst | 2 +- ceph/doc/dev/dev_cluster_deployement.rst | 8 - ceph/doc/dev/development-workflow.rst | 4 +- ceph/doc/dev/documenting.rst | 2 +- ceph/doc/dev/index.rst | 91 +- .../erasure_coding/developer_notes.rst | 2 +- ceph/doc/dev/perf_counters.rst | 182 +- ceph/doc/dev/perf_histograms.rst | 677 + ceph/doc/dev/placement-group.rst | 11 +- ceph/doc/dev/quick_guide.rst | 5 +- ceph/doc/install/build-ceph.rst | 3 +- ceph/doc/install/get-packages.rst | 4 +- ceph/doc/install/index.rst | 7 +- ceph/doc/install/manual-deployment.rst | 8 +- .../doc/install/manual-freebsd-deployment.rst | 624 + ceph/doc/install/mirrors.rst | 1 + ceph/doc/man/8/ceph-detect-init.rst | 11 + ceph/doc/man/8/ceph-disk.rst | 6 + ceph/doc/man/8/ceph-osd.rst | 14 +- ceph/doc/man/8/ceph.rst | 62 +- ceph/doc/man/8/rados.rst | 12 + ceph/doc/mgr/administrator.rst | 27 +- ceph/doc/mgr/dashboard.rst | 15 + ceph/doc/mgr/index.rst | 16 + ceph/doc/mgr/restful.rst | 25 + .../configuration/filestore-config-ref.rst | 16 +- .../rados/configuration/mon-config-ref.rst | 437 +- .../rados/configuration/mon-lookup-dns.rst | 7 + .../configuration/mon-osd-interaction.rst | 165 +- .../rados/configuration/osd-config-ref.rst | 22 +- .../configuration/pool-pg-config-ref.rst | 84 +- ceph/doc/rados/operations/crush-map.rst | 2 +- .../operations/erasure-code-jerasure.rst | 2 +- ceph/doc/rados/operations/erasure-code.rst | 2 +- ceph/doc/rados/operations/user-management.rst | 1 + .../troubleshooting/memory-profiling.rst | 2 +- .../troubleshooting/troubleshooting-osd.rst | 52 +- ceph/doc/radosgw/admin.rst | 14 + ceph/doc/radosgw/adminops.rst | 5 - ceph/doc/radosgw/barbican.rst | 3 +- ceph/doc/radosgw/bucketpolicy.rst | 133 + ceph/doc/radosgw/config-fcgi.rst | 595 - ceph/doc/radosgw/config-ref.rst | 501 +- ceph/doc/radosgw/encryption.rst | 2 +- ceph/doc/radosgw/federated-config.rst | 825 - ceph/doc/radosgw/index.rst | 7 +- ceph/doc/radosgw/layout.rst | 87 +- ceph/doc/radosgw/multisite.rst | 63 +- ceph/doc/radosgw/nfs.rst | 366 + ceph/doc/radosgw/pools.rst | 55 + ceph/doc/radosgw/rgw-centos.conf | 30 - ceph/doc/radosgw/rgw-debian.conf | 29 - ceph/doc/radosgw/rgw.conf | 30 - ceph/doc/radosgw/upgrade_to_jewel.rst | 43 - ceph/doc/release-notes.rst | 898 +- ceph/doc/start/documenting-ceph.rst | 3 +- ceph/doc/start/get-involved.rst | 4 +- ceph/doc/start/quick-ceph-deploy.rst | 7 +- ceph/examples/librados/Makefile | 12 +- ceph/examples/librados/hello_radosstriper.cc | 102 + ceph/install-deps.sh | 9 +- ceph/mirroring/MIRRORS | 1 + ceph/qa/clusters/extra-client.yaml | 5 + ceph/qa/clusters/fixed-1.yaml | 4 + ceph/qa/clusters/fixed-2.yaml | 5 + ceph/qa/clusters/fixed-3-cephfs.yaml | 5 + ceph/qa/clusters/fixed-3.yaml | 5 + ceph/qa/clusters/fixed-4.yaml | 5 + ceph/qa/machine_types/vps.yaml | 2 - ceph/qa/objectstore/bluestore-comp.yaml | 2 +- ceph/qa/objectstore/bluestore.yaml | 3 +- ceph/qa/releases/luminous-with-mgr.yaml | 2 +- ceph/qa/releases/luminous.yaml | 2 +- .../tasks/client-recovery.yaml | 1 + .../tasks/test_journal_migration.yaml} | 0 .../multiclient/tasks/cephfs_misc_tests.yaml | 5 + ceph/qa/suites/fs/multifs/tasks/failover.yaml | 3 + ceph/qa/suites/fs/standbyreplay/begin.yaml | 1 - .../clusters/standby-replay.yaml | 17 - .../suites/fs/standbyreplay/mount/fuse.yaml | 1 - ceph/qa/suites/fs/standbyreplay/objectstore | 1 - .../fs/standbyreplay/overrides/debug.yaml | 1 - .../standbyreplay/overrides/frag_enable.yaml | 1 - .../whitelist_wrongly_marked_down.yaml | 1 - .../suites/fs/thrash/ceph-thrash/default.yaml | 5 + .../kcephfs/recovery/tasks/auto-repair.yaml | 1 + .../kcephfs/recovery/tasks/client-limits.yaml | 5 + .../suites/kcephfs/recovery/tasks/damage.yaml | 1 + .../kcephfs/recovery/tasks/data-scan.yaml | 2 + .../kcephfs/recovery/tasks/forward-scrub.yaml | 1 + .../recovery/tasks/journal-repair.yaml | 3 + .../suites/kcephfs/thrash/thrashers/mds.yaml | 5 + .../rbd-nomount/tasks/krbd_fallocate.yaml} | 2 +- ceph/qa/suites/krbd/unmap/ceph/ceph.yaml | 3 + .../basic/q_check_counter/check_counter.yaml | 8 + .../tasks/cfuse_workunit_suites_fsync.yaml | 5 - .../tasks/cfuse_workunit_suites_iogen.yaml | 6 - .../tasks/cfuse_workunit_suites_iozone.yaml | 5 - .../cfuse_workunit_suites_truncate_delay.yaml | 14 - .../tasks/cfuse_workunit_trivial_sync.yaml | 1 - .../tasks/cfuse_workunit_trivial_sync.yaml | 1 - .../standbyreplay => rados/basic-luminous}/% | 0 ceph/qa/suites/rados/basic-luminous/ceph.yaml | 1 + ceph/qa/suites/rados/basic-luminous/clusters | 1 + .../suites/rados/basic-luminous/objectstore | 1 + .../qa/suites/rados/basic-luminous/rados.yaml | 1 + .../tasks => basic-luminous}/scrub_test.yaml | 1 + .../suites/rados/basic/tasks/repair_test.yaml | 1 + .../suites/rados/basic/tasks/rgw_snaps.yaml | 3 +- ceph/qa/suites/rados/rest/mgr-restful.yaml | 16 + .../all/admin_socket_output.yaml | 15 + .../singleton-nomsgr/all/full-tiering.yaml | 2 + .../singleton-nomsgr/all/health-warnings.yaml | 16 + .../all/multi-backfill-reject.yaml | 3 + .../singleton-nomsgr/all/pool-access.yaml | 9 + .../rados/thrash-erasure-code-big/ceph.yaml | 1 + .../d-require-luminous | 1 + .../thrashers/default.yaml | 6 +- .../thrashers/fastread.yaml | 6 +- .../thrashers/mapgap.yaml | 10 +- .../thrashers/morepggrow.yaml | 6 +- .../thrashers/pggrow.yaml | 6 +- .../d-require-luminous | 1 + .../thrash-erasure-code-overwrites/ceph.yaml | 1 + .../d-require-luminous | 1 + .../rados/thrash-erasure-code-shec/ceph.yaml | 1 + .../d-require-luminous | 1 + .../thrashers/default.yaml | 6 +- .../overrides/+ => rados/thrash-luminous/%} | 0 .../thrash-luminous/0-size-min-size-overrides | 1 + .../rados/thrash-luminous/1-pg-log-overrides | 1 + ceph/qa/suites/rados/thrash-luminous/backoff | 1 + .../qa/suites/rados/thrash-luminous/ceph.yaml | 1 + ceph/qa/suites/rados/thrash-luminous/clusters | 1 + ceph/qa/suites/rados/thrash-luminous/msgr | 1 + .../suites/rados/thrash-luminous/objectstore | 1 + .../suites/rados/thrash-luminous/rados.yaml | 1 + .../suites/rados/thrash-luminous/rocksdb.yaml | 1 + .../qa/suites/rados/thrash-luminous/thrashers | 1 + .../thrash-luminous/workloads/redirect.yaml | 11 + .../workloads/redirect_set_object.yaml | 9 + .../thrash/d-require-luminous/at-end.yaml | 5 +- .../rados/thrash/workloads/radosbench.yaml | 18 +- .../jewel-x-singleton/6-finish-upgrade.yaml | 4 + .../8-workload/rgw-swift.yaml | 1 - .../rbd/valgrind/validator/memcheck.yaml | 2 +- .../suites/rgw/multifs/frontend/apache.yaml | 3 - ceph/qa/suites/rgw/multifs/overrides.yaml | 1 + .../__init__.py => qa/suites/rgw/multisite/%} | 0 ceph/qa/suites/rgw/multisite/clusters.yaml | 3 + .../rgw/multisite/frontend/civetweb.yaml | 3 + ceph/qa/suites/rgw/multisite/overrides.yaml | 8 + .../rgw/multisite/realms/three-zone.yaml | 20 + .../rgw/multisite/realms/two-zonegroup.yaml | 27 + .../rgw/multisite/tasks/test_multi.yaml | 17 + ceph/qa/suites/rgw/multisite/valgrind.yaml | 13 + .../all/radosgw-admin-data-sync.yaml | 65 - .../all/radosgw-admin-multi-region.yaml | 67 - .../all/radosgw-convert-to-region.yaml | 81 - .../suites/rgw/singleton/frontend/apache.yaml | 3 - ceph/qa/suites/rgw/singleton/overrides.yaml | 1 + .../rgw/thrash/workload/rgw_s3tests.yaml | 2 + .../qa/suites/rgw/verify/frontend/apache.yaml | 3 - ceph/qa/suites/rgw/verify/overrides.yaml | 2 +- .../suites/rgw/verify/tasks/rgw_s3tests.yaml | 1 - .../verify/tasks/rgw_s3tests_multiregion.yaml | 69 - .../qa/suites/rgw/verify/tasks/rgw_swift.yaml | 1 - .../1-hammer-jewel-install/hammer-jewel.yaml | 1 + .../3-upgrade-sequence/upgrade-all.yaml | 1 + .../upgrade-osd-mds-mon.yaml | 1 + .../hammer-to-jewel.yaml | 9 +- .../hammer-to-jewel.yaml | 1 + .../hammer-jewel-x/tiering/3-upgrade.yaml | 1 + .../point-to-point-upgrade.yaml | 15 + .../7-final-workload/rgw-swift.yaml | 1 - .../kraken-x/parallel/0-cluster/start.yaml | 2 + .../stress-split/0-cluster/start.yaml | 3 + .../7-final-workload/rgw-swift.yaml | 1 - ceph/qa/tasks/apache.conf.template | 48 - ceph/qa/tasks/ceph.py | 29 +- ceph/qa/tasks/ceph_manager.py | 79 +- ceph/qa/tasks/cephfs/cephfs_test_case.py | 7 +- ceph/qa/tasks/cephfs/filesystem.py | 9 +- ceph/qa/tasks/cephfs/mount.py | 52 +- ceph/qa/tasks/cephfs/test_client_recovery.py | 46 +- ceph/qa/tasks/cephfs/test_exports.py | 29 +- ceph/qa/tasks/cephfs/test_fragment.py | 2 +- .../qa/tasks/cephfs/test_journal_migration.py | 41 +- ceph/qa/tasks/cephfs/test_journal_repair.py | 47 +- ceph/qa/tasks/cephfs/test_misc.py | 7 +- ceph/qa/tasks/cephfs/test_strays.py | 130 +- ceph/qa/tasks/cephfs/test_volume_client.py | 23 +- ceph/qa/tasks/divergent_priors.py | 4 +- ceph/qa/tasks/divergent_priors2.py | 4 +- ceph/qa/tasks/dnsmasq.py | 102 + ceph/qa/tasks/dump_stuck.py | 11 +- ceph/qa/tasks/ec_lost_unfound.py | 15 +- ceph/qa/tasks/lost_unfound.py | 15 +- ceph/qa/tasks/mod_fastcgi.conf.template | 17 - .../qa/tasks/mod_proxy_fcgi.tcp.conf.template | 16 - .../qa/tasks/mod_proxy_fcgi.uds.conf.template | 14 - ceph/qa/tasks/object_source_down.py | 9 +- ceph/qa/tasks/osd_backfill.py | 13 +- ceph/qa/tasks/osd_recovery.py | 29 +- ceph/qa/tasks/peer.py | 17 +- ceph/qa/tasks/rados.py | 2 + ceph/qa/tasks/radosgw_admin.py | 397 +- ceph/qa/tasks/radosgw_agent.py | 212 - ceph/qa/tasks/rebuild_mondb.py | 109 +- ceph/qa/tasks/reg11184.py | 4 +- ceph/qa/tasks/rep_lost_unfound_delete.py | 19 +- ceph/qa/tasks/repair_test.py | 3 + ceph/qa/tasks/resolve_stuck_peering.py | 2 + ceph/qa/tasks/rgw.py | 1179 +- ceph/qa/tasks/rgw_multi | 1 + ceph/qa/tasks/rgw_multisite.py | 427 + ceph/qa/tasks/rgw_multisite_tests.py | 91 + ceph/qa/tasks/s3tests.py | 123 +- ceph/qa/tasks/scrub_test.py | 3 +- ceph/qa/tasks/thrashosds.py | 2 + ceph/qa/tasks/util/rgw.py | 253 +- .../workunits/ceph-disk/ceph-disk-no-lockbox | 10 + ceph/qa/workunits/ceph-disk/ceph-disk-test.py | 23 +- ceph/qa/workunits/ceph-helpers.sh | 129 +- ceph/qa/workunits/cephtool/test.sh | 420 +- ceph/qa/workunits/mon/crush_ops.sh | 2 +- .../workunits/rados/test_health_warnings.sh | 60 + ceph/qa/workunits/rados/test_pool_access.sh | 23 + ceph/qa/workunits/rbd/krbd_data_pool.sh | 41 +- ceph/qa/workunits/rbd/krbd_fallocate.sh | 124 + ceph/qa/workunits/rbd/rbd-nbd.sh | 40 +- ceph/qa/workunits/rbd/rbd_mirror.sh | 4 + ceph/qa/workunits/rbd/test_librbd.sh | 4 +- ceph/qa/workunits/rbd/test_librbd_python.sh | 3 +- ceph/qa/workunits/rbd/test_rbd_mirror.sh | 4 +- ceph/qa/workunits/rest/test-restful.sh | 16 + ceph/qa/workunits/rest/test.py | 6 +- ceph/qa/workunits/rest/test_mgr_rest_api.py | 94 + ceph/qa/workunits/rgw/run-s3tests.sh | 12 +- ceph/run-make-check.sh | 5 +- ceph/selinux/ceph.fc | 1 + ceph/selinux/ceph.te | 2 +- ceph/src/.git_version | 4 +- ceph/src/CMakeLists.txt | 116 +- ceph/src/auth/AuthServiceHandler.h | 7 +- ceph/src/ceph-create-keys | 13 + .../ceph_detect_init/__init__.py | 18 +- .../ceph_detect_init/debian/__init__.py | 22 +- ceph/src/ceph-detect-init/tests/test_all.py | 77 +- ceph/src/ceph-disk-udev | 85 - ceph/src/ceph-disk/ceph_disk/main.py | 111 +- ceph/src/ceph-disk/tests/ceph-disk.sh | 14 +- ceph/src/ceph-disk/tests/test_main.py | 8 + ceph/src/ceph-disk/tests/test_prepare.py | 29 +- ceph/src/ceph-disk/tox.ini | 1 + ceph/src/ceph.in | 308 +- ceph/src/ceph_mds.cc | 2 +- ceph/src/ceph_mgr.cc | 12 +- ceph/src/ceph_mon.cc | 150 +- ceph/src/ceph_osd.cc | 16 +- ceph/src/ceph_release | 3 + ceph/src/ceph_ver.h.in.cmake | 3 + ceph/src/civetweb/src/civetweb.c | 46 +- ceph/src/civetweb/test/public_server.c | 37 +- ceph/src/client/Client.cc | 180 +- ceph/src/client/Client.h | 7 +- ceph/src/client/Dentry.cc | 6 +- ceph/src/client/Inode.cc | 18 +- ceph/src/client/MetaRequest.h | 9 +- ceph/src/client/ObjecterWriteback.h | 5 +- ceph/src/client/SyntheticClient.cc | 3 +- ceph/src/client/SyntheticClient.h | 4 +- ceph/src/client/hypertable/CephBroker.cc | 2 +- ceph/src/client/hypertable/CephBroker.h | 5 +- ceph/src/cls/cephfs/cls_cephfs.cc | 1 - ceph/src/cls/cephfs/cls_cephfs_client.cc | 2 +- ceph/src/cls/cephfs/cls_cephfs_client.h | 5 +- ceph/src/cls/journal/cls_journal_client.cc | 2 +- ceph/src/cls/journal/cls_journal_client.h | 9 +- ceph/src/cls/journal/cls_journal_types.h | 1 - ceph/src/cls/lock/cls_lock.cc | 6 - ceph/src/cls/lock/cls_lock_client.cc | 10 +- ceph/src/cls/lock/cls_lock_client.h | 11 +- ceph/src/cls/lock/cls_lock_ops.cc | 2 - ceph/src/cls/lock/cls_lock_types.cc | 2 - ceph/src/cls/log/cls_log.cc | 6 - ceph/src/cls/log/cls_log_client.cc | 1 - ceph/src/cls/log/cls_log_client.h | 8 +- ceph/src/cls/log/cls_log_ops.h | 1 - ceph/src/cls/lua/cls_lua_client.cc | 5 +- ceph/src/cls/lua/cls_lua_client.h | 8 +- ceph/src/cls/lua/cls_lua_ops.h | 4 +- ceph/src/cls/numops/cls_numops.cc | 2 - ceph/src/cls/numops/cls_numops_client.cc | 3 +- ceph/src/cls/numops/cls_numops_client.h | 6 +- ceph/src/cls/rbd/cls_rbd.cc | 40 +- ceph/src/cls/rbd/cls_rbd_client.cc | 36 +- ceph/src/cls/rbd/cls_rbd_client.h | 14 +- ceph/src/cls/refcount/cls_refcount.cc | 8 - ceph/src/cls/refcount/cls_refcount_client.cc | 2 +- ceph/src/cls/refcount/cls_refcount_client.h | 6 +- ceph/src/cls/refcount/cls_refcount_ops.h | 2 - ceph/src/cls/replica_log/cls_replica_log.cc | 1 - .../cls/replica_log/cls_replica_log_client.cc | 2 +- .../cls/replica_log/cls_replica_log_client.h | 8 +- .../src/cls/replica_log/cls_replica_log_ops.h | 1 - ceph/src/cls/rgw/cls_rgw.cc | 309 +- ceph/src/cls/rgw/cls_rgw_client.cc | 176 +- ceph/src/cls/rgw/cls_rgw_client.h | 50 +- ceph/src/cls/rgw/cls_rgw_ops.cc | 137 + ceph/src/cls/rgw/cls_rgw_ops.h | 280 +- ceph/src/cls/rgw/cls_rgw_types.cc | 55 +- ceph/src/cls/rgw/cls_rgw_types.h | 128 +- ceph/src/cls/statelog/cls_statelog.cc | 8 - ceph/src/cls/statelog/cls_statelog_client.cc | 3 +- ceph/src/cls/statelog/cls_statelog_client.h | 10 +- ceph/src/cls/statelog/cls_statelog_ops.h | 1 - ceph/src/cls/timeindex/cls_timeindex.cc | 8 - .../src/cls/timeindex/cls_timeindex_client.cc | 2 - ceph/src/cls/timeindex/cls_timeindex_client.h | 11 +- ceph/src/cls/timeindex/cls_timeindex_ops.h | 1 - ceph/src/cls/user/cls_user.cc | 6 - ceph/src/cls/user/cls_user_client.cc | 2 - ceph/src/cls/user/cls_user_client.h | 10 +- ceph/src/cls/user/cls_user_ops.cc | 1 - ceph/src/cls/user/cls_user_ops.h | 2 - ceph/src/cls/user/cls_user_types.cc | 1 + ceph/src/cls/version/cls_version.cc | 10 +- ceph/src/cls/version/cls_version_client.cc | 3 +- ceph/src/cls/version/cls_version_client.h | 10 +- ceph/src/cls/version/cls_version_ops.h | 3 - ceph/src/common/AsyncOpTracker.cc | 1 - ceph/src/common/AsyncOpTracker.h | 1 - ceph/src/common/AsyncReserver.h | 5 - ceph/src/common/BackTrace.cc | 3 - ceph/src/common/Checksummer.h | 1 - ceph/src/common/Clock.cc | 5 - ceph/src/common/Cond.h | 8 - ceph/src/common/ConfUtils.cc | 6 - ceph/src/common/ContextCompletion.h | 1 - ceph/src/common/Continuation.h | 1 - ceph/src/common/Cycles.cc | 6 - ceph/src/common/DecayCounter.h | 2 - ceph/src/common/EventTrace.cc | 4 - ceph/src/common/EventTrace.h | 2 - ceph/src/common/Finisher.cc | 2 - ceph/src/common/Finisher.h | 2 - ceph/src/common/Formatter.cc | 9 - ceph/src/common/Formatter.h | 7 +- ceph/src/common/Graylog.cc | 7 - ceph/src/common/Graylog.h | 3 - ceph/src/common/HTMLFormatter.cc | 2 +- ceph/src/common/HTMLFormatter.h | 4 - ceph/src/common/HeartbeatMap.cc | 31 +- ceph/src/common/HeartbeatMap.h | 14 +- ceph/src/common/LogClient.cc | 28 +- ceph/src/common/LogClient.h | 6 +- ceph/src/common/LogEntry.cc | 17 +- ceph/src/common/LogEntry.h | 60 +- ceph/src/common/MemoryModel.cc | 6 +- ceph/src/common/Mutex.cc | 4 - ceph/src/common/OutputDataSocket.cc | 23 +- ceph/src/common/OutputDataSocket.h | 7 - ceph/src/common/PluginRegistry.cc | 8 +- ceph/src/common/PluginRegistry.h | 3 - ceph/src/common/PrebufferedStreambuf.h | 1 - ceph/src/common/Preforker.h | 5 - ceph/src/common/PrioritizedQueue.h | 3 - ceph/src/common/QueueRing.h | 16 +- ceph/src/common/RWLock.h | 27 +- ceph/src/common/RefCountedObj.h | 25 +- ceph/src/common/SloppyCRCMap.h | 4 - ceph/src/common/SubProcess.h | 14 +- ceph/src/common/TextTable.h | 2 - ceph/src/common/Thread.cc | 10 - ceph/src/common/Throttle.cc | 54 +- ceph/src/common/Throttle.h | 22 +- ceph/src/common/Timer.cc | 8 - ceph/src/common/Timer.h | 3 - ceph/src/common/TracepointProvider.h | 5 - ceph/src/common/TrackedOp.cc | 9 +- ceph/src/common/TrackedOp.h | 11 +- ceph/src/common/WorkQueue.cc | 41 +- ceph/src/common/WorkQueue.h | 13 +- ceph/src/common/addr_parsing.c | 1 - ceph/src/common/address_helper.cc | 13 +- ceph/src/common/admin_socket.cc | 30 +- ceph/src/common/admin_socket.h | 7 - ceph/src/common/admin_socket_client.cc | 19 - ceph/src/common/admin_socket_client.h | 1 - ceph/src/common/aix_errno.cc | 8 +- ceph/src/common/assert.cc | 11 - ceph/src/common/backport14.h | 84 + ceph/src/common/bit_str.cc | 1 - ceph/src/common/bit_str.h | 2 - ceph/src/common/bit_vector.hpp | 6 - ceph/src/common/blkdev.cc | 10 +- ceph/src/common/bloom_filter.cc | 2 - ceph/src/common/bloom_filter.hpp | 6 - ceph/src/common/buffer.cc | 276 +- ceph/src/common/ceph_argparse.cc | 13 - ceph/src/common/ceph_argparse.h | 3 - ceph/src/common/ceph_context.cc | 59 +- ceph/src/common/ceph_context.h | 19 +- ceph/src/common/ceph_crypto.cc | 7 - ceph/src/common/ceph_crypto_cms.cc | 17 +- ceph/src/common/ceph_json.cc | 6 +- ceph/src/common/ceph_json.h | 13 +- ceph/src/common/ceph_strings.cc | 153 +- ceph/src/common/ceph_time.cc | 1 - ceph/src/common/ceph_time.h | 1 - ceph/src/common/ceph_timer.h | 5 - ceph/src/common/cmdparse.cc | 50 +- ceph/src/common/cmdparse.h | 19 +- ceph/src/common/code_environment.cc | 25 +- ceph/src/common/code_environment.h | 4 +- ceph/src/common/cohort_lru.h | 10 +- ceph/src/common/common_init.cc | 13 - ceph/src/common/common_init.h | 3 - ceph/src/common/config.cc | 49 +- ceph/src/common/config.h | 24 +- ceph/src/common/config_opts.h | 100 +- ceph/src/common/config_validators.cc | 26 +- ceph/src/common/config_validators.h | 4 + ceph/src/common/crc32c.cc | 188 +- ceph/src/common/crc32c_aarch64.h | 1 + ceph/src/common/crc32c_intel_fast.c | 6 +- ...tel_fast_asm.S => crc32c_intel_fast_asm.s} | 0 ...ero_asm.S => crc32c_intel_fast_zero_asm.s} | 0 ceph/src/common/crc32c_ppc.c | 55 +- ceph/src/common/crc32c_ppc_constants.h | 71 + ceph/src/common/crc32c_ppc_fast_zero_asm.S | 77 + ceph/src/common/darwin_errno.cc | 11 +- ceph/src/common/deleter.h | 5 - ceph/src/common/dns_resolve.cc | 8 - ceph/src/common/dns_resolve.h | 3 - ceph/src/common/dout.h | 6 - ceph/src/common/entity_name.cc | 13 +- ceph/src/common/entity_name.h | 6 +- ceph/src/common/errno.cc | 2 - ceph/src/common/event_socket.h | 4 +- ceph/src/common/fd.cc | 7 - ceph/src/common/freebsd_errno.cc | 219 + ceph/src/common/function_signature.h | 3 - ceph/src/common/hex.cc | 4 - ceph/src/common/histogram.h | 5 +- ceph/src/common/hobject.cc | 1 - ceph/src/common/hobject.h | 25 +- ceph/src/common/hostname.cc | 1 - ceph/src/common/inline_variant.h | 19 - ceph/src/common/interval_map.h | 5 - ceph/src/common/io_priority.cc | 4 +- ceph/src/common/ipaddr.cc | 9 +- ceph/src/common/iso_8601.cc | 200 + ceph/src/common/iso_8601.h | 43 + ceph/src/common/lockdep.cc | 8 +- ceph/src/common/lru_map.h | 3 - ceph/src/common/map_cacher.hpp | 10 - ceph/src/common/mempool.cc | 20 +- ceph/src/common/module.c | 3 +- ceph/src/common/mutex_debug.cc | 6 - ceph/src/common/obj_bencher.cc | 10 - ceph/src/common/obj_bencher.h | 2 - ceph/src/common/perf_counters.cc | 105 +- ceph/src/common/perf_counters.h | 70 +- ceph/src/common/perf_histogram.h | 26 +- ceph/src/common/pick_address.cc | 6 +- ceph/src/common/pipe.c | 5 - ceph/src/common/reverse.c | 42 + ceph/src/common/reverse.h | 31 + ceph/src/common/run_cmd.cc | 2 - ceph/src/common/safe_io.c | 6 +- ceph/src/common/safe_io.h | 1 - ceph/src/common/scrub_types.h | 3 - ceph/src/common/secret.c | 2 - ceph/src/common/shared_cache.hpp | 5 +- ceph/src/common/simple_cache.hpp | 4 - ceph/src/common/solaris_errno.cc | 10 +- ceph/src/common/sstring.hh | 74 +- ceph/src/common/str_map.cc | 2 - ceph/src/common/strtol.cc | 2 - ceph/src/common/tracked_int_ptr.hpp | 25 +- ceph/src/common/util.cc | 2 - ceph/src/common/version.cc | 20 +- ceph/src/common/version.h | 7 + ceph/src/common/xattr.h | 2 - ceph/src/common/zipkin_trace.h | 2 +- ceph/src/compressor/AsyncCompressor.cc | 30 +- ceph/src/compressor/AsyncCompressor.h | 29 +- ceph/src/compressor/CMakeLists.txt | 23 +- ceph/src/compressor/CompressionPlugin.h | 3 +- ceph/src/compressor/Compressor.cc | 9 +- ceph/src/compressor/Compressor.h | 15 +- ceph/src/compressor/lz4/CMakeLists.txt | 19 + .../compressor/lz4/CompressionPluginLZ4.cc | 39 + .../src/compressor/lz4/CompressionPluginLZ4.h | 41 + ceph/src/compressor/lz4/LZ4Compressor.h | 114 + .../snappy/CompressionPluginSnappy.cc | 2 +- ceph/src/compressor/snappy/SnappyCompressor.h | 2 +- ceph/src/crush/CrushCompiler.cc | 9 - ceph/src/crush/CrushCompiler.h | 3 +- ceph/src/crush/CrushLocation.cc | 2 +- ceph/src/crush/CrushTester.cc | 2 +- ceph/src/crush/CrushTester.h | 1 - ceph/src/crush/CrushTreeDumper.h | 31 +- ceph/src/crush/CrushWrapper.cc | 499 +- ceph/src/crush/CrushWrapper.h | 106 +- ceph/src/crush/builder.c | 5 +- ceph/src/crush/builder.h | 7 +- ceph/src/crush/crush.h | 18 + ceph/src/dmclock/CMakeLists.txt | 31 +- ...EADME.before-modifying-files-here-or-below | 29 + .../src/dmclock/cmake/modules/Findboost.cmake | 15 - .../src/dmclock/cmake/modules/Findgtest.cmake | 48 - ceph/src/dmclock/sim/CMakeLists.txt | 8 + ceph/src/dmclock/sim/src/sim_server.h | 2 + ceph/src/dmclock/sim/src/simulate.h | 11 + ceph/src/dmclock/sim/src/test_dmclock_main.cc | 2 + ceph/src/dmclock/src/CMakeLists.txt | 9 +- ceph/src/dmclock/src/dmclock_server.h | 54 +- ceph/src/dmclock/support/CMakeLists.txt | 1 - .../support/src/indirect_intrusive_heap.h | 2 +- ceph/src/dmclock/support/src/run_every.cc | 17 +- ceph/src/dmclock/support/src/run_every.h | 4 +- ceph/src/dmclock/support/test/CMakeLists.txt | 3 - ceph/src/dmclock/test/CMakeLists.txt | 6 +- ceph/src/dmclock/test/test_test_client.cc | 4 + ceph/src/erasure-code/ErasureCode.cc | 7 +- ceph/src/erasure-code/ErasureCode.h | 56 +- ceph/src/erasure-code/ErasureCodeInterface.h | 55 +- ceph/src/erasure-code/ErasureCodePlugin.cc | 2 + ceph/src/erasure-code/ErasureCodePlugin.h | 8 +- ceph/src/erasure-code/isa/CMakeLists.txt | 96 +- ceph/src/erasure-code/isa/ErasureCodeIsa.cc | 16 +- ceph/src/erasure-code/isa/ErasureCodeIsa.h | 27 +- .../isa/ErasureCodeIsaTableCache.cc | 1 - .../erasure-code/isa/ErasureCodePluginIsa.cc | 6 +- .../erasure-code/isa/ErasureCodePluginIsa.h | 2 +- .../isa/isa-l/erasure_code/ec_base.c | 348 - .../isa/isa-l/erasure_code/ec_base.h | 6680 ------- .../isa-l/erasure_code/ec_highlevel_func.c | 267 - .../isa-l/erasure_code/ec_multibinary.asm.s | 395 - .../erasure_code/gf_2vect_dot_prod_avx.asm.s | 337 - .../erasure_code/gf_2vect_dot_prod_avx2.asm.s | 356 - .../erasure_code/gf_2vect_dot_prod_sse.asm.s | 339 - .../isa-l/erasure_code/gf_2vect_mad_avx.asm.s | 236 - .../erasure_code/gf_2vect_mad_avx2.asm.s | 247 - .../isa-l/erasure_code/gf_2vect_mad_sse.asm.s | 239 - .../erasure_code/gf_3vect_dot_prod_avx.asm.s | 377 - .../erasure_code/gf_3vect_dot_prod_avx2.asm.s | 397 - .../erasure_code/gf_3vect_dot_prod_sse.asm.s | 378 - .../isa-l/erasure_code/gf_3vect_mad_avx.asm.s | 288 - .../erasure_code/gf_3vect_mad_avx2.asm.s | 317 - .../isa-l/erasure_code/gf_3vect_mad_sse.asm.s | 298 - .../erasure_code/gf_4vect_dot_prod_avx.asm.s | 441 - .../erasure_code/gf_4vect_dot_prod_avx2.asm.s | 460 - .../erasure_code/gf_4vect_dot_prod_sse.asm.s | 443 - .../isa-l/erasure_code/gf_4vect_mad_avx.asm.s | 336 - .../erasure_code/gf_4vect_mad_avx2.asm.s | 342 - .../isa-l/erasure_code/gf_4vect_mad_sse.asm.s | 342 - .../erasure_code/gf_5vect_dot_prod_avx.asm.s | 303 - .../erasure_code/gf_5vect_dot_prod_avx2.asm.s | 315 - .../erasure_code/gf_5vect_dot_prod_sse.asm.s | 304 - .../isa-l/erasure_code/gf_5vect_mad_avx.asm.s | 365 - .../erasure_code/gf_5vect_mad_avx2.asm.s | 363 - .../isa-l/erasure_code/gf_5vect_mad_sse.asm.s | 373 - .../erasure_code/gf_6vect_dot_prod_avx.asm.s | 315 - .../erasure_code/gf_6vect_dot_prod_avx2.asm.s | 326 - .../erasure_code/gf_6vect_dot_prod_sse.asm.s | 315 - .../isa-l/erasure_code/gf_6vect_mad_avx.asm.s | 394 - .../erasure_code/gf_6vect_mad_avx2.asm.s | 400 - .../isa-l/erasure_code/gf_6vect_mad_sse.asm.s | 406 - .../erasure_code/gf_vect_dot_prod_avx.asm.s | 271 - .../erasure_code/gf_vect_dot_prod_avx2.asm.s | 280 - .../erasure_code/gf_vect_dot_prod_sse.asm.s | 271 - .../isa-l/erasure_code/gf_vect_mad_avx.asm.s | 196 - .../isa-l/erasure_code/gf_vect_mad_avx2.asm.s | 203 - .../isa-l/erasure_code/gf_vect_mad_sse.asm.s | 197 - .../isa-l/erasure_code/gf_vect_mul_avx.asm.s | 164 - .../isa-l/erasure_code/gf_vect_mul_sse.asm.s | 170 - .../isa/isa-l/include/erasure_code.h | 933 - .../isa/isa-l/include/gf_vect_mul.h | 148 - .../isa/isa-l/include/reg_sizes.asm | 123 - .../erasure-code/isa/isa-l/include/types.h | 88 - ceph/src/erasure-code/isa/xor_op.cc | 1 + ceph/src/erasure-code/isa/xor_op.h | 1 - .../jerasure/ErasureCodeJerasure.cc | 8 +- .../jerasure/ErasureCodeJerasure.h | 44 +- .../jerasure/ErasureCodePluginJerasure.cc | 2 +- ceph/src/erasure-code/lrc/ErasureCodeLrc.cc | 2 + ceph/src/erasure-code/lrc/ErasureCodeLrc.h | 76 +- .../erasure-code/lrc/ErasureCodePluginLrc.cc | 5 +- .../shec/ErasureCodePluginShec.cc | 2 +- ceph/src/erasure-code/shec/ErasureCodeShec.cc | 11 +- ceph/src/erasure-code/shec/ErasureCodeShec.h | 2 - .../shec/ErasureCodeShecTableCache.cc | 2 +- ceph/src/fetch_config | 20 - ceph/src/include/atomic.h | 157 - ceph/src/include/buffer.h | 32 +- ceph/src/include/ceph_features.h | 4 +- ceph/src/include/ceph_fs.h | 3 +- ceph/src/include/config-h.in.cmake | 22 +- ceph/src/include/cpp-btree/btree_set.h | 121 + ceph/src/include/crc32c.h | 28 +- ceph/src/include/denc.h | 336 +- ceph/src/include/encoding.h | 4 + ceph/src/include/frag.h | 2 +- ceph/src/include/fs_types.h | 4 +- ceph/src/include/inline_memory.h | 9 + ceph/src/include/int_types.h | 55 +- ceph/src/include/interval_set.h | 31 +- ceph/src/include/ipaddr.h | 4 - ceph/src/include/lru.h | 14 +- ceph/src/include/mempool.h | 43 +- ceph/src/include/object.h | 3 +- ceph/src/include/rados.h | 85 +- ceph/src/include/rados/librados.h | 35 +- ceph/src/include/rados/librados.hpp | 9 + ceph/src/include/rados/objclass.h | 14 +- ceph/src/include/rbd/librbd.h | 4 + ceph/src/include/rbd/librbd.hpp | 2 + ceph/src/include/types.h | 38 +- ceph/src/journal/JournalRecorder.cc | 6 +- ceph/src/journal/JournalRecorder.h | 1 - ceph/src/json_spirit/json_spirit_value.h | 1 - ceph/src/kv/KeyValueDB.h | 4 + ceph/src/kv/LevelDBStore.cc | 10 +- ceph/src/kv/LevelDBStore.h | 3 + ceph/src/kv/RocksDBStore.cc | 89 +- ceph/src/kv/RocksDBStore.h | 6 + ceph/src/librados/IoCtxImpl.cc | 16 +- ceph/src/librados/IoCtxImpl.h | 9 +- ceph/src/librados/RadosClient.cc | 37 +- ceph/src/librados/RadosClient.h | 4 +- ceph/src/librados/RadosXattrIter.h | 2 +- ceph/src/librados/librados.cc | 23 +- ceph/src/libradosstriper/RadosStriperImpl.h | 2 - ceph/src/librbd/CMakeLists.txt | 2 +- ceph/src/librbd/ExclusiveLock.cc | 48 +- ceph/src/librbd/ExclusiveLock.h | 12 +- ceph/src/librbd/ImageCtx.cc | 35 +- ceph/src/librbd/ImageCtx.h | 18 +- ceph/src/librbd/ImageWatcher.cc | 52 +- ceph/src/librbd/ImageWatcher.h | 23 +- ceph/src/librbd/Journal.cc | 8 +- ceph/src/librbd/LibrbdWriteback.cc | 50 +- ceph/src/librbd/LibrbdWriteback.h | 4 +- ceph/src/librbd/ManagedLock.cc | 20 +- ceph/src/librbd/ManagedLock.h | 1 + ceph/src/librbd/ObjectMap.cc | 16 +- ceph/src/librbd/ObjectMap.h | 23 +- ceph/src/librbd/Operations.cc | 7 +- ceph/src/librbd/Utils.h | 11 + ceph/src/librbd/Watcher.cc | 41 +- ceph/src/librbd/Watcher.h | 10 +- ceph/src/librbd/api/Group.cc | 8 +- ceph/src/librbd/cache/ImageWriteback.cc | 13 +- .../exclusive_lock/PreReleaseRequest.cc | 36 +- .../librbd/exclusive_lock/PreReleaseRequest.h | 19 +- ceph/src/librbd/image/CloseRequest.cc | 73 +- ceph/src/librbd/image/CloseRequest.h | 25 +- ceph/src/librbd/image/OpenRequest.cc | 39 + ceph/src/librbd/image/OpenRequest.h | 6 + ceph/src/librbd/image/RemoveRequest.cc | 410 +- ceph/src/librbd/image/RemoveRequest.h | 52 +- ceph/src/librbd/internal.cc | 71 +- ceph/src/librbd/io/AioCompletion.h | 2 +- ceph/src/librbd/{ => io}/AsyncOperation.cc | 7 +- ceph/src/librbd/{ => io}/AsyncOperation.h | 10 +- ceph/src/librbd/io/CopyupRequest.cc | 36 +- ceph/src/librbd/io/CopyupRequest.h | 9 +- ceph/src/librbd/io/ImageRequest.cc | 74 +- ceph/src/librbd/io/ImageRequest.h | 64 +- ceph/src/librbd/io/ImageRequestWQ.cc | 68 +- ceph/src/librbd/io/ObjectRequest.cc | 118 +- ceph/src/librbd/io/ObjectRequest.h | 122 +- ceph/src/librbd/journal/Replay.cc | 90 +- ceph/src/librbd/journal/Replay.h | 1 + ceph/src/librbd/librbd.cc | 36 +- .../src/librbd/managed_lock/AcquireRequest.cc | 7 +- ceph/src/librbd/managed_lock/AcquireRequest.h | 20 +- ceph/src/librbd/managed_lock/BreakRequest.cc | 42 +- ceph/src/librbd/managed_lock/BreakRequest.h | 22 +- ceph/src/librbd/object_map/Request.cc | 4 +- ceph/src/librbd/object_map/UpdateRequest.cc | 5 +- ceph/src/librbd/object_map/UpdateRequest.h | 15 +- ceph/src/librbd/operation/FlattenRequest.cc | 2 +- ceph/src/librbd/operation/TrimRequest.cc | 14 +- ceph/src/mds/CDentry.cc | 4 +- ceph/src/mds/CDentry.h | 4 +- ceph/src/mds/CDir.cc | 104 +- ceph/src/mds/CDir.h | 5 +- ceph/src/mds/CInode.cc | 100 +- ceph/src/mds/CInode.h | 5 +- ceph/src/mds/CMakeLists.txt | 3 +- ceph/src/mds/FSMap.cc | 22 +- ceph/src/mds/FSMap.h | 2 +- ceph/src/mds/Locker.cc | 41 +- ceph/src/mds/Locker.h | 2 + ceph/src/mds/MDBalancer.cc | 92 +- ceph/src/mds/MDBalancer.h | 2 - ceph/src/mds/MDCache.cc | 412 +- ceph/src/mds/MDCache.h | 63 +- ceph/src/mds/MDLog.cc | 6 +- ceph/src/mds/MDSCacheObject.h | 6 +- ceph/src/mds/MDSDaemon.cc | 10 +- ceph/src/mds/MDSDaemon.h | 2 +- ceph/src/mds/MDSMap.cc | 12 +- ceph/src/mds/MDSMap.h | 15 +- ceph/src/mds/MDSRank.cc | 171 +- ceph/src/mds/MDSRank.h | 6 +- ceph/src/mds/Migrator.cc | 47 +- ceph/src/mds/PurgeQueue.cc | 24 +- ceph/src/mds/RecoveryQueue.cc | 1 - ceph/src/mds/Server.cc | 176 +- ceph/src/mds/Server.h | 5 +- ceph/src/mds/SessionMap.cc | 4 + ceph/src/mds/SnapServer.cc | 8 +- ceph/src/mds/StrayManager.cc | 88 +- ceph/src/mds/StrayManager.h | 13 +- ceph/src/mds/events/EExport.h | 10 +- ceph/src/mds/events/EImportStart.h | 16 +- ceph/src/mds/flock.cc | 56 +- ceph/src/mds/flock.h | 10 - ceph/src/mds/journal.cc | 48 +- ceph/src/messages/MClientCaps.h | 1 + ceph/src/messages/MClientReply.h | 2 +- ceph/src/messages/MMDSResolve.h | 2 +- ceph/src/messages/MMDSSlaveRequest.h | 8 +- ceph/src/messages/MMonMgrReport.h | 67 + ceph/src/messages/MMonPaxos.h | 8 +- ceph/src/messages/MOSDPGUpdateLogMissing.h | 4 +- ceph/src/messages/MOSDPing.h | 47 +- ceph/src/mgr/ClusterState.cc | 70 +- ceph/src/mgr/ClusterState.h | 15 + ceph/src/mgr/DaemonServer.cc | 191 +- ceph/src/mgr/DaemonServer.h | 7 +- ceph/src/mgr/DaemonState.cc | 34 +- ceph/src/mgr/DaemonState.h | 4 +- ceph/src/mgr/Gil.h | 96 + ceph/src/mgr/Mgr.cc | 18 +- ceph/src/mgr/Mgr.h | 2 + ceph/src/mgr/MgrClient.cc | 21 +- ceph/src/mgr/MgrClient.h | 1 + ceph/src/mgr/MgrCommands.h | 13 + ceph/src/mgr/MgrPyModule.cc | 145 +- ceph/src/mgr/MgrPyModule.h | 4 +- ceph/src/mgr/MgrSession.h | 2 + ceph/src/mgr/MgrStandby.cc | 93 +- ceph/src/mgr/MgrStandby.h | 12 +- ceph/src/mgr/PyFormatter.cc | 8 +- ceph/src/mgr/PyModules.cc | 131 +- ceph/src/mgr/PyModules.h | 6 +- ceph/src/mgr/PyState.cc | 92 +- ceph/src/mon/AuthMonitor.cc | 422 +- ceph/src/mon/AuthMonitor.h | 60 +- ceph/src/mon/CMakeLists.txt | 13 +- ceph/src/mon/ConfigKeyService.cc | 122 +- ceph/src/mon/ConfigKeyService.h | 14 + ceph/src/mon/CreatingPGs.h | 72 +- ceph/src/mon/FSCommands.cc | 37 +- ceph/src/mon/LogMonitor.cc | 64 +- ceph/src/mon/MDSMonitor.cc | 91 +- ceph/src/mon/MDSMonitor.h | 2 +- ceph/src/mon/MgrMap.h | 11 +- ceph/src/mon/MgrMonitor.cc | 94 +- ceph/src/mon/MgrMonitor.h | 14 +- ceph/src/mon/MgrStatMonitor.cc | 262 + ceph/src/mon/MgrStatMonitor.h | 71 + ceph/src/mon/MonCap.cc | 12 +- ceph/src/mon/MonCap.h | 2 +- ceph/src/mon/MonClient.cc | 22 +- ceph/src/mon/MonClient.h | 20 +- ceph/src/mon/MonCommands.h | 164 +- ceph/src/mon/MonOpRequest.h | 26 + ceph/src/mon/Monitor.cc | 180 +- ceph/src/mon/Monitor.h | 17 +- ceph/src/mon/MonitorDBStore.h | 11 +- ceph/src/mon/MonmapMonitor.cc | 12 +- ceph/src/mon/MonmapMonitor.h | 2 - ceph/src/mon/OSDMonitor.cc | 2939 ++- ceph/src/mon/OSDMonitor.h | 69 +- ceph/src/mon/PGMap.cc | 4131 ++-- ceph/src/mon/PGMap.h | 514 +- ceph/src/mon/PGMonitor.cc | 781 +- ceph/src/mon/PGMonitor.h | 36 +- ceph/src/mon/PGStatService.h | 130 + ceph/src/mon/Paxos.cc | 13 +- ceph/src/mon/Paxos.h | 43 +- ceph/src/mon/PaxosService.cc | 80 +- ceph/src/mon/PaxosService.h | 27 +- ceph/src/mon/Session.h | 19 +- ceph/src/mon/mon_types.h | 93 +- ceph/src/msg/DispatchQueue.h | 1 - ceph/src/msg/Message.cc | 5 + ceph/src/msg/Message.h | 2 + ceph/src/msg/async/AsyncConnection.cc | 146 +- ceph/src/msg/async/AsyncConnection.h | 12 +- ceph/src/msg/async/AsyncMessenger.cc | 2 + ceph/src/msg/async/AsyncMessenger.h | 5 +- ceph/src/msg/async/Event.cc | 5 +- ceph/src/msg/async/Event.h | 2 +- ceph/src/msg/async/PosixStack.cc | 1 - ceph/src/msg/async/Stack.cc | 6 +- ceph/src/msg/async/Stack.h | 13 +- ceph/src/msg/async/dpdk/IP.cc | 2 +- ceph/src/msg/async/dpdk/TCP.h | 4 +- ceph/src/msg/async/dpdk/ethernet.cc | 2 +- ceph/src/msg/async/dpdk/ethernet.h | 2 +- ceph/src/msg/async/dpdk/ip_types.h | 2 +- ceph/src/msg/async/rdma/Device.cc | 550 - ceph/src/msg/async/rdma/Device.h | 168 - ceph/src/msg/async/rdma/Infiniband.cc | 424 +- ceph/src/msg/async/rdma/Infiniband.h | 163 +- ceph/src/msg/async/rdma/RDMAConnTCP.cc | 117 - ceph/src/msg/async/rdma/RDMAConnTCP.h | 89 - .../msg/async/rdma/RDMAConnectedSocketImpl.cc | 229 +- .../msg/async/rdma/RDMAConnectedSocketImpl.h | 158 - .../msg/async/rdma/RDMAServerSocketImpl.cc | 28 +- ceph/src/msg/async/rdma/RDMAStack.cc | 181 +- ceph/src/msg/async/rdma/RDMAStack.h | 115 +- ceph/src/msg/async/rdma/ib_dbg.h | 387 - ceph/src/msg/simple/Pipe.cc | 10 +- ceph/src/msg/simple/Pipe.h | 2 +- ceph/src/msg/simple/SimpleMessenger.cc | 2 + ceph/src/msg/simple/SimpleMessenger.h | 3 +- ceph/src/msg/xio/XioConnection.cc | 16 +- ceph/src/msg/xio/XioConnection.h | 56 +- ceph/src/msg/xio/XioMessenger.cc | 42 +- ceph/src/msg/xio/XioMessenger.h | 11 +- ceph/src/msg/xio/XioMsg.h | 13 +- ceph/src/msg/xio/XioPool.h | 64 +- ceph/src/os/CMakeLists.txt | 9 + ceph/src/os/FuseStore.cc | 1 + ceph/src/os/ObjectStore.cc | 6 +- ceph/src/os/ObjectStore.h | 14 + ceph/src/os/bluestore/BitAllocator.cc | 4 +- ceph/src/os/bluestore/BitMapAllocator.cc | 11 +- ceph/src/os/bluestore/BitMapAllocator.h | 1 + ceph/src/os/bluestore/BlockDevice.cc | 27 + ceph/src/os/bluestore/BlockDevice.h | 26 +- ceph/src/os/bluestore/BlueFS.cc | 13 +- ceph/src/os/bluestore/BlueRocksEnv.cc | 10 - ceph/src/os/bluestore/BlueStore.cc | 1305 +- ceph/src/os/bluestore/BlueStore.h | 253 +- ceph/src/os/bluestore/KernelDevice.cc | 26 +- ceph/src/os/bluestore/NVMEDevice.cc | 12 +- ceph/src/os/bluestore/NVMEDevice.h | 1 - ceph/src/os/bluestore/PMEMDevice.cc | 305 + ceph/src/os/bluestore/PMEMDevice.h | 74 + ceph/src/os/bluestore/bluefs_types.cc | 2 +- ceph/src/os/bluestore/bluefs_types.h | 2 +- ceph/src/os/bluestore/bluestore_tool.cc | 2 +- ceph/src/os/bluestore/bluestore_types.cc | 41 +- ceph/src/os/bluestore/bluestore_types.h | 61 +- ceph/src/os/filestore/FileJournal.h | 3 + ceph/src/os/filestore/FileStore.cc | 585 +- ceph/src/os/filestore/FileStore.h | 13 +- .../os/filestore/GenericFileStoreBackend.cc | 26 +- .../os/filestore/GenericFileStoreBackend.h | 4 + ceph/src/os/filestore/ZFSFileStoreBackend.h | 3 + ceph/src/os/filestore/chain_xattr.cc | 24 +- ceph/src/os/filestore/chain_xattr.h | 8 +- ceph/src/os/fs/aio.h | 9 +- ceph/src/osd/CMakeLists.txt | 15 +- ceph/src/osd/ECBackend.cc | 4 +- ceph/src/osd/ECTransaction.cc | 8 +- ceph/src/osd/ECTransaction.h | 18 +- ceph/src/osd/ECUtil.cc | 1 + ceph/src/osd/ECUtil.h | 38 +- ceph/src/osd/OSD.cc | 342 +- ceph/src/osd/OSD.h | 79 +- ceph/src/osd/OSDCap.cc | 2 +- ceph/src/osd/OSDCap.h | 2 +- ceph/src/osd/OSDMap.cc | 903 +- ceph/src/osd/OSDMap.h | 418 +- ceph/src/osd/PG.cc | 131 +- ceph/src/osd/PG.h | 17 +- ceph/src/osd/PGBackend.cc | 62 +- ceph/src/osd/PGLog.cc | 2 +- ceph/src/osd/PGLog.h | 74 +- ceph/src/osd/PrimaryLogPG.cc | 283 +- ceph/src/osd/PrimaryLogPG.h | 22 +- ceph/src/osd/ReplicatedBackend.cc | 10 +- ceph/src/osd/Session.h | 5 + ceph/src/osd/SnapMapper.cc | 28 + ceph/src/osd/osd_types.cc | 122 +- ceph/src/osd/osd_types.h | 129 +- ceph/src/osdc/Journaler.cc | 48 +- ceph/src/osdc/ObjectCacher.cc | 188 +- ceph/src/osdc/ObjectCacher.h | 32 +- ceph/src/osdc/Objecter.cc | 203 +- ceph/src/osdc/Objecter.h | 126 +- ceph/src/osdc/WritebackHandler.h | 7 +- ceph/src/perf_histogram.h | 227 + ceph/src/pybind/ceph_argparse.py | 10 +- ceph/src/pybind/ceph_daemon.py | 35 +- ceph/src/pybind/ceph_rest_api.py | 21 +- ceph/src/pybind/mgr/dashboard/HACKING.rst | 95 + ceph/src/pybind/mgr/dashboard/README.rst | 72 + .../mgr/{rest => dashboard}/__init__.py | 1 - ceph/src/pybind/mgr/dashboard/base.html | 292 + .../pybind/mgr/dashboard/cephfs_clients.py | 25 + ceph/src/pybind/mgr/dashboard/clients.html | 66 + ceph/src/pybind/mgr/dashboard/filesystem.html | 290 + ceph/src/pybind/mgr/dashboard/health.html | 234 + ceph/src/pybind/mgr/dashboard/module.py | 760 + ceph/src/pybind/mgr/dashboard/osd_perf.html | 188 + ceph/src/pybind/mgr/dashboard/rbd.html | 64 + ceph/src/pybind/mgr/dashboard/rbd_ls.py | 38 + .../pybind/mgr/dashboard/remote_view_cache.py | 135 + ceph/src/pybind/mgr/dashboard/servers.html | 84 + .../dashboard/static/AdminLTE-2.3.7/.jshintrc | 17 + .../static/AdminLTE-2.3.7/Gruntfile.js | 172 + .../dashboard/static/AdminLTE-2.3.7/LICENSE | 20 + .../dashboard/static/AdminLTE-2.3.7/README.md | 123 + .../bootstrap/css/bootstrap.css | 6760 +++++++ .../bootstrap/css/bootstrap.css.map | 1 + .../bootstrap/css/bootstrap.min.css | 6 + .../bootstrap/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../AdminLTE-2.3.7/bootstrap/js/bootstrap.js | 2363 +++ .../bootstrap/js/bootstrap.min.js | 7 + .../static/AdminLTE-2.3.7/bootstrap/js/npm.js | 13 + .../static/AdminLTE-2.3.7/bower.json | 33 + .../build/bootstrap-less/mixins.less | 36 + .../build/bootstrap-less/mixins/alerts.less | 14 + .../mixins/background-variant.less | 9 + .../bootstrap-less/mixins/border-radius.less | 21 + .../build/bootstrap-less/mixins/buttons.less | 68 + .../bootstrap-less/mixins/center-block.less | 7 + .../build/bootstrap-less/mixins/clearfix.less | 22 + .../build/bootstrap-less/mixins/forms.less | 84 + .../bootstrap-less/mixins/gradients.less | 59 + .../bootstrap-less/mixins/grid-framework.less | 102 + .../build/bootstrap-less/mixins/grid.less | 134 + .../bootstrap-less/mixins/hide-text.less | 21 + .../build/bootstrap-less/mixins/image.less | 25 + .../build/bootstrap-less/mixins/labels.less | 12 + .../bootstrap-less/mixins/list-group.less | 30 + .../bootstrap-less/mixins/nav-divider.less | 10 + .../mixins/nav-vertical-align.less | 9 + .../build/bootstrap-less/mixins/opacity.less | 8 + .../bootstrap-less/mixins/pagination.less | 24 + .../build/bootstrap-less/mixins/panels.less | 24 + .../bootstrap-less/mixins/progress-bar.less | 10 + .../bootstrap-less/mixins/reset-filter.less | 8 + .../bootstrap-less/mixins/reset-text.less | 18 + .../build/bootstrap-less/mixins/resize.less | 6 + .../mixins/responsive-visibility.less | 21 + .../build/bootstrap-less/mixins/size.less | 10 + .../bootstrap-less/mixins/tab-focus.less | 9 + .../bootstrap-less/mixins/table-row.less | 28 + .../bootstrap-less/mixins/text-emphasis.less | 9 + .../bootstrap-less/mixins/text-overflow.less | 8 + .../mixins/vendor-prefixes.less | 254 + .../build/bootstrap-less/variables.less | 841 + .../AdminLTE-2.3.7/build/less/.csslintrc | 23 + .../build/less/404_500_errors.less | 36 + .../AdminLTE-2.3.7/build/less/AdminLTE.less | 61 + .../AdminLTE-2.3.7/build/less/alerts.less | 47 + .../build/less/bootstrap-social.less | 172 + .../AdminLTE-2.3.7/build/less/boxes.less | 485 + .../AdminLTE-2.3.7/build/less/buttons.less | 168 + .../AdminLTE-2.3.7/build/less/callout.less | 48 + .../AdminLTE-2.3.7/build/less/carousel.less | 18 + .../build/less/control-sidebar.less | 289 + .../AdminLTE-2.3.7/build/less/core.less | 174 + .../build/less/direct-chat.less | 194 + .../AdminLTE-2.3.7/build/less/dropdown.less | 350 + .../AdminLTE-2.3.7/build/less/forms.less | 108 + .../build/less/fullcalendar.less | 100 + .../AdminLTE-2.3.7/build/less/header.less | 248 + .../AdminLTE-2.3.7/build/less/info-box.less | 75 + .../AdminLTE-2.3.7/build/less/invoice.less | 16 + .../AdminLTE-2.3.7/build/less/labels.less | 28 + .../AdminLTE-2.3.7/build/less/lockscreen.less | 73 + .../build/less/login_and_register.less | 52 + .../AdminLTE-2.3.7/build/less/mailbox.less | 88 + .../build/less/miscellaneous.less | 606 + .../AdminLTE-2.3.7/build/less/mixins.less | 315 + .../AdminLTE-2.3.7/build/less/modal.less | 80 + .../AdminLTE-2.3.7/build/less/navs.less | 226 + .../AdminLTE-2.3.7/build/less/print.less | 54 + .../AdminLTE-2.3.7/build/less/products.less | 45 + .../AdminLTE-2.3.7/build/less/profile.less | 31 + .../build/less/progress-bars.less | 111 + .../AdminLTE-2.3.7/build/less/select2.less | 117 + .../build/less/sidebar-mini.less | 151 + .../AdminLTE-2.3.7/build/less/sidebar.less | 163 + .../build/less/skins/_all-skins.less | 13 + .../build/less/skins/skin-black-light.less | 64 + .../build/less/skins/skin-black.less | 74 + .../build/less/skins/skin-blue-light.less | 61 + .../build/less/skins/skin-blue.less | 58 + .../build/less/skins/skin-green-light.less | 55 + .../build/less/skins/skin-green.less | 55 + .../build/less/skins/skin-purple-light.less | 54 + .../build/less/skins/skin-purple.less | 54 + .../build/less/skins/skin-red-light.less | 54 + .../build/less/skins/skin-red.less | 54 + .../build/less/skins/skin-yellow-light.less | 54 + .../build/less/skins/skin-yellow.less | 54 + .../AdminLTE-2.3.7/build/less/small-box.less | 89 + .../build/less/social-widgets.less | 78 + .../AdminLTE-2.3.7/build/less/table.less | 71 + .../AdminLTE-2.3.7/build/less/timeline.less | 110 + .../AdminLTE-2.3.7/build/less/users-list.less | 42 + .../AdminLTE-2.3.7/build/less/variables.less | 123 + .../static/AdminLTE-2.3.7/changelog.md | 224 + .../static/AdminLTE-2.3.7/composer.json | 26 + .../AdminLTE-2.3.7/dist/css/AdminLTE.css | 4932 +++++ .../AdminLTE-2.3.7/dist/css/AdminLTE.min.css | 7 + .../dist/css/skins/_all-skins.css | 1770 ++ .../dist/css/skins/_all-skins.min.css | 1 + .../dist/css/skins/skin-black-light.css | 173 + .../dist/css/skins/skin-black-light.min.css | 1 + .../dist/css/skins/skin-black.css | 158 + .../dist/css/skins/skin-black.min.css | 1 + .../dist/css/skins/skin-blue-light.css | 164 + .../dist/css/skins/skin-blue-light.min.css | 1 + .../dist/css/skins/skin-blue.css | 139 + .../dist/css/skins/skin-blue.min.css | 1 + .../dist/css/skins/skin-green-light.css | 153 + .../dist/css/skins/skin-green-light.min.css | 1 + .../dist/css/skins/skin-green.css | 131 + .../dist/css/skins/skin-green.min.css | 1 + .../dist/css/skins/skin-purple-light.css | 153 + .../dist/css/skins/skin-purple-light.min.css | 1 + .../dist/css/skins/skin-purple.css | 131 + .../dist/css/skins/skin-purple.min.css | 1 + .../dist/css/skins/skin-red-light.css | 153 + .../dist/css/skins/skin-red-light.min.css | 1 + .../dist/css/skins/skin-red.css | 131 + .../dist/css/skins/skin-red.min.css | 1 + .../dist/css/skins/skin-yellow-light.css | 153 + .../dist/css/skins/skin-yellow-light.min.css | 1 + .../dist/css/skins/skin-yellow.css | 131 + .../dist/css/skins/skin-yellow.min.css | 1 + .../static/AdminLTE-2.3.7/dist/img/avatar.png | Bin 0 -> 8543 bytes .../AdminLTE-2.3.7/dist/img/avatar04.png | Bin 0 -> 14037 bytes .../AdminLTE-2.3.7/dist/img/avatar2.png | Bin 0 -> 8836 bytes .../AdminLTE-2.3.7/dist/img/avatar3.png | Bin 0 -> 9780 bytes .../AdminLTE-2.3.7/dist/img/avatar5.png | Bin 0 -> 8007 bytes .../AdminLTE-2.3.7/dist/img/boxed-bg.jpg | Bin 0 -> 123770 bytes .../AdminLTE-2.3.7/dist/img/boxed-bg.png | Bin 0 -> 43694 bytes .../dist/img/credit/american-express.png | Bin 0 -> 2205 bytes .../AdminLTE-2.3.7/dist/img/credit/cirrus.png | Bin 0 -> 1593 bytes .../dist/img/credit/mastercard.png | Bin 0 -> 1593 bytes .../AdminLTE-2.3.7/dist/img/credit/mestro.png | Bin 0 -> 1588 bytes .../AdminLTE-2.3.7/dist/img/credit/paypal.png | Bin 0 -> 2046 bytes .../dist/img/credit/paypal2.png | Bin 0 -> 1372 bytes .../AdminLTE-2.3.7/dist/img/credit/visa.png | Bin 0 -> 1137 bytes .../AdminLTE-2.3.7/dist/img/default-50x50.gif | Bin 0 -> 184 bytes .../static/AdminLTE-2.3.7/dist/img/icons.png | Bin 0 -> 1154 bytes .../static/AdminLTE-2.3.7/dist/img/photo1.png | Bin 0 -> 673900 bytes .../static/AdminLTE-2.3.7/dist/img/photo2.png | Bin 0 -> 424395 bytes .../static/AdminLTE-2.3.7/dist/img/photo3.jpg | Bin 0 -> 392079 bytes .../static/AdminLTE-2.3.7/dist/img/photo4.jpg | Bin 0 -> 1179224 bytes .../AdminLTE-2.3.7/dist/img/user1-128x128.jpg | Bin 0 -> 2879 bytes .../AdminLTE-2.3.7/dist/img/user2-160x160.jpg | Bin 0 -> 7070 bytes .../AdminLTE-2.3.7/dist/img/user3-128x128.jpg | Bin 0 -> 3511 bytes .../AdminLTE-2.3.7/dist/img/user4-128x128.jpg | Bin 0 -> 3477 bytes .../AdminLTE-2.3.7/dist/img/user5-128x128.jpg | Bin 0 -> 6446 bytes .../AdminLTE-2.3.7/dist/img/user6-128x128.jpg | Bin 0 -> 4342 bytes .../AdminLTE-2.3.7/dist/img/user7-128x128.jpg | Bin 0 -> 6434 bytes .../AdminLTE-2.3.7/dist/img/user8-128x128.jpg | Bin 0 -> 5060 bytes .../static/AdminLTE-2.3.7/dist/js/app.js | 763 + .../static/AdminLTE-2.3.7/dist/js/app.min.js | 13 + .../static/AdminLTE-2.3.7/dist/js/demo.js | 340 + .../AdminLTE-2.3.7/dist/js/pages/dashboard.js | 210 + .../dist/js/pages/dashboard2.js | 274 + .../build/include/adminlte-options.html | 123 + .../documentation/build/include/advice.html | 17 + .../documentation/build/include/browsers.html | 12 + .../build/include/components.html | 1545 ++ .../build/include/dependencies.html | 10 + .../documentation/build/include/download.html | 48 + .../documentation/build/include/faq.html | 12 + .../build/include/implementations.html | 18 + .../build/include/introduction.html | 12 + .../documentation/build/include/layout.html | 92 + .../documentation/build/include/license.html | 10 + .../documentation/build/include/plugins.html | 47 + .../documentation/build/include/upgrade.html | 26 + .../documentation/build/index.html | 192 + .../AdminLTE-2.3.7/documentation/docs.js | 63 + .../AdminLTE-2.3.7/documentation/index.html | 2164 ++ .../AdminLTE-2.3.7/documentation/style.css | 261 + .../static/AdminLTE-2.3.7/index.html | 1258 ++ .../static/AdminLTE-2.3.7/index2.html | 1556 ++ .../static/AdminLTE-2.3.7/package.json | 25 + .../AdminLTE-2.3.7/pages/UI/buttons.html | 1710 ++ .../AdminLTE-2.3.7/pages/UI/general.html | 1658 ++ .../static/AdminLTE-2.3.7/pages/UI/icons.html | 3033 +++ .../AdminLTE-2.3.7/pages/UI/modals.html | 901 + .../AdminLTE-2.3.7/pages/UI/sliders.html | 894 + .../AdminLTE-2.3.7/pages/UI/timeline.html | 905 + .../static/AdminLTE-2.3.7/pages/calendar.html | 971 + .../AdminLTE-2.3.7/pages/charts/chartjs.html | 917 + .../AdminLTE-2.3.7/pages/charts/flot.html | 1125 ++ .../AdminLTE-2.3.7/pages/charts/inline.html | 1303 ++ .../AdminLTE-2.3.7/pages/charts/morris.html | 908 + .../AdminLTE-2.3.7/pages/examples/404.html | 756 + .../AdminLTE-2.3.7/pages/examples/500.html | 757 + .../AdminLTE-2.3.7/pages/examples/blank.html | 654 + .../pages/examples/invoice-print.html | 170 + .../pages/examples/invoice.html | 886 + .../pages/examples/lockscreen.html | 74 + .../AdminLTE-2.3.7/pages/examples/login.html | 94 + .../AdminLTE-2.3.7/pages/examples/pace.html | 679 + .../pages/examples/profile.html | 1085 + .../pages/examples/register.html | 99 + .../AdminLTE-2.3.7/pages/forms/advanced.html | 1220 ++ .../AdminLTE-2.3.7/pages/forms/editors.html | 798 + .../AdminLTE-2.3.7/pages/forms/general.html | 1116 ++ .../AdminLTE-2.3.7/pages/layout/boxed.html | 654 + .../pages/layout/collapsed-sidebar.html | 660 + .../AdminLTE-2.3.7/pages/layout/fixed.html | 660 + .../AdminLTE-2.3.7/pages/layout/top-nav.html | 290 + .../AdminLTE-2.3.7/pages/mailbox/compose.html | 760 + .../AdminLTE-2.3.7/pages/mailbox/mailbox.html | 940 + .../pages/mailbox/read-mail.html | 815 + .../AdminLTE-2.3.7/pages/tables/data.html | 1638 ++ .../AdminLTE-2.3.7/pages/tables/simple.html | 1056 + .../static/AdminLTE-2.3.7/pages/widgets.html | 1788 ++ .../bootstrap-slider/bootstrap-slider.js | 1576 ++ .../plugins/bootstrap-slider/slider.css | 282 + .../bootstrap3-wysihtml5.all.js | 14975 ++++++++++++++ .../bootstrap3-wysihtml5.all.min.js | 8 + .../bootstrap3-wysihtml5.css | 117 + .../bootstrap3-wysihtml5.min.css | 3 + .../AdminLTE-2.3.7/plugins/chartjs/Chart.js | 3736 ++++ .../plugins/chartjs/Chart.min.js | 11 + .../plugins/ckeditor/CHANGES.md | 1053 + .../plugins/ckeditor/LICENSE.md | 1420 ++ .../AdminLTE-2.3.7/plugins/ckeditor/README.md | 39 + .../plugins/ckeditor/adapters/jquery.js | 10 + .../plugins/ckeditor/build-config.js | 159 + .../plugins/ckeditor/ckeditor.js | 1010 + .../AdminLTE-2.3.7/plugins/ckeditor/config.js | 38 + .../plugins/ckeditor/contents.css | 132 + .../plugins/ckeditor/lang/af.js | 5 + .../plugins/ckeditor/lang/ar.js | 5 + .../plugins/ckeditor/lang/bg.js | 5 + .../plugins/ckeditor/lang/bn.js | 5 + .../plugins/ckeditor/lang/bs.js | 5 + .../plugins/ckeditor/lang/ca.js | 5 + .../plugins/ckeditor/lang/cs.js | 5 + .../plugins/ckeditor/lang/cy.js | 5 + .../plugins/ckeditor/lang/da.js | 5 + .../plugins/ckeditor/lang/de-ch.js | 5 + .../plugins/ckeditor/lang/de.js | 5 + .../plugins/ckeditor/lang/el.js | 5 + .../plugins/ckeditor/lang/en-au.js | 5 + .../plugins/ckeditor/lang/en-ca.js | 5 + .../plugins/ckeditor/lang/en-gb.js | 5 + .../plugins/ckeditor/lang/en.js | 5 + .../plugins/ckeditor/lang/eo.js | 5 + .../plugins/ckeditor/lang/es.js | 5 + .../plugins/ckeditor/lang/et.js | 5 + .../plugins/ckeditor/lang/eu.js | 5 + .../plugins/ckeditor/lang/fa.js | 5 + .../plugins/ckeditor/lang/fi.js | 5 + .../plugins/ckeditor/lang/fo.js | 5 + .../plugins/ckeditor/lang/fr-ca.js | 5 + .../plugins/ckeditor/lang/fr.js | 5 + .../plugins/ckeditor/lang/gl.js | 5 + .../plugins/ckeditor/lang/gu.js | 5 + .../plugins/ckeditor/lang/he.js | 5 + .../plugins/ckeditor/lang/hi.js | 5 + .../plugins/ckeditor/lang/hr.js | 5 + .../plugins/ckeditor/lang/hu.js | 5 + .../plugins/ckeditor/lang/id.js | 5 + .../plugins/ckeditor/lang/is.js | 5 + .../plugins/ckeditor/lang/it.js | 5 + .../plugins/ckeditor/lang/ja.js | 5 + .../plugins/ckeditor/lang/ka.js | 5 + .../plugins/ckeditor/lang/km.js | 5 + .../plugins/ckeditor/lang/ko.js | 5 + .../plugins/ckeditor/lang/ku.js | 5 + .../plugins/ckeditor/lang/lt.js | 5 + .../plugins/ckeditor/lang/lv.js | 5 + .../plugins/ckeditor/lang/mk.js | 5 + .../plugins/ckeditor/lang/mn.js | 5 + .../plugins/ckeditor/lang/ms.js | 5 + .../plugins/ckeditor/lang/nb.js | 5 + .../plugins/ckeditor/lang/nl.js | 5 + .../plugins/ckeditor/lang/no.js | 5 + .../plugins/ckeditor/lang/pl.js | 5 + .../plugins/ckeditor/lang/pt-br.js | 5 + .../plugins/ckeditor/lang/pt.js | 5 + .../plugins/ckeditor/lang/ro.js | 5 + .../plugins/ckeditor/lang/ru.js | 5 + .../plugins/ckeditor/lang/si.js | 5 + .../plugins/ckeditor/lang/sk.js | 5 + .../plugins/ckeditor/lang/sl.js | 5 + .../plugins/ckeditor/lang/sq.js | 5 + .../plugins/ckeditor/lang/sr-latn.js | 5 + .../plugins/ckeditor/lang/sr.js | 5 + .../plugins/ckeditor/lang/sv.js | 5 + .../plugins/ckeditor/lang/th.js | 5 + .../plugins/ckeditor/lang/tr.js | 5 + .../plugins/ckeditor/lang/tt.js | 5 + .../plugins/ckeditor/lang/ug.js | 5 + .../plugins/ckeditor/lang/uk.js | 5 + .../plugins/ckeditor/lang/vi.js | 5 + .../plugins/ckeditor/lang/zh-cn.js | 5 + .../plugins/ckeditor/lang/zh.js | 5 + .../plugins/a11yhelp/dialogs/a11yhelp.js | 10 + .../dialogs/lang/_translationstatus.txt | 25 + .../plugins/a11yhelp/dialogs/lang/af.js | 11 + .../plugins/a11yhelp/dialogs/lang/ar.js | 11 + .../plugins/a11yhelp/dialogs/lang/bg.js | 11 + .../plugins/a11yhelp/dialogs/lang/ca.js | 12 + .../plugins/a11yhelp/dialogs/lang/cs.js | 12 + .../plugins/a11yhelp/dialogs/lang/cy.js | 11 + .../plugins/a11yhelp/dialogs/lang/da.js | 11 + .../plugins/a11yhelp/dialogs/lang/de-ch.js | 12 + .../plugins/a11yhelp/dialogs/lang/de.js | 12 + .../plugins/a11yhelp/dialogs/lang/el.js | 12 + .../plugins/a11yhelp/dialogs/lang/en-gb.js | 11 + .../plugins/a11yhelp/dialogs/lang/en.js | 11 + .../plugins/a11yhelp/dialogs/lang/eo.js | 13 + .../plugins/a11yhelp/dialogs/lang/es.js | 12 + .../plugins/a11yhelp/dialogs/lang/et.js | 11 + .../plugins/a11yhelp/dialogs/lang/eu.js | 12 + .../plugins/a11yhelp/dialogs/lang/fa.js | 11 + .../plugins/a11yhelp/dialogs/lang/fi.js | 11 + .../plugins/a11yhelp/dialogs/lang/fo.js | 11 + .../plugins/a11yhelp/dialogs/lang/fr-ca.js | 11 + .../plugins/a11yhelp/dialogs/lang/fr.js | 12 + .../plugins/a11yhelp/dialogs/lang/gl.js | 12 + .../plugins/a11yhelp/dialogs/lang/gu.js | 11 + .../plugins/a11yhelp/dialogs/lang/he.js | 11 + .../plugins/a11yhelp/dialogs/lang/hi.js | 11 + .../plugins/a11yhelp/dialogs/lang/hr.js | 11 + .../plugins/a11yhelp/dialogs/lang/hu.js | 12 + .../plugins/a11yhelp/dialogs/lang/id.js | 11 + .../plugins/a11yhelp/dialogs/lang/it.js | 13 + .../plugins/a11yhelp/dialogs/lang/ja.js | 9 + .../plugins/a11yhelp/dialogs/lang/km.js | 11 + .../plugins/a11yhelp/dialogs/lang/ko.js | 10 + .../plugins/a11yhelp/dialogs/lang/ku.js | 11 + .../plugins/a11yhelp/dialogs/lang/lt.js | 11 + .../plugins/a11yhelp/dialogs/lang/lv.js | 12 + .../plugins/a11yhelp/dialogs/lang/mk.js | 11 + .../plugins/a11yhelp/dialogs/lang/mn.js | 11 + .../plugins/a11yhelp/dialogs/lang/nb.js | 12 + .../plugins/a11yhelp/dialogs/lang/nl.js | 11 + .../plugins/a11yhelp/dialogs/lang/no.js | 11 + .../plugins/a11yhelp/dialogs/lang/pl.js | 13 + .../plugins/a11yhelp/dialogs/lang/pt-br.js | 13 + .../plugins/a11yhelp/dialogs/lang/pt.js | 12 + .../plugins/a11yhelp/dialogs/lang/ro.js | 11 + .../plugins/a11yhelp/dialogs/lang/ru.js | 11 + .../plugins/a11yhelp/dialogs/lang/si.js | 10 + .../plugins/a11yhelp/dialogs/lang/sk.js | 11 + .../plugins/a11yhelp/dialogs/lang/sl.js | 11 + .../plugins/a11yhelp/dialogs/lang/sq.js | 11 + .../plugins/a11yhelp/dialogs/lang/sr-latn.js | 11 + .../plugins/a11yhelp/dialogs/lang/sr.js | 11 + .../plugins/a11yhelp/dialogs/lang/sv.js | 11 + .../plugins/a11yhelp/dialogs/lang/th.js | 11 + .../plugins/a11yhelp/dialogs/lang/tr.js | 12 + .../plugins/a11yhelp/dialogs/lang/tt.js | 11 + .../plugins/a11yhelp/dialogs/lang/ug.js | 12 + .../plugins/a11yhelp/dialogs/lang/uk.js | 12 + .../plugins/a11yhelp/dialogs/lang/vi.js | 11 + .../plugins/a11yhelp/dialogs/lang/zh-cn.js | 9 + .../plugins/a11yhelp/dialogs/lang/zh.js | 9 + .../ckeditor/plugins/about/dialogs/about.js | 7 + .../about/dialogs/hidpi/logo_ckeditor.png | Bin 0 -> 13339 bytes .../plugins/about/dialogs/logo_ckeditor.png | Bin 0 -> 6757 bytes .../plugins/clipboard/dialogs/paste.js | 12 + .../plugins/dialog/dialogDefinition.js | 4 + .../plugins/ckeditor/plugins/icons.png | Bin 0 -> 10227 bytes .../plugins/ckeditor/plugins/icons_hidpi.png | Bin 0 -> 34465 bytes .../ckeditor/plugins/image/dialogs/image.js | 44 + .../ckeditor/plugins/image/images/noimage.png | Bin 0 -> 1610 bytes .../ckeditor/plugins/link/dialogs/anchor.js | 7 + .../ckeditor/plugins/link/dialogs/link.js | 26 + .../ckeditor/plugins/link/images/anchor.png | Bin 0 -> 589 bytes .../plugins/link/images/hidpi/anchor.png | Bin 0 -> 1379 bytes .../magicline/images/hidpi/icon-rtl.png | Bin 0 -> 176 bytes .../plugins/magicline/images/hidpi/icon.png | Bin 0 -> 199 bytes .../plugins/magicline/images/icon-rtl.png | Bin 0 -> 138 bytes .../plugins/magicline/images/icon.png | Bin 0 -> 133 bytes .../plugins/pastefromword/filter/default.js | 32 + .../ckeditor/plugins/scayt/CHANGELOG.md | 20 + .../plugins/ckeditor/plugins/scayt/LICENSE.md | 28 + .../plugins/ckeditor/plugins/scayt/README.md | 25 + .../ckeditor/plugins/scayt/dialogs/options.js | 19 + .../plugins/scayt/dialogs/toolbar.css | 71 + .../dialogs/lang/_translationstatus.txt | 20 + .../plugins/specialchar/dialogs/lang/af.js | 13 + .../plugins/specialchar/dialogs/lang/ar.js | 13 + .../plugins/specialchar/dialogs/lang/bg.js | 13 + .../plugins/specialchar/dialogs/lang/ca.js | 14 + .../plugins/specialchar/dialogs/lang/cs.js | 13 + .../plugins/specialchar/dialogs/lang/cy.js | 14 + .../plugins/specialchar/dialogs/lang/da.js | 11 + .../plugins/specialchar/dialogs/lang/de-ch.js | 13 + .../plugins/specialchar/dialogs/lang/de.js | 13 + .../plugins/specialchar/dialogs/lang/el.js | 13 + .../plugins/specialchar/dialogs/lang/en-gb.js | 13 + .../plugins/specialchar/dialogs/lang/en.js | 13 + .../plugins/specialchar/dialogs/lang/eo.js | 12 + .../plugins/specialchar/dialogs/lang/es.js | 13 + .../plugins/specialchar/dialogs/lang/et.js | 13 + .../plugins/specialchar/dialogs/lang/eu.js | 13 + .../plugins/specialchar/dialogs/lang/fa.js | 12 + .../plugins/specialchar/dialogs/lang/fi.js | 13 + .../plugins/specialchar/dialogs/lang/fr-ca.js | 10 + .../plugins/specialchar/dialogs/lang/fr.js | 11 + .../plugins/specialchar/dialogs/lang/gl.js | 13 + .../plugins/specialchar/dialogs/lang/he.js | 12 + .../plugins/specialchar/dialogs/lang/hr.js | 13 + .../plugins/specialchar/dialogs/lang/hu.js | 12 + .../plugins/specialchar/dialogs/lang/id.js | 13 + .../plugins/specialchar/dialogs/lang/it.js | 14 + .../plugins/specialchar/dialogs/lang/ja.js | 9 + .../plugins/specialchar/dialogs/lang/km.js | 13 + .../plugins/specialchar/dialogs/lang/ko.js | 10 + .../plugins/specialchar/dialogs/lang/ku.js | 13 + .../plugins/specialchar/dialogs/lang/lt.js | 13 + .../plugins/specialchar/dialogs/lang/lv.js | 13 + .../plugins/specialchar/dialogs/lang/nb.js | 11 + .../plugins/specialchar/dialogs/lang/nl.js | 13 + .../plugins/specialchar/dialogs/lang/no.js | 11 + .../plugins/specialchar/dialogs/lang/pl.js | 12 + .../plugins/specialchar/dialogs/lang/pt-br.js | 11 + .../plugins/specialchar/dialogs/lang/pt.js | 13 + .../plugins/specialchar/dialogs/lang/ru.js | 13 + .../plugins/specialchar/dialogs/lang/si.js | 13 + .../plugins/specialchar/dialogs/lang/sk.js | 13 + .../plugins/specialchar/dialogs/lang/sl.js | 12 + .../plugins/specialchar/dialogs/lang/sq.js | 13 + .../plugins/specialchar/dialogs/lang/sv.js | 11 + .../plugins/specialchar/dialogs/lang/th.js | 13 + .../plugins/specialchar/dialogs/lang/tr.js | 12 + .../plugins/specialchar/dialogs/lang/tt.js | 13 + .../plugins/specialchar/dialogs/lang/ug.js | 13 + .../plugins/specialchar/dialogs/lang/uk.js | 12 + .../plugins/specialchar/dialogs/lang/vi.js | 14 + .../plugins/specialchar/dialogs/lang/zh-cn.js | 9 + .../plugins/specialchar/dialogs/lang/zh.js | 9 + .../specialchar/dialogs/specialchar.js | 14 + .../ckeditor/plugins/table/dialogs/table.js | 21 + .../plugins/tabletools/dialogs/tableCell.js | 17 + .../plugins/ckeditor/plugins/wsc/LICENSE.md | 28 + .../plugins/ckeditor/plugins/wsc/README.md | 25 + .../ckeditor/plugins/wsc/dialogs/ciframe.html | 66 + .../plugins/wsc/dialogs/tmpFrameset.html | 52 + .../ckeditor/plugins/wsc/dialogs/wsc.css | 82 + .../ckeditor/plugins/wsc/dialogs/wsc.js | 92 + .../ckeditor/plugins/wsc/dialogs/wsc_ie.js | 11 + .../plugins/ckeditor/samples/css/samples.css | 1640 ++ .../ckeditor/samples/img/github-top.png | Bin 0 -> 383 bytes .../ckeditor/samples/img/header-bg.png | Bin 0 -> 13086 bytes .../ckeditor/samples/img/header-separator.png | Bin 0 -> 123 bytes .../plugins/ckeditor/samples/img/logo.png | Bin 0 -> 5891 bytes .../ckeditor/samples/img/navigation-tip.png | Bin 0 -> 12029 bytes .../plugins/ckeditor/samples/index.html | 128 + .../plugins/ckeditor/samples/js/sample.js | 53 + .../plugins/ckeditor/samples/js/sf.js | 17 + .../plugins/ckeditor/samples/old/ajax.html | 85 + .../plugins/ckeditor/samples/old/api.html | 210 + .../ckeditor/samples/old/appendto.html | 59 + .../samples/old/assets/inlineall/logo.png | Bin 0 -> 4283 bytes .../old/assets/outputxhtml/outputxhtml.css | 204 + .../samples/old/assets/posteddata.php | 59 + .../ckeditor/samples/old/assets/sample.jpg | Bin 0 -> 14449 bytes .../old/assets/uilanguages/languages.js | 7 + .../ckeditor/samples/old/datafiltering.html | 508 + .../samples/old/dialog/assets/my_dialog.js | 48 + .../ckeditor/samples/old/dialog/dialog.html | 190 + .../ckeditor/samples/old/divreplace.html | 144 + .../samples/old/enterkey/enterkey.html | 106 + .../assets/outputforflash/outputforflash.fla | Bin 0 -> 85504 bytes .../assets/outputforflash/outputforflash.swf | Bin 0 -> 15571 bytes .../assets/outputforflash/swfobject.js | 19 + .../old/htmlwriter/outputforflash.html | 283 + .../samples/old/htmlwriter/outputhtml.html | 224 + .../plugins/ckeditor/samples/old/index.html | 131 + .../ckeditor/samples/old/inlineall.html | 314 + .../ckeditor/samples/old/inlinebycode.html | 124 + .../ckeditor/samples/old/inlinetextarea.html | 113 + .../plugins/ckeditor/samples/old/jquery.html | 103 + .../samples/old/magicline/magicline.html | 209 + .../ckeditor/samples/old/readonly.html | 76 + .../ckeditor/samples/old/replacebyclass.html | 60 + .../ckeditor/samples/old/replacebycode.html | 59 + .../plugins/ckeditor/samples/old/sample.css | 357 + .../plugins/ckeditor/samples/old/sample.js | 50 + .../samples/old/sample_posteddata.php | 16 + .../ckeditor/samples/old/tabindex.html | 78 + .../ckeditor/samples/old/toolbar/toolbar.html | 235 + .../plugins/ckeditor/samples/old/uicolor.html | 72 + .../ckeditor/samples/old/uilanguages.html | 122 + .../samples/old/wysiwygarea/fullpage.html | 80 + .../ckeditor/samples/old/xhtmlstyle.html | 234 + .../toolbarconfigurator/css/fontello.css | 55 + .../toolbarconfigurator/font/LICENSE.txt | 10 + .../toolbarconfigurator/font/config.json | 28 + .../toolbarconfigurator/font/fontello.eot | Bin 0 -> 4988 bytes .../toolbarconfigurator/font/fontello.svg | 14 + .../toolbarconfigurator/font/fontello.ttf | Bin 0 -> 4820 bytes .../toolbarconfigurator/font/fontello.woff | Bin 0 -> 2904 bytes .../samples/toolbarconfigurator/index.html | 446 + .../js/abstracttoolbarmodifier.js | 13 + .../js/fulltoolbareditor.js | 9 + .../toolbarconfigurator/js/toolbarmodifier.js | 33 + .../js/toolbartextmodifier.js | 14 + .../lib/codemirror/LICENSE | 19 + .../lib/codemirror/codemirror.css | 325 + .../lib/codemirror/codemirror.js | 288 + .../lib/codemirror/javascript.js | 25 + .../lib/codemirror/neo.css | 36 + .../lib/codemirror/show-hint.css | 38 + .../lib/codemirror/show-hint.js | 16 + .../plugins/ckeditor/skins/moono/dialog.css | 5 + .../ckeditor/skins/moono/dialog_ie.css | 5 + .../ckeditor/skins/moono/dialog_ie7.css | 5 + .../ckeditor/skins/moono/dialog_ie8.css | 5 + .../ckeditor/skins/moono/dialog_iequirks.css | 5 + .../plugins/ckeditor/skins/moono/editor.css | 5 + .../ckeditor/skins/moono/editor_gecko.css | 5 + .../ckeditor/skins/moono/editor_ie.css | 5 + .../ckeditor/skins/moono/editor_ie7.css | 5 + .../ckeditor/skins/moono/editor_ie8.css | 5 + .../ckeditor/skins/moono/editor_iequirks.css | 5 + .../plugins/ckeditor/skins/moono/icons.png | Bin 0 -> 10227 bytes .../ckeditor/skins/moono/icons_hidpi.png | Bin 0 -> 34465 bytes .../ckeditor/skins/moono/images/arrow.png | Bin 0 -> 191 bytes .../ckeditor/skins/moono/images/close.png | Bin 0 -> 468 bytes .../skins/moono/images/hidpi/close.png | Bin 0 -> 1271 bytes .../skins/moono/images/hidpi/lock-open.png | Bin 0 -> 1329 bytes .../skins/moono/images/hidpi/lock.png | Bin 0 -> 1299 bytes .../skins/moono/images/hidpi/refresh.png | Bin 0 -> 1842 bytes .../ckeditor/skins/moono/images/lock-open.png | Bin 0 -> 349 bytes .../ckeditor/skins/moono/images/lock.png | Bin 0 -> 475 bytes .../ckeditor/skins/moono/images/refresh.png | Bin 0 -> 422 bytes .../ckeditor/skins/moono/images/spinner.gif | Bin 0 -> 2984 bytes .../plugins/ckeditor/skins/moono/readme.md | 49 + .../AdminLTE-2.3.7/plugins/ckeditor/styles.js | 111 + .../colorpicker/bootstrap-colorpicker.css | 251 + .../colorpicker/bootstrap-colorpicker.js | 1079 + .../colorpicker/bootstrap-colorpicker.min.css | 9 + .../colorpicker/bootstrap-colorpicker.min.js | 1 + .../colorpicker/img/alpha-horizontal.png | Bin 0 -> 3635 bytes .../plugins/colorpicker/img/alpha.png | Bin 0 -> 3271 bytes .../colorpicker/img/hue-horizontal.png | Bin 0 -> 2837 bytes .../plugins/colorpicker/img/hue.png | Bin 0 -> 2972 bytes .../plugins/colorpicker/img/saturation.png | Bin 0 -> 8817 bytes .../datatables/dataTables.bootstrap.css | 372 + .../datatables/dataTables.bootstrap.js | 206 + .../datatables/dataTables.bootstrap.min.js | 8 + .../datatables/extensions/AutoFill/Readme.txt | 38 + .../AutoFill/css/dataTables.autoFill.css | 24 + .../AutoFill/css/dataTables.autoFill.min.css | 1 + .../extensions/AutoFill/examples/columns.html | 644 + .../AutoFill/examples/complete-callback.html | 652 + .../AutoFill/examples/fill-both.html | 641 + .../AutoFill/examples/fill-horizontal.html | 641 + .../extensions/AutoFill/examples/index.html | 66 + .../AutoFill/examples/scrolling.html | 638 + .../extensions/AutoFill/examples/simple.html | 631 + .../AutoFill/examples/step-callback.html | 660 + .../extensions/AutoFill/images/filler.png | Bin 0 -> 1040 bytes .../AutoFill/js/dataTables.autoFill.js | 855 + .../AutoFill/js/dataTables.autoFill.min.js | 22 + .../extensions/ColReorder/License.txt | 20 + .../extensions/ColReorder/Readme.md | 39 + .../ColReorder/css/dataTables.colReorder.css | 14 + .../css/dataTables.colReorder.min.css | 1 + .../ColReorder/examples/alt_insert.html | 637 + .../ColReorder/examples/col_filter.html | 656 + .../ColReorder/examples/colvis.html | 635 + .../ColReorder/examples/fixedcolumns.html | 831 + .../ColReorder/examples/fixedheader.html | 635 + .../extensions/ColReorder/examples/index.html | 74 + .../ColReorder/examples/jqueryui.html | 635 + .../ColReorder/examples/new_init.html | 626 + .../ColReorder/examples/predefined.html | 636 + .../ColReorder/examples/realtime.html | 637 + .../extensions/ColReorder/examples/reset.html | 649 + .../ColReorder/examples/scrolling.html | 632 + .../ColReorder/examples/server_side.html | 192 + .../ColReorder/examples/simple.html | 630 + .../ColReorder/examples/state_save.html | 631 + .../extensions/ColReorder/images/insert.png | Bin 0 -> 1885 bytes .../ColReorder/js/dataTables.colReorder.js | 1372 ++ .../js/dataTables.colReorder.min.js | 26 + .../datatables/extensions/ColVis/License.txt | 20 + .../datatables/extensions/ColVis/Readme.md | 38 + .../ColVis/css/dataTables.colVis.css | 185 + .../ColVis/css/dataTables.colVis.min.css | 1 + .../ColVis/css/dataTables.colvis.jqueryui.css | 41 + .../ColVis/examples/button_order.html | 630 + .../ColVis/examples/exclude_columns.html | 632 + .../ColVis/examples/group_columns.html | 656 + .../extensions/ColVis/examples/index.html | 72 + .../extensions/ColVis/examples/jqueryui.html | 637 + .../extensions/ColVis/examples/mouseover.html | 632 + .../extensions/ColVis/examples/new_init.html | 629 + .../extensions/ColVis/examples/restore.html | 641 + .../extensions/ColVis/examples/simple.html | 627 + .../extensions/ColVis/examples/text.html | 631 + .../ColVis/examples/title_callback.html | 636 + .../ColVis/examples/two_tables.html | 339 + .../ColVis/examples/two_tables_identical.html | 363 + .../extensions/ColVis/js/dataTables.colVis.js | 1123 ++ .../ColVis/js/dataTables.colVis.min.js | 24 + .../extensions/FixedColumns/License.txt | 20 + .../extensions/FixedColumns/Readme.md | 42 + .../css/dataTables.fixedColumns.css | 25 + .../css/dataTables.fixedColumns.min.css | 1 + .../FixedColumns/examples/bootstrap.html | 819 + .../FixedColumns/examples/col_filter.html | 857 + .../FixedColumns/examples/colvis.html | 833 + .../FixedColumns/examples/css_size.html | 828 + .../FixedColumns/examples/index.html | 74 + .../FixedColumns/examples/index_column.html | 932 + .../examples/left_right_columns.html | 816 + .../FixedColumns/examples/right_column.html | 816 + .../FixedColumns/examples/rowspan.html | 657 + .../examples/server-side-processing.html | 204 + .../FixedColumns/examples/simple.html | 813 + .../FixedColumns/examples/size_fixed.html | 824 + .../FixedColumns/examples/size_fluid.html | 824 + .../FixedColumns/examples/two_columns.html | 810 + .../js/dataTables.fixedColumns.js | 1423 ++ .../js/dataTables.fixedColumns.min.js | 30 + .../extensions/FixedHeader/Readme.txt | 36 + .../css/dataTables.fixedHeader.css | 7 + .../css/dataTables.fixedHeader.min.css | 1 + .../FixedHeader/examples/header_footer.html | 641 + .../FixedHeader/examples/index.html | 69 + .../FixedHeader/examples/simple.html | 637 + .../FixedHeader/examples/top_left_right.html | 236 + .../FixedHeader/examples/two_tables.html | 354 + .../FixedHeader/examples/zIndexes.html | 653 + .../FixedHeader/js/dataTables.fixedHeader.js | 1028 + .../js/dataTables.fixedHeader.min.js | 30 + .../datatables/extensions/KeyTable/Readme.txt | 36 + .../KeyTable/css/dataTables.keyTable.css | 7 + .../KeyTable/css/dataTables.keyTable.min.css | 1 + .../extensions/KeyTable/examples/events.html | 756 + .../extensions/KeyTable/examples/html.html | 627 + .../extensions/KeyTable/examples/index.html | 69 + .../KeyTable/examples/scrolling.html | 637 + .../extensions/KeyTable/examples/simple.html | 631 + .../KeyTable/js/dataTables.keyTable.js | 1175 ++ .../KeyTable/js/dataTables.keyTable.min.js | 18 + .../extensions/Responsive/License.txt | 20 + .../extensions/Responsive/Readme.md} | 0 .../Responsive/css/dataTables.responsive.css | 106 + .../Responsive/css/dataTables.responsive.scss | 149 + .../examples/child-rows/column-control.html | 854 + .../examples/child-rows/custom-renderer.html | 863 + .../child-rows/disable-child-rows.html | 819 + .../Responsive/examples/child-rows/index.html | 72 + .../examples/child-rows/right-column.html | 850 + .../child-rows/whole-row-control.html | 853 + .../examples/display-control/auto.html | 813 + .../examples/display-control/classes.html | 247 + .../display-control/complexHeader.html | 708 + .../examples/display-control/fixedHeader.html | 825 + .../examples/display-control/index.html | 65 + .../display-control/init-classes.html | 215 + .../extensions/Responsive/examples/index.html | 86 + .../examples/initialisation/ajax.html | 210 + .../examples/initialisation/className.html | 812 + .../examples/initialisation/default.html | 822 + .../examples/initialisation/index.html | 65 + .../examples/initialisation/new.html | 821 + .../examples/initialisation/option.html | 820 + .../examples/styling/bootstrap.html | 831 + .../Responsive/examples/styling/compact.html | 816 + .../examples/styling/foundation.html | 822 + .../Responsive/examples/styling/index.html | 57 + .../examples/styling/scrolling.html | 826 + .../Responsive/js/dataTables.responsive.js | 873 + .../js/dataTables.responsive.min.js | 19 + .../datatables/extensions/Scroller/Readme.txt | 43 + .../Scroller/css/dataTables.scroller.css | 44 + .../Scroller/css/dataTables.scroller.min.css | 1 + .../Scroller/examples/api_scrolling.html | 174 + .../Scroller/examples/data/2500.txt | 2502 +++ .../extensions/Scroller/examples/data/ssp.php | 58 + .../extensions/Scroller/examples/index.html | 83 + .../Scroller/examples/large_js_source.html | 182 + .../examples/server-side_processing.html | 220 + .../extensions/Scroller/examples/simple.html | 175 + .../Scroller/examples/state_saving.html | 170 + .../Scroller/images/loading-background.png | Bin 0 -> 1013 bytes .../Scroller/js/dataTables.scroller.js | 1262 ++ .../Scroller/js/dataTables.scroller.min.js | 25 + .../extensions/TableTools/Readme.md | 41 + .../TableTools/css/dataTables.tableTools.css | 361 + .../css/dataTables.tableTools.min.css | 1 + .../extensions/TableTools/examples/ajax.html | 190 + .../TableTools/examples/alter_buttons.html | 637 + .../TableTools/examples/bootstrap.html | 645 + .../TableTools/examples/button_text.html | 669 + .../TableTools/examples/collection.html | 654 + .../TableTools/examples/defaults.html | 634 + .../extensions/TableTools/examples/index.html | 80 + .../TableTools/examples/jqueryui.html | 637 + .../TableTools/examples/multi_instance.html | 638 + .../TableTools/examples/multiple_tables.html | 343 + .../TableTools/examples/new_init.html | 644 + .../TableTools/examples/pdf_message.html | 655 + .../TableTools/examples/plug-in.html | 682 + .../TableTools/examples/select_column.html | 228 + .../TableTools/examples/select_multi.html | 649 + .../TableTools/examples/select_os.html | 649 + .../TableTools/examples/select_single.html | 646 + .../TableTools/examples/simple.html | 633 + .../TableTools/examples/swf_path.html | 639 + .../TableTools/images/collection.png | Bin 0 -> 1166 bytes .../TableTools/images/collection_hover.png | Bin 0 -> 1194 bytes .../extensions/TableTools/images/copy.png | Bin 0 -> 2184 bytes .../TableTools/images/copy_hover.png | Bin 0 -> 2797 bytes .../extensions/TableTools/images/csv.png | Bin 0 -> 1607 bytes .../TableTools/images/csv_hover.png | Bin 0 -> 1854 bytes .../extensions/TableTools/images/pdf.png | Bin 0 -> 4325 bytes .../TableTools/images/pdf_hover.png | Bin 0 -> 2786 bytes .../extensions/TableTools/images/print.png | Bin 0 -> 2123 bytes .../TableTools/images/print_hover.png | Bin 0 -> 2230 bytes .../TableTools/images/psd/collection.psd | Bin 0 -> 25792 bytes .../TableTools/images/psd/copy document.psd | Bin 0 -> 104729 bytes .../TableTools/images/psd/file_types.psd | Bin 0 -> 1090645 bytes .../TableTools/images/psd/printer.psd | Bin 0 -> 119952 bytes .../extensions/TableTools/images/xls.png | Bin 0 -> 1641 bytes .../TableTools/images/xls_hover.png | Bin 0 -> 2061 bytes .../TableTools/js/dataTables.tableTools.js | 3230 +++ .../js/dataTables.tableTools.min.js | 70 + .../TableTools/swf/copy_csv_xls.swf | Bin 0 -> 2232 bytes .../TableTools/swf/copy_csv_xls_pdf.swf | Bin 0 -> 58846 bytes .../plugins/datatables/images/sort_asc.png | Bin 0 -> 160 bytes .../datatables/images/sort_asc_disabled.png | Bin 0 -> 148 bytes .../plugins/datatables/images/sort_both.png | Bin 0 -> 201 bytes .../plugins/datatables/images/sort_desc.png | Bin 0 -> 158 bytes .../datatables/images/sort_desc_disabled.png | Bin 0 -> 146 bytes .../plugins/datatables/jquery.dataTables.css | 455 + .../plugins/datatables/jquery.dataTables.js | 14951 ++++++++++++++ .../datatables/jquery.dataTables.min.css | 1 + .../datatables/jquery.dataTables.min.js | 160 + .../jquery.dataTables_themeroller.css | 416 + .../datepicker/bootstrap-datepicker.js | 1671 ++ .../plugins/datepicker/datepicker3.css | 790 + .../locales/bootstrap-datepicker.ar.js | 15 + .../locales/bootstrap-datepicker.az.js | 12 + .../locales/bootstrap-datepicker.bg.js | 14 + .../locales/bootstrap-datepicker.ca.js | 14 + .../locales/bootstrap-datepicker.cs.js | 15 + .../locales/bootstrap-datepicker.cy.js | 14 + .../locales/bootstrap-datepicker.da.js | 15 + .../locales/bootstrap-datepicker.de.js | 17 + .../locales/bootstrap-datepicker.el.js | 13 + .../locales/bootstrap-datepicker.es.js | 14 + .../locales/bootstrap-datepicker.et.js | 18 + .../locales/bootstrap-datepicker.fa.js | 17 + .../locales/bootstrap-datepicker.fi.js | 16 + .../locales/bootstrap-datepicker.fr.js | 17 + .../locales/bootstrap-datepicker.gl.js | 11 + .../locales/bootstrap-datepicker.he.js | 15 + .../locales/bootstrap-datepicker.hr.js | 13 + .../locales/bootstrap-datepicker.hu.js | 16 + .../locales/bootstrap-datepicker.id.js | 15 + .../locales/bootstrap-datepicker.is.js | 14 + .../locales/bootstrap-datepicker.it.js | 17 + .../locales/bootstrap-datepicker.ja.js | 15 + .../locales/bootstrap-datepicker.ka.js | 17 + .../locales/bootstrap-datepicker.kk.js | 15 + .../locales/bootstrap-datepicker.kr.js | 13 + .../locales/bootstrap-datepicker.lt.js | 16 + .../locales/bootstrap-datepicker.lv.js | 16 + .../locales/bootstrap-datepicker.mk.js | 15 + .../locales/bootstrap-datepicker.ms.js | 14 + .../locales/bootstrap-datepicker.nb.js | 14 + .../locales/bootstrap-datepicker.nl-BE.js | 17 + .../locales/bootstrap-datepicker.nl.js | 14 + .../locales/bootstrap-datepicker.no.js | 16 + .../locales/bootstrap-datepicker.pl.js | 15 + .../locales/bootstrap-datepicker.pt-BR.js | 15 + .../locales/bootstrap-datepicker.pt.js | 16 + .../locales/bootstrap-datepicker.ro.js | 16 + .../locales/bootstrap-datepicker.rs-latin.js | 14 + .../locales/bootstrap-datepicker.rs.js | 14 + .../locales/bootstrap-datepicker.ru.js | 15 + .../locales/bootstrap-datepicker.sk.js | 15 + .../locales/bootstrap-datepicker.sl.js | 14 + .../locales/bootstrap-datepicker.sq.js | 15 + .../locales/bootstrap-datepicker.sv.js | 16 + .../locales/bootstrap-datepicker.sw.js | 15 + .../locales/bootstrap-datepicker.th.js | 14 + .../locales/bootstrap-datepicker.tr.js | 16 + .../locales/bootstrap-datepicker.ua.js | 15 + .../locales/bootstrap-datepicker.vi.js | 16 + .../locales/bootstrap-datepicker.zh-CN.js | 16 + .../locales/bootstrap-datepicker.zh-TW.js | 17 + .../daterangepicker/daterangepicker.css | 232 + .../daterangepicker/daterangepicker.js | 1542 ++ .../plugins/daterangepicker/moment.js | 3111 +++ .../plugins/daterangepicker/moment.min.js | 7 + .../plugins/fastclick/fastclick.js | 841 + .../plugins/fastclick/fastclick.min.js | 1 + .../AdminLTE-2.3.7/plugins/flot/excanvas.js | 1427 ++ .../plugins/flot/excanvas.min.js | 1 + .../plugins/flot/jquery.colorhelpers.js | 180 + .../plugins/flot/jquery.colorhelpers.min.js | 1 + .../plugins/flot/jquery.flot.canvas.js | 345 + .../plugins/flot/jquery.flot.canvas.min.js | 1 + .../plugins/flot/jquery.flot.categories.js | 190 + .../flot/jquery.flot.categories.min.js | 1 + .../plugins/flot/jquery.flot.crosshair.js | 176 + .../plugins/flot/jquery.flot.crosshair.min.js | 1 + .../plugins/flot/jquery.flot.errorbars.js | 353 + .../plugins/flot/jquery.flot.errorbars.min.js | 1 + .../plugins/flot/jquery.flot.fillbetween.js | 226 + .../flot/jquery.flot.fillbetween.min.js | 1 + .../plugins/flot/jquery.flot.image.js | 241 + .../plugins/flot/jquery.flot.image.min.js | 1 + .../plugins/flot/jquery.flot.js | 3137 +++ .../plugins/flot/jquery.flot.min.js | 2 + .../plugins/flot/jquery.flot.navigate.js | 346 + .../plugins/flot/jquery.flot.navigate.min.js | 1 + .../plugins/flot/jquery.flot.pie.js | 817 + .../plugins/flot/jquery.flot.pie.min.js | 1 + .../plugins/flot/jquery.flot.resize.js | 60 + .../plugins/flot/jquery.flot.resize.min.js | 1 + .../plugins/flot/jquery.flot.selection.js | 360 + .../plugins/flot/jquery.flot.selection.min.js | 1 + .../plugins/flot/jquery.flot.stack.js | 188 + .../plugins/flot/jquery.flot.stack.min.js | 1 + .../plugins/flot/jquery.flot.symbol.js | 71 + .../plugins/flot/jquery.flot.symbol.min.js | 1 + .../plugins/flot/jquery.flot.threshold.js | 142 + .../plugins/flot/jquery.flot.threshold.min.js | 1 + .../plugins/flot/jquery.flot.time.js | 429 + .../plugins/flot/jquery.flot.time.min.js | 1 + .../plugins/fullcalendar/fullcalendar.css | 977 + .../plugins/fullcalendar/fullcalendar.js | 9732 +++++++++ .../plugins/fullcalendar/fullcalendar.min.css | 5 + .../plugins/fullcalendar/fullcalendar.min.js | 8 + .../fullcalendar/fullcalendar.print.css | 202 + .../AdminLTE-2.3.7/plugins/iCheck/all.css | 61 + .../plugins/iCheck/flat/_all.css | 560 + .../plugins/iCheck/flat/aero.css | 56 + .../plugins/iCheck/flat/aero.png | Bin 0 -> 1520 bytes .../plugins/iCheck/flat/aero@2x.png | Bin 0 -> 3218 bytes .../plugins/iCheck/flat/blue.css | 56 + .../plugins/iCheck/flat/blue.png | Bin 0 -> 1518 bytes .../plugins/iCheck/flat/blue@2x.png | Bin 0 -> 3217 bytes .../plugins/iCheck/flat/flat.css | 56 + .../plugins/iCheck/flat/flat.png | Bin 0 -> 1515 bytes .../plugins/iCheck/flat/flat@2x.png | Bin 0 -> 3217 bytes .../plugins/iCheck/flat/green.css | 56 + .../plugins/iCheck/flat/green.png | Bin 0 -> 1444 bytes .../plugins/iCheck/flat/green@2x.png | Bin 0 -> 3117 bytes .../plugins/iCheck/flat/grey.css | 56 + .../plugins/iCheck/flat/grey.png | Bin 0 -> 1516 bytes .../plugins/iCheck/flat/grey@2x.png | Bin 0 -> 3217 bytes .../plugins/iCheck/flat/orange.css | 56 + .../plugins/iCheck/flat/orange.png | Bin 0 -> 1518 bytes .../plugins/iCheck/flat/orange@2x.png | Bin 0 -> 3275 bytes .../plugins/iCheck/flat/pink.css | 56 + .../plugins/iCheck/flat/pink.png | Bin 0 -> 1522 bytes .../plugins/iCheck/flat/pink@2x.png | Bin 0 -> 3218 bytes .../plugins/iCheck/flat/purple.css | 56 + .../plugins/iCheck/flat/purple.png | Bin 0 -> 1519 bytes .../plugins/iCheck/flat/purple@2x.png | Bin 0 -> 3218 bytes .../plugins/iCheck/flat/red.css | 56 + .../plugins/iCheck/flat/red.png | Bin 0 -> 1516 bytes .../plugins/iCheck/flat/red@2x.png | Bin 0 -> 3276 bytes .../plugins/iCheck/flat/yellow.css | 56 + .../plugins/iCheck/flat/yellow.png | Bin 0 -> 1516 bytes .../plugins/iCheck/flat/yellow@2x.png | Bin 0 -> 3216 bytes .../plugins/iCheck/futurico/futurico.css | 56 + .../plugins/iCheck/futurico/futurico.png | Bin 0 -> 1734 bytes .../plugins/iCheck/futurico/futurico@2x.png | Bin 0 -> 3446 bytes .../AdminLTE-2.3.7/plugins/iCheck/icheck.js | 478 + .../plugins/iCheck/icheck.min.js | 10 + .../plugins/iCheck/line/_all.css | 740 + .../plugins/iCheck/line/aero.css | 74 + .../plugins/iCheck/line/blue.css | 74 + .../plugins/iCheck/line/green.css | 74 + .../plugins/iCheck/line/grey.css | 74 + .../plugins/iCheck/line/line.css | 74 + .../plugins/iCheck/line/line.png | Bin 0 -> 588 bytes .../plugins/iCheck/line/line@2x.png | Bin 0 -> 1073 bytes .../plugins/iCheck/line/orange.css | 74 + .../plugins/iCheck/line/pink.css | 74 + .../plugins/iCheck/line/purple.css | 74 + .../plugins/iCheck/line/red.css | 74 + .../plugins/iCheck/line/yellow.css | 74 + .../plugins/iCheck/minimal/_all.css | 557 + .../plugins/iCheck/minimal/aero.css | 62 + .../plugins/iCheck/minimal/aero.png | Bin 0 -> 1151 bytes .../plugins/iCheck/minimal/aero@2x.png | Bin 0 -> 1409 bytes .../plugins/iCheck/minimal/blue.css | 62 + .../plugins/iCheck/minimal/blue.png | Bin 0 -> 1132 bytes .../plugins/iCheck/minimal/blue@2x.png | Bin 0 -> 1410 bytes .../plugins/iCheck/minimal/green.css | 62 + .../plugins/iCheck/minimal/green.png | Bin 0 -> 1143 bytes .../plugins/iCheck/minimal/green@2x.png | Bin 0 -> 1408 bytes .../plugins/iCheck/minimal/grey.css | 62 + .../plugins/iCheck/minimal/grey.png | Bin 0 -> 1142 bytes .../plugins/iCheck/minimal/grey@2x.png | Bin 0 -> 1407 bytes .../plugins/iCheck/minimal/minimal.css | 62 + .../plugins/iCheck/minimal/minimal.png | Bin 0 -> 1114 bytes .../plugins/iCheck/minimal/minimal@2x.png | Bin 0 -> 1410 bytes .../plugins/iCheck/minimal/orange.css | 62 + .../plugins/iCheck/minimal/orange.png | Bin 0 -> 1139 bytes .../plugins/iCheck/minimal/orange@2x.png | Bin 0 -> 1407 bytes .../plugins/iCheck/minimal/pink.css | 62 + .../plugins/iCheck/minimal/pink.png | Bin 0 -> 1150 bytes .../plugins/iCheck/minimal/pink@2x.png | Bin 0 -> 1409 bytes .../plugins/iCheck/minimal/purple.css | 62 + .../plugins/iCheck/minimal/purple.png | Bin 0 -> 1132 bytes .../plugins/iCheck/minimal/purple@2x.png | Bin 0 -> 1409 bytes .../plugins/iCheck/minimal/red.css | 62 + .../plugins/iCheck/minimal/red.png | Bin 0 -> 1130 bytes .../plugins/iCheck/minimal/red@2x.png | Bin 0 -> 1410 bytes .../plugins/iCheck/minimal/yellow.css | 62 + .../plugins/iCheck/minimal/yellow.png | Bin 0 -> 1135 bytes .../plugins/iCheck/minimal/yellow@2x.png | Bin 0 -> 1406 bytes .../plugins/iCheck/polaris/polaris.css | 62 + .../plugins/iCheck/polaris/polaris.png | Bin 0 -> 6401 bytes .../plugins/iCheck/polaris/polaris@2x.png | Bin 0 -> 16760 bytes .../plugins/iCheck/square/_all.css | 620 + .../plugins/iCheck/square/aero.css | 62 + .../plugins/iCheck/square/aero.png | Bin 0 -> 2167 bytes .../plugins/iCheck/square/aero@2x.png | Bin 0 -> 4455 bytes .../plugins/iCheck/square/blue.css | 62 + .../plugins/iCheck/square/blue.png | Bin 0 -> 2185 bytes .../plugins/iCheck/square/blue@2x.png | Bin 0 -> 4485 bytes .../plugins/iCheck/square/green.css | 62 + .../plugins/iCheck/square/green.png | Bin 0 -> 2193 bytes .../plugins/iCheck/square/green@2x.png | Bin 0 -> 4498 bytes .../plugins/iCheck/square/grey.css | 62 + .../plugins/iCheck/square/grey.png | Bin 0 -> 2186 bytes .../plugins/iCheck/square/grey@2x.png | Bin 0 -> 4483 bytes .../plugins/iCheck/square/orange.css | 62 + .../plugins/iCheck/square/orange.png | Bin 0 -> 2181 bytes .../plugins/iCheck/square/orange@2x.png | Bin 0 -> 4474 bytes .../plugins/iCheck/square/pink.css | 62 + .../plugins/iCheck/square/pink.png | Bin 0 -> 2189 bytes .../plugins/iCheck/square/pink@2x.png | Bin 0 -> 4479 bytes .../plugins/iCheck/square/purple.css | 62 + .../plugins/iCheck/square/purple.png | Bin 0 -> 2188 bytes .../plugins/iCheck/square/purple@2x.png | Bin 0 -> 4501 bytes .../plugins/iCheck/square/red.css | 62 + .../plugins/iCheck/square/red.png | Bin 0 -> 2190 bytes .../plugins/iCheck/square/red@2x.png | Bin 0 -> 4490 bytes .../plugins/iCheck/square/square.css | 62 + .../plugins/iCheck/square/square.png | Bin 0 -> 2175 bytes .../plugins/iCheck/square/square@2x.png | Bin 0 -> 4478 bytes .../plugins/iCheck/square/yellow.css | 62 + .../plugins/iCheck/square/yellow.png | Bin 0 -> 2131 bytes .../plugins/iCheck/square/yellow@2x.png | Bin 0 -> 4385 bytes .../jquery.inputmask.date.extensions.js | 488 + .../input-mask/jquery.inputmask.extensions.js | 122 + .../plugins/input-mask/jquery.inputmask.js | 1627 ++ .../jquery.inputmask.numeric.extensions.js | 177 + .../jquery.inputmask.phone.extensions.js | 50 + .../jquery.inputmask.regex.extensions.js | 169 + .../input-mask/phone-codes/phone-be.json | 45 + .../input-mask/phone-codes/phone-codes.json | 294 + .../plugins/input-mask/phone-codes/readme.txt | 1 + .../ionslider/img/sprite-skin-flat.png | Bin 0 -> 304 bytes .../ionslider/img/sprite-skin-nice.png | Bin 0 -> 694 bytes .../plugins/ionslider/ion.rangeSlider.css | 149 + .../plugins/ionslider/ion.rangeSlider.min.js | 76 + .../ionslider/ion.rangeSlider.skinFlat.css | 106 + .../ionslider/ion.rangeSlider.skinNice.css | 102 + .../plugins/jQuery/jquery-2.2.3.min.js | 4 + .../plugins/jQueryUI/jquery-ui.js | 16617 ++++++++++++++++ .../plugins/jQueryUI/jquery-ui.min.js | 13 + .../jvectormap/jquery-jvectormap-1.2.2.css | 40 + .../jvectormap/jquery-jvectormap-1.2.2.min.js | 8 + .../jvectormap/jquery-jvectormap-usa-en.js | 1 + .../jquery-jvectormap-world-mill-en.js | 1 + .../plugins/knob/jquery.knob.js | 805 + .../AdminLTE-2.3.7/plugins/morris/morris.css | 2 + .../AdminLTE-2.3.7/plugins/morris/morris.js | 1892 ++ .../plugins/morris/morris.min.js | 7 + .../AdminLTE-2.3.7/plugins/pace/pace.css | 85 + .../AdminLTE-2.3.7/plugins/pace/pace.js | 935 + .../AdminLTE-2.3.7/plugins/pace/pace.min.css | 1 + .../AdminLTE-2.3.7/plugins/pace/pace.min.js | 2 + .../AdminLTE-2.3.7/plugins/select2/i18n/ar.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/az.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/bg.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/ca.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/cs.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/da.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/de.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/el.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/en.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/es.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/et.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/eu.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/fa.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/fi.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/fr.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/gl.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/he.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/hi.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/hr.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/hu.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/id.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/is.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/it.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/ja.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/km.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/ko.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/lt.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/lv.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/mk.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/ms.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/nb.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/nl.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/pl.js | 3 + .../plugins/select2/i18n/pt-BR.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/pt.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/ro.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/ru.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/sk.js | 3 + .../plugins/select2/i18n/sr-Cyrl.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/sr.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/sv.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/th.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/tr.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/uk.js | 3 + .../AdminLTE-2.3.7/plugins/select2/i18n/vi.js | 3 + .../plugins/select2/i18n/zh-CN.js | 3 + .../plugins/select2/i18n/zh-TW.js | 3 + .../plugins/select2/select2.css | 484 + .../plugins/select2/select2.full.js | 6436 ++++++ .../plugins/select2/select2.full.min.js | 3 + .../AdminLTE-2.3.7/plugins/select2/select2.js | 5725 ++++++ .../plugins/select2/select2.min.css | 1 + .../plugins/select2/select2.min.js | 3 + .../plugins/slimScroll/jquery.slimscroll.js | 474 + .../slimScroll/jquery.slimscroll.min.js | 16 + .../plugins/sparkline/jquery.sparkline.js | 3054 +++ .../plugins/sparkline/jquery.sparkline.min.js | 5 + .../timepicker/bootstrap-timepicker.css | 121 + .../timepicker/bootstrap-timepicker.js | 903 + .../timepicker/bootstrap-timepicker.min.css | 10 + .../timepicker/bootstrap-timepicker.min.js | 5 + .../static/AdminLTE-2.3.7/starter.html | 405 + ...Ceph_Logo_Standard_RGB_White_120411_fa.png | Bin 0 -> 4801 bytes .../pybind/mgr/dashboard/static/favicon.ico | Bin 0 -> 1150 bytes .../dashboard/static/rivets.bundled.min.js | 6 + .../mgr/dashboard/static/underscore-min.js | 6 + .../mgr/{rest/app => dashboard}/types.py | 107 +- ceph/src/pybind/mgr/fsstatus/module.py | 4 +- ceph/src/pybind/mgr/mgr_module.py | 17 + .../mgr/rest/app/fixtures/ceph_fake.json | 1 - .../rest/app/management/commands/api_docs.py | 406 - .../rest/app/manager/osd_request_factory.py | 119 - .../rest/app/manager/pool_request_factory.py | 165 - .../rest/app/manager/request_collection.py | 259 - .../mgr/rest/app/manager/request_factory.py | 24 - .../mgr/rest/app/manager/user_request.py | 553 - ceph/src/pybind/mgr/rest/app/models.py | 2 - .../pybind/mgr/rest/app/serializers/fields.py | 52 - .../src/pybind/mgr/rest/app/serializers/v2.py | 326 - ceph/src/pybind/mgr/rest/app/settings.py | 146 - ceph/src/pybind/mgr/rest/app/urls/__init__.py | 18 - ceph/src/pybind/mgr/rest/app/urls/v2.py | 94 - ceph/src/pybind/mgr/rest/app/util.py | 25 - .../src/pybind/mgr/rest/app/views/__init__.py | 0 .../mgr/rest/app/views/paginated_mixin.py | 36 - .../src/pybind/mgr/rest/app/views/rpc_view.py | 292 - ceph/src/pybind/mgr/rest/app/views/v2.py | 538 - ceph/src/pybind/mgr/rest/logger.py | 8 - ceph/src/pybind/mgr/rest/module.py | 259 - ceph/src/pybind/mgr/restful/__init__.py | 1 + ceph/src/pybind/mgr/restful/api/__init__.py | 37 + ceph/src/pybind/mgr/restful/api/config.py | 86 + ceph/src/pybind/mgr/restful/api/crush.py | 26 + ceph/src/pybind/mgr/restful/api/doc.py | 15 + ceph/src/pybind/mgr/restful/api/mon.py | 44 + ceph/src/pybind/mgr/restful/api/osd.py | 135 + ceph/src/pybind/mgr/restful/api/pool.py | 140 + ceph/src/pybind/mgr/restful/api/request.py | 92 + ceph/src/pybind/mgr/restful/api/server.py | 35 + ceph/src/pybind/mgr/restful/common.py | 150 + ceph/src/pybind/mgr/restful/decorators.py | 77 + ceph/src/pybind/mgr/restful/hooks.py | 9 + ceph/src/pybind/mgr/restful/module.py | 605 + ceph/src/pybind/rados/rados.pxd | 1 + ceph/src/pybind/rados/rados.pyx | 44 +- ceph/src/pybind/rbd/CMakeLists.txt | 2 +- ceph/src/pybind/rbd/rbd.pyx | 41 +- ceph/src/rapidjson/.gitattributes | 22 + ceph/src/rapidjson/.gitmodules | 3 + ceph/src/rapidjson/.travis.yml | 98 + ceph/src/rapidjson/CHANGELOG.md | 158 + ceph/src/rapidjson/CMakeLists.txt | 173 + .../rapidjson/CMakeModules/FindGTestSrc.cmake | 30 + ceph/src/rapidjson/RapidJSON.pc.in | 7 + ceph/src/rapidjson/RapidJSONConfig.cmake.in | 3 + .../rapidjson/RapidJSONConfigVersion.cmake.in | 10 + ceph/src/rapidjson/appveyor.yml | 41 + ceph/src/rapidjson/bin/data/glossary.json | 22 + ceph/src/rapidjson/bin/data/menu.json | 27 + ceph/src/rapidjson/bin/data/readme.txt | 1 + ceph/src/rapidjson/bin/data/sample.json | 3315 +++ ceph/src/rapidjson/bin/data/webapp.json | 88 + ceph/src/rapidjson/bin/data/widget.json | 26 + ceph/src/rapidjson/bin/draft-04/schema | 150 + ceph/src/rapidjson/bin/encodings/utf16be.json | Bin 0 -> 368 bytes .../rapidjson/bin/encodings/utf16bebom.json | Bin 0 -> 370 bytes ceph/src/rapidjson/bin/encodings/utf16le.json | Bin 0 -> 368 bytes .../rapidjson/bin/encodings/utf16lebom.json | Bin 0 -> 370 bytes ceph/src/rapidjson/bin/encodings/utf32be.json | Bin 0 -> 736 bytes .../rapidjson/bin/encodings/utf32bebom.json | Bin 0 -> 740 bytes ceph/src/rapidjson/bin/encodings/utf32le.json | Bin 0 -> 736 bytes .../rapidjson/bin/encodings/utf32lebom.json | Bin 0 -> 740 bytes ceph/src/rapidjson/bin/encodings/utf8.json | 7 + ceph/src/rapidjson/bin/encodings/utf8bom.json | 7 + ceph/src/rapidjson/bin/jsonchecker/fail1.json | 1 + .../src/rapidjson/bin/jsonchecker/fail10.json | 1 + .../src/rapidjson/bin/jsonchecker/fail11.json | 1 + .../src/rapidjson/bin/jsonchecker/fail12.json | 1 + .../src/rapidjson/bin/jsonchecker/fail13.json | 1 + .../src/rapidjson/bin/jsonchecker/fail14.json | 1 + .../src/rapidjson/bin/jsonchecker/fail15.json | 1 + .../src/rapidjson/bin/jsonchecker/fail16.json | 1 + .../src/rapidjson/bin/jsonchecker/fail17.json | 1 + .../src/rapidjson/bin/jsonchecker/fail18.json | 1 + .../src/rapidjson/bin/jsonchecker/fail19.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail2.json | 1 + .../src/rapidjson/bin/jsonchecker/fail20.json | 1 + .../src/rapidjson/bin/jsonchecker/fail21.json | 1 + .../src/rapidjson/bin/jsonchecker/fail22.json | 1 + .../src/rapidjson/bin/jsonchecker/fail23.json | 1 + .../src/rapidjson/bin/jsonchecker/fail24.json | 1 + .../src/rapidjson/bin/jsonchecker/fail25.json | 1 + .../src/rapidjson/bin/jsonchecker/fail26.json | 1 + .../src/rapidjson/bin/jsonchecker/fail27.json | 2 + .../src/rapidjson/bin/jsonchecker/fail28.json | 2 + .../src/rapidjson/bin/jsonchecker/fail29.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail3.json | 1 + .../src/rapidjson/bin/jsonchecker/fail30.json | 1 + .../src/rapidjson/bin/jsonchecker/fail31.json | 1 + .../src/rapidjson/bin/jsonchecker/fail32.json | 1 + .../src/rapidjson/bin/jsonchecker/fail33.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail4.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail5.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail6.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail7.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail8.json | 1 + ceph/src/rapidjson/bin/jsonchecker/fail9.json | 1 + ceph/src/rapidjson/bin/jsonchecker/pass1.json | 58 + ceph/src/rapidjson/bin/jsonchecker/pass2.json | 1 + ceph/src/rapidjson/bin/jsonchecker/pass3.json | 6 + ceph/src/rapidjson/bin/jsonchecker/readme.txt | 3 + ceph/src/rapidjson/bin/jsonschema/.travis.yml | 4 + ceph/src/rapidjson/bin/jsonschema/LICENSE | 19 + ceph/src/rapidjson/bin/jsonschema/README.md | 148 + .../bin/jsonschema/bin/jsonschema_suite | 283 + .../bin/jsonschema/remotes/.DS_Store | Bin 0 -> 6148 bytes .../remotes/folder/folderInteger.json | 3 + .../bin/jsonschema/remotes/integer.json | 3 + .../bin/jsonschema/remotes/subSchemas.json | 8 + .../rapidjson/bin/jsonschema/tests/.DS_Store | Bin 0 -> 6148 bytes .../tests/draft3/additionalItems.json | 82 + .../tests/draft3/additionalProperties.json | 88 + .../bin/jsonschema/tests/draft3/default.json | 49 + .../jsonschema/tests/draft3/dependencies.json | 108 + .../bin/jsonschema/tests/draft3/disallow.json | 80 + .../jsonschema/tests/draft3/divisibleBy.json | 60 + .../bin/jsonschema/tests/draft3/enum.json | 71 + .../bin/jsonschema/tests/draft3/extends.json | 94 + .../bin/jsonschema/tests/draft3/items.json | 46 + .../bin/jsonschema/tests/draft3/maxItems.json | 28 + .../jsonschema/tests/draft3/maxLength.json | 33 + .../bin/jsonschema/tests/draft3/maximum.json | 42 + .../bin/jsonschema/tests/draft3/minItems.json | 28 + .../jsonschema/tests/draft3/minLength.json | 33 + .../bin/jsonschema/tests/draft3/minimum.json | 42 + .../tests/draft3/optional/bignum.json | 107 + .../tests/draft3/optional/format.json | 222 + .../tests/draft3/optional/jsregex.json | 18 + .../draft3/optional/zeroTerminatedFloats.json | 15 + .../bin/jsonschema/tests/draft3/pattern.json | 34 + .../tests/draft3/patternProperties.json | 110 + .../jsonschema/tests/draft3/properties.json | 92 + .../bin/jsonschema/tests/draft3/ref.json | 159 + .../jsonschema/tests/draft3/refRemote.json | 74 + .../bin/jsonschema/tests/draft3/required.json | 53 + .../bin/jsonschema/tests/draft3/type.json | 474 + .../jsonschema/tests/draft3/uniqueItems.json | 79 + .../bin/jsonschema/tests/draft4/.DS_Store | Bin 0 -> 6148 bytes .../tests/draft4/additionalItems.json | 82 + .../tests/draft4/additionalProperties.json | 88 + .../bin/jsonschema/tests/draft4/allOf.json | 112 + .../bin/jsonschema/tests/draft4/anyOf.json | 68 + .../bin/jsonschema/tests/draft4/default.json | 49 + .../jsonschema/tests/draft4/definitions.json | 32 + .../jsonschema/tests/draft4/dependencies.json | 113 + .../bin/jsonschema/tests/draft4/enum.json | 72 + .../bin/jsonschema/tests/draft4/items.json | 46 + .../bin/jsonschema/tests/draft4/maxItems.json | 28 + .../jsonschema/tests/draft4/maxLength.json | 33 + .../tests/draft4/maxProperties.json | 28 + .../bin/jsonschema/tests/draft4/maximum.json | 42 + .../bin/jsonschema/tests/draft4/minItems.json | 28 + .../jsonschema/tests/draft4/minLength.json | 33 + .../tests/draft4/minProperties.json | 28 + .../bin/jsonschema/tests/draft4/minimum.json | 42 + .../jsonschema/tests/draft4/multipleOf.json | 60 + .../bin/jsonschema/tests/draft4/not.json | 96 + .../bin/jsonschema/tests/draft4/oneOf.json | 68 + .../tests/draft4/optional/bignum.json | 107 + .../tests/draft4/optional/format.json | 148 + .../draft4/optional/zeroTerminatedFloats.json | 15 + .../bin/jsonschema/tests/draft4/pattern.json | 34 + .../tests/draft4/patternProperties.json | 110 + .../jsonschema/tests/draft4/properties.json | 92 + .../bin/jsonschema/tests/draft4/ref.json | 159 + .../jsonschema/tests/draft4/refRemote.json | 74 + .../bin/jsonschema/tests/draft4/required.json | 39 + .../bin/jsonschema/tests/draft4/type.json | 330 + .../jsonschema/tests/draft4/uniqueItems.json | 79 + ceph/src/rapidjson/bin/jsonschema/tox.ini | 8 + ceph/src/rapidjson/bin/types/booleans.json | 102 + ceph/src/rapidjson/bin/types/floats.json | 102 + ceph/src/rapidjson/bin/types/guids.json | 102 + ceph/src/rapidjson/bin/types/integers.json | 102 + ceph/src/rapidjson/bin/types/mixed.json | 592 + ceph/src/rapidjson/bin/types/nulls.json | 102 + ceph/src/rapidjson/bin/types/paragraphs.json | 102 + ceph/src/rapidjson/bin/types/readme.txt | 1 + ceph/src/rapidjson/doc/CMakeLists.txt | 25 + ceph/src/rapidjson/doc/Doxyfile.in | 2369 +++ ceph/src/rapidjson/doc/Doxyfile.zh-cn.in | 2369 +++ .../rapidjson/doc/diagram/architecture.dot | 50 + .../rapidjson/doc/diagram/architecture.png | Bin 0 -> 16569 bytes .../rapidjson/doc/diagram/insituparsing.dot | 65 + .../rapidjson/doc/diagram/insituparsing.png | Bin 0 -> 37281 bytes .../iterative-parser-states-diagram.dot | 62 + .../iterative-parser-states-diagram.png | Bin 0 -> 92378 bytes ceph/src/rapidjson/doc/diagram/makefile | 8 + ceph/src/rapidjson/doc/diagram/move1.dot | 47 + ceph/src/rapidjson/doc/diagram/move1.png | Bin 0 -> 16081 bytes ceph/src/rapidjson/doc/diagram/move2.dot | 62 + ceph/src/rapidjson/doc/diagram/move2.png | Bin 0 -> 41517 bytes ceph/src/rapidjson/doc/diagram/move3.dot | 60 + ceph/src/rapidjson/doc/diagram/move3.png | Bin 0 -> 36371 bytes .../rapidjson/doc/diagram/normalparsing.dot | 56 + .../rapidjson/doc/diagram/normalparsing.png | Bin 0 -> 32887 bytes ceph/src/rapidjson/doc/diagram/simpledom.dot | 54 + ceph/src/rapidjson/doc/diagram/simpledom.png | Bin 0 -> 43670 bytes ceph/src/rapidjson/doc/diagram/tutorial.dot | 58 + ceph/src/rapidjson/doc/diagram/tutorial.png | Bin 0 -> 44634 bytes .../rapidjson/doc/diagram/utilityclass.dot | 73 + .../rapidjson/doc/diagram/utilityclass.png | Bin 0 -> 99993 bytes ceph/src/rapidjson/doc/dom.md | 280 + ceph/src/rapidjson/doc/dom.zh-cn.md | 284 + ceph/src/rapidjson/doc/encoding.md | 146 + ceph/src/rapidjson/doc/encoding.zh-cn.md | 152 + ceph/src/rapidjson/doc/faq.md | 289 + ceph/src/rapidjson/doc/faq.zh-cn.md | 290 + ceph/src/rapidjson/doc/features.md | 104 + ceph/src/rapidjson/doc/features.zh-cn.md | 103 + ceph/src/rapidjson/doc/internals.md | 365 + ceph/src/rapidjson/doc/logo/rapidjson.png | Bin 0 -> 5259 bytes ceph/src/rapidjson/doc/logo/rapidjson.svg | 119 + ceph/src/rapidjson/doc/misc/DoxygenLayout.xml | 194 + ceph/src/rapidjson/doc/misc/doxygenextra.css | 274 + ceph/src/rapidjson/doc/misc/footer.html | 11 + ceph/src/rapidjson/doc/misc/header.html | 24 + ceph/src/rapidjson/doc/npm.md | 31 + ceph/src/rapidjson/doc/performance.md | 26 + ceph/src/rapidjson/doc/performance.zh-cn.md | 26 + ceph/src/rapidjson/doc/pointer.md | 234 + ceph/src/rapidjson/doc/pointer.zh-cn.md | 234 + ceph/src/rapidjson/doc/sax.md | 486 + ceph/src/rapidjson/doc/sax.zh-cn.md | 487 + ceph/src/rapidjson/doc/schema.md | 237 + ceph/src/rapidjson/doc/schema.zh-cn.md | 237 + ceph/src/rapidjson/doc/stream.md | 426 + ceph/src/rapidjson/doc/stream.zh-cn.md | 426 + ceph/src/rapidjson/doc/tutorial.md | 536 + ceph/src/rapidjson/doc/tutorial.zh-cn.md | 534 + ceph/src/rapidjson/docker/debian/Dockerfile | 8 + ceph/src/rapidjson/example/CMakeLists.txt | 42 + .../example/capitalize/capitalize.cpp | 67 + .../rapidjson/example/condense/condense.cpp | 32 + .../rapidjson/example/filterkey/filterkey.cpp | 135 + .../example/filterkeydom/filterkeydom.cpp | 170 + ceph/src/rapidjson/example/jsonx/jsonx.cpp | 207 + .../example/messagereader/messagereader.cpp | 105 + .../example/parsebyparts/parsebyparts.cpp | 173 + ceph/src/rapidjson/example/pretty/pretty.cpp | 30 + .../example/prettyauto/prettyauto.cpp | 56 + .../schemavalidator/schemavalidator.cpp | 72 + .../rapidjson/example/serialize/serialize.cpp | 173 + .../rapidjson/example/simpledom/simpledom.cpp | 29 + .../example/simplereader/simplereader.cpp | 42 + .../example/simplewriter/simplewriter.cpp | 36 + .../rapidjson/example/tutorial/tutorial.cpp | 151 + .../rapidjson/include/rapidjson/allocators.h | 271 + .../rapidjson/include/rapidjson/document.h | 2575 +++ .../include/rapidjson/encodedstream.h | 299 + .../rapidjson/include/rapidjson/encodings.h | 716 + .../rapidjson/include/rapidjson/error/en.h | 74 + .../rapidjson/include/rapidjson/error/error.h | 155 + .../include/rapidjson/filereadstream.h | 99 + .../include/rapidjson/filewritestream.h | 104 + ceph/src/rapidjson/include/rapidjson/fwd.h | 151 + .../include/rapidjson/internal/biginteger.h | 290 + .../include/rapidjson/internal/diyfp.h | 258 + .../include/rapidjson/internal/dtoa.h | 245 + .../include/rapidjson/internal/ieee754.h | 78 + .../include/rapidjson/internal/itoa.h | 304 + .../include/rapidjson/internal/meta.h | 181 + .../include/rapidjson/internal/pow10.h | 55 + .../include/rapidjson/internal/regex.h | 701 + .../include/rapidjson/internal/stack.h | 230 + .../include/rapidjson/internal/strfunc.h | 55 + .../include/rapidjson/internal/strtod.h | 269 + .../include/rapidjson/internal/swap.h | 46 + .../include/rapidjson/istreamwrapper.h | 115 + .../include/rapidjson/memorybuffer.h | 70 + .../include/rapidjson/memorystream.h | 71 + .../include/rapidjson/msinttypes/inttypes.h | 316 + .../include/rapidjson/msinttypes/stdint.h | 300 + .../include/rapidjson/ostreamwrapper.h | 81 + .../src/rapidjson/include/rapidjson/pointer.h | 1358 ++ .../include/rapidjson/prettywriter.h | 255 + .../rapidjson/include/rapidjson/rapidjson.h | 615 + ceph/src/rapidjson/include/rapidjson/reader.h | 1879 ++ ceph/src/rapidjson/include/rapidjson/schema.h | 2006 ++ ceph/src/rapidjson/include/rapidjson/stream.h | 179 + .../include/rapidjson/stringbuffer.h | 117 + ceph/src/rapidjson/include/rapidjson/writer.h | 610 + ceph/src/rapidjson/include_dirs.js | 2 + ceph/src/rapidjson/library.json | 12 + ceph/src/rapidjson/license.txt | 57 + ceph/src/rapidjson/package.json | 24 + ceph/src/rapidjson/rapidjson.autopkg | 75 + ceph/src/rapidjson/readme.md | 160 + ceph/src/rapidjson/readme.zh-cn.md | 152 + ceph/src/rapidjson/test/CMakeLists.txt | 20 + .../rapidjson/test/perftest/CMakeLists.txt | 26 + ceph/src/rapidjson/test/perftest/misctest.cpp | 974 + ceph/src/rapidjson/test/perftest/perftest.cpp | 24 + ceph/src/rapidjson/test/perftest/perftest.h | 182 + .../rapidjson/test/perftest/platformtest.cpp | 166 + .../rapidjson/test/perftest/rapidjsontest.cpp | 441 + .../rapidjson/test/perftest/schematest.cpp | 216 + .../rapidjson/test/unittest/CMakeLists.txt | 92 + .../test/unittest/allocatorstest.cpp | 102 + .../test/unittest/bigintegertest.cpp | 133 + .../rapidjson/test/unittest/documenttest.cpp | 652 + ceph/src/rapidjson/test/unittest/dtoatest.cpp | 98 + .../test/unittest/encodedstreamtest.cpp | 313 + .../rapidjson/test/unittest/encodingstest.cpp | 451 + .../test/unittest/filestreamtest.cpp | 112 + ceph/src/rapidjson/test/unittest/fwdtest.cpp | 227 + .../test/unittest/istreamwrappertest.cpp | 181 + ceph/src/rapidjson/test/unittest/itoatest.cpp | 160 + .../test/unittest/jsoncheckertest.cpp | 99 + .../rapidjson/test/unittest/namespacetest.cpp | 70 + .../test/unittest/ostreamwrappertest.cpp | 91 + .../rapidjson/test/unittest/pointertest.cpp | 1524 ++ .../test/unittest/prettywritertest.cpp | 203 + .../rapidjson/test/unittest/readertest.cpp | 1844 ++ .../src/rapidjson/test/unittest/regextest.cpp | 592 + .../rapidjson/test/unittest/schematest.cpp | 1313 ++ ceph/src/rapidjson/test/unittest/simdtest.cpp | 215 + .../rapidjson/test/unittest/strfunctest.cpp | 30 + .../test/unittest/stringbuffertest.cpp | 170 + .../rapidjson/test/unittest/strtodtest.cpp | 132 + ceph/src/rapidjson/test/unittest/unittest.cpp | 51 + ceph/src/rapidjson/test/unittest/unittest.h | 135 + .../src/rapidjson/test/unittest/valuetest.cpp | 1792 ++ .../rapidjson/test/unittest/writertest.cpp | 497 + .../rapidjson/thirdparty/gtest/.travis.yml | 46 + .../rapidjson/thirdparty/gtest/CMakeLists.txt | 16 + ceph/src/rapidjson/thirdparty/gtest/README.md | 141 + .../thirdparty/gtest/googlemock/CHANGES | 126 + .../gtest/googlemock/CMakeLists.txt | 202 + .../thirdparty/gtest/googlemock/CONTRIBUTORS | 40 + .../thirdparty/gtest/googlemock/LICENSE | 28 + .../thirdparty/gtest/googlemock/Makefile.am | 224 + .../thirdparty/gtest/googlemock/README.md | 333 + .../gtest/googlemock/build-aux/.keep} | 0 .../thirdparty/gtest/googlemock/configure.ac | 146 + .../gtest/googlemock/docs/CheatSheet.md | 562 + .../gtest/googlemock/docs/CookBook.md | 3675 ++++ .../gtest/googlemock/docs/DesignDoc.md | 280 + .../gtest/googlemock/docs/DevGuide.md | 132 + .../gtest/googlemock/docs/Documentation.md | 12 + .../gtest/googlemock/docs/ForDummies.md | 439 + .../docs/FrequentlyAskedQuestions.md | 628 + .../gtest/googlemock/docs/KnownIssues.md | 19 + .../gtest/googlemock/docs/v1_5/CheatSheet.md | 525 + .../gtest/googlemock/docs/v1_5/CookBook.md | 3250 +++ .../googlemock/docs/v1_5/Documentation.md | 11 + .../gtest/googlemock/docs/v1_5/ForDummies.md | 439 + .../docs/v1_5/FrequentlyAskedQuestions.md | 624 + .../gtest/googlemock/docs/v1_6/CheatSheet.md | 534 + .../gtest/googlemock/docs/v1_6/CookBook.md | 3342 ++++ .../googlemock/docs/v1_6/Documentation.md | 12 + .../gtest/googlemock/docs/v1_6/ForDummies.md | 439 + .../docs/v1_6/FrequentlyAskedQuestions.md | 628 + .../gtest/googlemock/docs/v1_7/CheatSheet.md | 556 + .../gtest/googlemock/docs/v1_7/CookBook.md | 3432 ++++ .../googlemock/docs/v1_7/Documentation.md | 12 + .../gtest/googlemock/docs/v1_7/ForDummies.md | 439 + .../docs/v1_7/FrequentlyAskedQuestions.md | 628 + .../googlemock/include/gmock/gmock-actions.h | 1205 ++ .../include/gmock/gmock-cardinalities.h | 147 + .../include/gmock/gmock-generated-actions.h | 2377 +++ .../gmock/gmock-generated-actions.h.pump | 794 + .../gmock/gmock-generated-function-mockers.h | 1095 + .../gmock-generated-function-mockers.h.pump | 291 + .../include/gmock/gmock-generated-matchers.h | 2179 ++ .../gmock/gmock-generated-matchers.h.pump | 672 + .../gmock/gmock-generated-nice-strict.h | 397 + .../gmock/gmock-generated-nice-strict.h.pump | 161 + .../googlemock/include/gmock/gmock-matchers.h | 4399 ++++ .../include/gmock/gmock-more-actions.h | 246 + .../include/gmock/gmock-more-matchers.h | 58 + .../include/gmock/gmock-spec-builders.h | 1847 ++ .../gtest/googlemock/include/gmock/gmock.h | 94 + .../internal/custom/gmock-generated-actions.h | 8 + .../custom/gmock-generated-actions.h.pump | 10 + .../gmock/internal/custom/gmock-matchers.h | 39 + .../gmock/internal/custom/gmock-port.h | 46 + .../internal/gmock-generated-internal-utils.h | 279 + .../gmock-generated-internal-utils.h.pump | 136 + .../gmock/internal/gmock-internal-utils.h | 511 + .../include/gmock/internal/gmock-port.h | 91 + .../thirdparty/gtest/googlemock/make/Makefile | 101 + .../gtest/googlemock/msvc/2005/gmock.sln | 32 + .../gtest/googlemock/msvc/2005/gmock.vcproj | 191 + .../googlemock/msvc/2005/gmock_config.vsprops | 15 + .../googlemock/msvc/2005/gmock_main.vcproj | 187 + .../googlemock/msvc/2005/gmock_test.vcproj | 201 + .../gtest/googlemock/msvc/2010/gmock.sln | 32 + .../gtest/googlemock/msvc/2010/gmock.vcxproj | 82 + .../googlemock/msvc/2010/gmock_config.props | 19 + .../googlemock/msvc/2010/gmock_main.vcxproj | 88 + .../googlemock/msvc/2010/gmock_test.vcxproj | 101 + .../gtest/googlemock/msvc/2015/gmock.sln | 32 + .../gtest/googlemock/msvc/2015/gmock.vcxproj | 84 + .../googlemock/msvc/2015/gmock_config.props | 19 + .../googlemock/msvc/2015/gmock_main.vcxproj | 90 + .../googlemock/msvc/2015/gmock_test.vcxproj | 103 + .../googlemock/scripts/fuse_gmock_files.py | 240 + .../googlemock/scripts/generator/LICENSE | 203 + .../gtest/googlemock/scripts/generator/README | 35 + .../scripts/generator/README.cppclean | 115 + .../scripts/generator/cpp}/__init__.py | 0 .../googlemock/scripts/generator/cpp/ast.py | 1733 ++ .../scripts/generator/cpp/gmock_class.py | 227 + .../scripts/generator/cpp/gmock_class_test.py | 448 + .../scripts/generator/cpp/keywords.py | 59 + .../scripts/generator/cpp/tokenize.py | 287 + .../googlemock/scripts/generator/cpp/utils.py | 41 + .../googlemock/scripts/generator/gmock_gen.py | 31 + .../gtest/googlemock/scripts/gmock-config.in | 303 + .../gtest/googlemock/scripts/gmock_doctor.py | 640 + .../gtest/googlemock/scripts/upload.py | 1387 ++ .../gtest/googlemock/scripts/upload_gmock.py | 78 + .../gtest/googlemock/src/gmock-all.cc | 47 + .../googlemock/src/gmock-cardinalities.cc | 156 + .../googlemock/src/gmock-internal-utils.cc | 174 + .../gtest/googlemock/src/gmock-matchers.cc | 498 + .../googlemock/src/gmock-spec-builders.cc | 823 + .../thirdparty/gtest/googlemock/src/gmock.cc | 183 + .../gtest/googlemock/src/gmock_main.cc | 54 + .../googlemock/test/gmock-actions_test.cc | 1411 ++ .../test/gmock-cardinalities_test.cc | 428 + .../test/gmock-generated-actions_test.cc | 1228 ++ .../gmock-generated-function-mockers_test.cc | 622 + .../gmock-generated-internal-utils_test.cc | 127 + .../test/gmock-generated-matchers_test.cc | 1286 ++ .../test/gmock-internal-utils_test.cc | 699 + .../googlemock/test/gmock-matchers_test.cc | 5648 ++++++ .../test/gmock-more-actions_test.cc | 708 + .../googlemock/test/gmock-nice-strict_test.cc | 424 + .../gtest/googlemock/test/gmock-port_test.cc | 43 + .../test/gmock-spec-builders_test.cc | 2644 +++ .../gtest/googlemock/test/gmock_all_test.cc | 51 + .../gtest/googlemock/test/gmock_ex_test.cc | 81 + .../gtest/googlemock/test/gmock_leak_test.py | 108 + .../gtest/googlemock/test/gmock_leak_test_.cc | 100 + .../gtest/googlemock/test/gmock_link2_test.cc | 40 + .../gtest/googlemock/test/gmock_link_test.cc | 40 + .../gtest/googlemock/test/gmock_link_test.h | 669 + .../googlemock/test/gmock_output_test.py | 180 + .../googlemock/test/gmock_output_test_.cc | 291 + .../test/gmock_output_test_golden.txt | 310 + .../googlemock/test/gmock_stress_test.cc | 322 + .../gtest/googlemock/test/gmock_test.cc | 220 + .../gtest/googlemock/test/gmock_test_utils.py | 112 + .../thirdparty/gtest/googletest/CHANGES | 157 + .../gtest/googletest/CMakeLists.txt | 286 + .../thirdparty/gtest/googletest/CONTRIBUTORS | 37 + .../thirdparty/gtest/googletest/LICENSE | 28 + .../thirdparty/gtest/googletest/Makefile.am | 310 + .../thirdparty/gtest/googletest/README.md | 280 + .../gtest/googletest/build-aux/.keep} | 0 .../googletest/cmake/internal_utils.cmake | 242 + .../gtest/googletest/codegear/gtest.cbproj | 138 + .../gtest/googletest/codegear/gtest.groupproj | 54 + .../gtest/googletest/codegear/gtest_all.cc | 38 + .../gtest/googletest/codegear/gtest_link.cc | 40 + .../googletest/codegear/gtest_main.cbproj | 82 + .../googletest/codegear/gtest_unittest.cbproj | 88 + .../thirdparty/gtest/googletest/configure.ac | 68 + .../gtest/googletest/docs/AdvancedGuide.md | 2182 ++ .../gtest/googletest/docs/DevGuide.md | 126 + .../gtest/googletest/docs/Documentation.md | 14 + .../thirdparty/gtest/googletest/docs/FAQ.md | 1087 + .../gtest/googletest/docs/Primer.md | 502 + .../gtest/googletest/docs/PumpManual.md | 177 + .../gtest/googletest/docs/Samples.md | 14 + .../googletest/docs/V1_5_AdvancedGuide.md | 2096 ++ .../googletest/docs/V1_5_Documentation.md | 12 + .../gtest/googletest/docs/V1_5_FAQ.md | 886 + .../gtest/googletest/docs/V1_5_Primer.md | 497 + .../gtest/googletest/docs/V1_5_PumpManual.md | 177 + .../gtest/googletest/docs/V1_5_XcodeGuide.md | 93 + .../googletest/docs/V1_6_AdvancedGuide.md | 2178 ++ .../googletest/docs/V1_6_Documentation.md | 14 + .../gtest/googletest/docs/V1_6_FAQ.md | 1038 + .../gtest/googletest/docs/V1_6_Primer.md | 501 + .../gtest/googletest/docs/V1_6_PumpManual.md | 177 + .../gtest/googletest/docs/V1_6_Samples.md | 14 + .../gtest/googletest/docs/V1_6_XcodeGuide.md | 93 + .../googletest/docs/V1_7_AdvancedGuide.md | 2181 ++ .../googletest/docs/V1_7_Documentation.md | 14 + .../gtest/googletest/docs/V1_7_FAQ.md | 1082 + .../gtest/googletest/docs/V1_7_Primer.md | 501 + .../gtest/googletest/docs/V1_7_PumpManual.md | 177 + .../gtest/googletest/docs/V1_7_Samples.md | 14 + .../gtest/googletest/docs/V1_7_XcodeGuide.md | 93 + .../gtest/googletest/docs/XcodeGuide.md | 93 + .../include/gtest/gtest-death-test.h | 294 + .../googletest/include/gtest/gtest-message.h | 250 + .../include/gtest/gtest-param-test.h | 1444 ++ .../include/gtest/gtest-param-test.h.pump | 510 + .../googletest/include/gtest/gtest-printers.h | 993 + .../googletest/include/gtest/gtest-spi.h | 232 + .../include/gtest/gtest-test-part.h | 179 + .../include/gtest/gtest-typed-test.h | 263 + .../gtest/googletest/include/gtest/gtest.h | 2236 +++ .../include/gtest/gtest_pred_impl.h | 358 + .../googletest/include/gtest/gtest_prod.h | 58 + .../gtest/internal/custom/gtest-port.h | 69 + .../gtest/internal/custom/gtest-printers.h | 42 + .../include/gtest/internal/custom/gtest.h | 41 + .../internal/gtest-death-test-internal.h | 319 + .../include/gtest/internal/gtest-filepath.h | 206 + .../include/gtest/internal/gtest-internal.h | 1238 ++ .../include/gtest/internal/gtest-linked_ptr.h | 243 + .../internal/gtest-param-util-generated.h | 5146 +++++ .../gtest-param-util-generated.h.pump | 286 + .../include/gtest/internal/gtest-param-util.h | 731 + .../include/gtest/internal/gtest-port-arch.h | 93 + .../include/gtest/internal/gtest-port.h | 2554 +++ .../include/gtest/internal/gtest-string.h | 167 + .../include/gtest/internal/gtest-tuple.h | 1020 + .../include/gtest/internal/gtest-tuple.h.pump | 347 + .../include/gtest/internal/gtest-type-util.h | 3331 ++++ .../gtest/internal/gtest-type-util.h.pump | 297 + .../gtest/googletest/m4/acx_pthread.m4 | 363 + .../thirdparty/gtest/googletest/m4/gtest.m4 | 74 + .../thirdparty/gtest/googletest/make/Makefile | 82 + .../gtest/googletest/msvc/gtest-md.sln | 45 + .../gtest/googletest/msvc/gtest-md.vcproj | 126 + .../gtest/googletest/msvc/gtest.sln | 45 + .../gtest/googletest/msvc/gtest.vcproj | 126 + .../googletest/msvc/gtest_main-md.vcproj | 129 + .../gtest/googletest/msvc/gtest_main.vcproj | 129 + .../googletest/msvc/gtest_prod_test-md.vcproj | 164 + .../googletest/msvc/gtest_prod_test.vcproj | 164 + .../googletest/msvc/gtest_unittest-md.vcproj | 147 + .../googletest/msvc/gtest_unittest.vcproj | 147 + .../gtest/googletest/samples/prime_tables.h | 123 + .../gtest/googletest/samples/sample1.cc | 68 + .../gtest/googletest/samples/sample1.h | 43 + .../googletest/samples/sample10_unittest.cc | 144 + .../googletest/samples/sample1_unittest.cc | 153 + .../gtest/googletest/samples/sample2.cc | 56 + .../gtest/googletest/samples/sample2.h | 85 + .../googletest/samples/sample2_unittest.cc | 109 + .../gtest/googletest/samples/sample3-inl.h | 172 + .../googletest/samples/sample3_unittest.cc | 151 + .../gtest/googletest/samples/sample4.cc | 46 + .../gtest/googletest/samples/sample4.h | 53 + .../googletest/samples/sample4_unittest.cc | 45 + .../googletest/samples/sample5_unittest.cc | 199 + .../googletest/samples/sample6_unittest.cc | 224 + .../googletest/samples/sample7_unittest.cc | 130 + .../googletest/samples/sample8_unittest.cc | 173 + .../googletest/samples/sample9_unittest.cc | 160 + .../gtest/googletest/scripts/common.py | 83 + .../googletest/scripts/fuse_gtest_files.py | 253 + .../googletest/scripts/gen_gtest_pred_impl.py | 730 + .../gtest/googletest/scripts/gtest-config.in | 274 + .../gtest/googletest/scripts/pump.py | 855 + .../gtest/googletest/scripts/release_docs.py | 158 + .../gtest/googletest/scripts/test/Makefile | 59 + .../gtest/googletest/scripts/upload.py | 1387 ++ .../gtest/googletest/scripts/upload_gtest.py | 78 + .../gtest/googletest/src/gtest-all.cc | 48 + .../gtest/googletest/src/gtest-death-test.cc | 1342 ++ .../gtest/googletest/src/gtest-filepath.cc | 387 + .../gtest/googletest/src/gtest-internal-inl.h | 1183 ++ .../gtest/googletest/src/gtest-port.cc | 1259 ++ .../gtest/googletest/src/gtest-printers.cc | 373 + .../gtest/googletest/src/gtest-test-part.cc | 110 + .../gtest/googletest/src/gtest-typed-test.cc | 118 + .../thirdparty/gtest/googletest/src/gtest.cc | 5388 +++++ .../gtest/googletest/src/gtest_main.cc | 38 + .../test/gtest-death-test_ex_test.cc | 93 + .../googletest/test/gtest-death-test_test.cc | 1427 ++ .../googletest/test/gtest-filepath_test.cc | 662 + .../googletest/test/gtest-linked_ptr_test.cc | 154 + .../googletest/test/gtest-listener_test.cc | 311 + .../googletest/test/gtest-message_test.cc | 159 + .../googletest/test/gtest-options_test.cc | 215 + .../googletest/test/gtest-param-test2_test.cc | 65 + .../googletest/test/gtest-param-test_test.cc | 1055 + .../googletest/test/gtest-param-test_test.h | 57 + .../gtest/googletest/test/gtest-port_test.cc | 1304 ++ .../googletest/test/gtest-printers_test.cc | 1635 ++ .../googletest/test/gtest-test-part_test.cc | 208 + .../gtest/googletest/test/gtest-tuple_test.cc | 320 + .../googletest/test/gtest-typed-test2_test.cc | 45 + .../googletest/test/gtest-typed-test_test.cc | 380 + .../googletest/test/gtest-typed-test_test.h | 66 + .../test/gtest-unittest-api_test.cc | 341 + .../gtest/googletest/test/gtest_all_test.cc | 47 + .../test/gtest_break_on_failure_unittest.py | 212 + .../test/gtest_break_on_failure_unittest_.cc | 88 + .../test/gtest_catch_exceptions_test.py | 237 + .../test/gtest_catch_exceptions_test_.cc | 311 + .../gtest/googletest/test/gtest_color_test.py | 130 + .../googletest/test/gtest_color_test_.cc | 71 + .../googletest/test/gtest_env_var_test.py | 117 + .../googletest/test/gtest_env_var_test_.cc | 126 + .../googletest/test/gtest_environment_test.cc | 192 + .../googletest/test/gtest_filter_unittest.py | 636 + .../googletest/test/gtest_filter_unittest_.cc | 140 + .../gtest/googletest/test/gtest_help_test.py | 172 + .../gtest/googletest/test/gtest_help_test_.cc | 46 + .../test/gtest_list_tests_unittest.py | 207 + .../test/gtest_list_tests_unittest_.cc | 157 + .../googletest/test/gtest_main_unittest.cc | 45 + .../googletest/test/gtest_no_test_unittest.cc | 56 + .../googletest/test/gtest_output_test.py | 340 + .../googletest/test/gtest_output_test_.cc | 1062 + .../test/gtest_output_test_golden_lin.txt | 743 + .../test/gtest_pred_impl_unittest.cc | 2427 +++ .../test/gtest_premature_exit_test.cc | 127 + .../gtest/googletest/test/gtest_prod_test.cc | 57 + .../googletest/test/gtest_repeat_test.cc | 253 + .../googletest/test/gtest_shuffle_test.py | 325 + .../googletest/test/gtest_shuffle_test_.cc | 103 + .../googletest/test/gtest_sole_header_test.cc | 57 + .../googletest/test/gtest_stress_test.cc | 256 + .../gtest/googletest/test/gtest_test_utils.py | 320 + .../test/gtest_throw_on_failure_ex_test.cc | 92 + .../test/gtest_throw_on_failure_test.py | 171 + .../test/gtest_throw_on_failure_test_.cc | 72 + .../test/gtest_uninitialized_test.py | 70 + .../test/gtest_uninitialized_test_.cc | 43 + .../gtest/googletest/test/gtest_unittest.cc | 7706 +++++++ .../test/gtest_xml_outfile1_test_.cc | 49 + .../test/gtest_xml_outfile2_test_.cc | 49 + .../test/gtest_xml_outfiles_test.py | 132 + .../test/gtest_xml_output_unittest.py | 308 + .../test/gtest_xml_output_unittest_.cc | 181 + .../googletest/test/gtest_xml_test_utils.py | 194 + .../gtest/googletest/test/production.cc | 36 + .../gtest/googletest/test/production.h | 55 + .../xcode/Config/DebugProject.xcconfig | 30 + .../xcode/Config/FrameworkTarget.xcconfig | 17 + .../googletest/xcode/Config/General.xcconfig | 41 + .../xcode/Config/ReleaseProject.xcconfig | 32 + .../xcode/Config/StaticLibraryTarget.xcconfig | 18 + .../xcode/Config/TestTarget.xcconfig | 8 + .../googletest/xcode/Resources/Info.plist | 30 + .../xcode/Samples/FrameworkSample/Info.plist | 28 + .../WidgetFramework.xcodeproj/project.pbxproj | 457 + .../xcode/Samples/FrameworkSample/runtests.sh | 62 + .../xcode/Samples/FrameworkSample/widget.cc | 63 + .../xcode/Samples/FrameworkSample/widget.h | 59 + .../Samples/FrameworkSample/widget_test.cc | 68 + .../googletest/xcode/Scripts/runtests.sh | 65 + .../xcode/Scripts/versiongenerate.py | 100 + .../xcode/gtest.xcodeproj/project.pbxproj | 1135 ++ ceph/src/rapidjson/thirdparty/gtest/travis.sh | 15 + ceph/src/rapidjson/travis-doxygen.sh | 122 + ceph/src/rbd_replay/CMakeLists.txt | 2 +- ceph/src/rbd_replay/Replayer.cc | 14 +- ceph/src/rbd_replay/rbd-replay.cc | 2 +- ceph/src/rgw/CMakeLists.txt | 56 +- ceph/src/rgw/librgw.cc | 4 +- ceph/src/rgw/rgw_acl.cc | 35 +- ceph/src/rgw/rgw_acl.h | 13 +- ceph/src/rgw/rgw_acl_s3.cc | 6 +- ceph/src/rgw/rgw_acl_s3.h | 5 +- ceph/src/rgw/rgw_acl_swift.cc | 13 +- ceph/src/rgw/rgw_admin.cc | 677 +- ceph/src/rgw/rgw_auth.cc | 107 +- ceph/src/rgw/rgw_auth.h | 24 +- ceph/src/rgw/rgw_auth_filters.h | 5 + ceph/src/rgw/rgw_auth_keystone.cc | 27 +- ceph/src/rgw/rgw_auth_keystone.h | 21 +- ceph/src/rgw/rgw_auth_registry.h | 32 +- ceph/src/rgw/rgw_auth_s3.cc | 994 +- ceph/src/rgw/rgw_auth_s3.h | 333 +- ceph/src/rgw/rgw_b64.h | 30 +- ceph/src/rgw/rgw_basic_types.cc | 28 + ceph/src/rgw/rgw_basic_types.h | 82 + ceph/src/rgw/rgw_boost_asio_coroutine.h | 67 - ceph/src/rgw/rgw_boost_asio_yield.h | 78 - ceph/src/rgw/rgw_bucket.cc | 32 +- ceph/src/rgw/rgw_bucket.h | 7 +- ceph/src/rgw/rgw_civetweb.cc | 2 +- ceph/src/rgw/rgw_civetweb_frontend.cc | 1 + ceph/src/rgw/rgw_client_io.cc | 22 - ceph/src/rgw/rgw_client_io.h | 51 +- ceph/src/rgw/rgw_common.cc | 514 +- ceph/src/rgw/rgw_common.h | 287 +- ceph/src/rgw/rgw_compression.cc | 13 +- ceph/src/rgw/rgw_coroutine.cc | 4 +- ceph/src/rgw/rgw_coroutine.h | 2 +- ceph/src/rgw/rgw_cors_s3.h | 3 - ceph/src/rgw/rgw_cors_swift.h | 2 - ceph/src/rgw/rgw_cr_rados.cc | 8 +- ceph/src/rgw/rgw_cr_rados.h | 27 +- ceph/src/rgw/rgw_crypt.cc | 165 +- ceph/src/rgw/rgw_crypt.h | 2 +- ceph/src/rgw/rgw_crypt_sanitize.h | 6 +- ceph/src/rgw/rgw_data_sync.cc | 113 +- ceph/src/rgw/rgw_data_sync.h | 14 +- ceph/src/rgw/rgw_dencoder.cc | 1 + ceph/src/rgw/rgw_env.cc | 58 +- ceph/src/rgw/rgw_es_main.cc | 77 + ceph/src/rgw/rgw_es_query.cc | 660 + ceph/src/rgw/rgw_es_query.h | 162 + ceph/src/rgw/rgw_file.cc | 127 +- ceph/src/rgw/rgw_file.h | 76 +- ceph/src/rgw/rgw_gc.cc | 20 +- ceph/src/rgw/rgw_http_client.cc | 13 +- ceph/src/rgw/rgw_http_client.h | 8 +- ceph/src/rgw/rgw_http_errors.h | 139 +- ceph/src/rgw/rgw_iam_policy.cc | 1520 ++ ceph/src/rgw/rgw_iam_policy.h | 466 + ceph/src/rgw/rgw_iam_policy_keywords.gperf | 127 + ceph/src/rgw/rgw_iam_policy_keywords.h | 139 + ceph/src/rgw/rgw_json_enc.cc | 26 +- ceph/src/rgw/rgw_lc.cc | 48 +- ceph/src/rgw/rgw_lc.h | 24 +- ceph/src/rgw/rgw_lc_s3.cc | 26 +- ceph/src/rgw/rgw_lc_s3.h | 50 +- ceph/src/rgw/rgw_loadgen.cc | 14 +- ceph/src/rgw/rgw_loadgen_process.cc | 4 +- ceph/src/rgw/rgw_log.cc | 4 +- ceph/src/rgw/rgw_log.h | 1 - ceph/src/rgw/rgw_main.cc | 16 +- ceph/src/rgw/rgw_metadata.cc | 4 +- ceph/src/rgw/rgw_object_expirer.cc | 2 +- ceph/src/rgw/rgw_object_expirer_core.h | 10 +- ceph/src/rgw/rgw_op.cc | 948 +- ceph/src/rgw/rgw_op.h | 137 +- ceph/src/rgw/rgw_orphan.cc | 3 +- ceph/src/rgw/rgw_period_pusher.cc | 3 +- ceph/src/rgw/rgw_process.h | 2 +- ceph/src/rgw/rgw_quota.cc | 28 + ceph/src/rgw/rgw_quota.h | 5 + ceph/src/rgw/rgw_rados.cc | 898 +- ceph/src/rgw/rgw_rados.h | 188 +- ceph/src/rgw/rgw_realm_reloader.cc | 3 +- ceph/src/rgw/rgw_replica_log.h | 2 - ceph/src/rgw/rgw_request.h | 4 +- ceph/src/rgw/rgw_reshard.cc | 928 + ceph/src/rgw/rgw_reshard.h | 127 + ceph/src/rgw/rgw_rest.cc | 193 +- ceph/src/rgw/rgw_rest.h | 5 +- ceph/src/rgw/rgw_rest_client.cc | 84 +- ceph/src/rgw/rgw_rest_client.h | 8 +- ceph/src/rgw/rgw_rest_conn.cc | 39 +- ceph/src/rgw/rgw_rest_conn.h | 16 +- ceph/src/rgw/rgw_rest_log.cc | 1 + ceph/src/rgw/rgw_rest_metadata.cc | 8 +- ceph/src/rgw/rgw_rest_realm.cc | 4 +- ceph/src/rgw/rgw_rest_role.cc | 24 +- ceph/src/rgw/rgw_rest_role.h | 2 + ceph/src/rgw/rgw_rest_s3.cc | 1645 +- ceph/src/rgw/rgw_rest_s3.h | 235 +- ceph/src/rgw/rgw_rest_swift.cc | 146 +- ceph/src/rgw/rgw_rest_swift.h | 3 + ceph/src/rgw/rgw_role.cc | 82 +- ceph/src/rgw/rgw_role.h | 44 +- ceph/src/rgw/rgw_string.h | 145 +- ceph/src/rgw/rgw_swift_auth.cc | 18 +- ceph/src/rgw/rgw_sync.cc | 75 +- ceph/src/rgw/rgw_sync_module.cc | 3 +- ceph/src/rgw/rgw_sync_module.h | 21 +- ceph/src/rgw/rgw_sync_module_es.cc | 474 +- ceph/src/rgw/rgw_sync_module_es.h | 15 +- ceph/src/rgw/rgw_sync_module_es_rest.cc | 412 + ceph/src/rgw/rgw_sync_module_es_rest.h | 17 + ceph/src/rgw/rgw_sync_module_log.cc | 9 +- ceph/src/rgw/rgw_sync_module_log.h | 2 +- ceph/src/rgw/rgw_tools.cc | 2 - ceph/src/rgw/rgw_torrent.cc | 70 +- ceph/src/rgw/rgw_torrent.h | 10 +- ceph/src/rgw/rgw_user.h | 2 - ceph/src/rgw/rgw_xml.h | 3 - ceph/src/script/check_commands.sh | 19 + ceph/src/test/CMakeLists.txt | 33 +- ceph/src/test/ObjectMap/test_object_map.cc | 2 +- ceph/src/test/admin_socket_output.cc | 227 + ceph/src/test/admin_socket_output.h | 78 + ceph/src/test/admin_socket_output_tests.cc | 66 + ceph/src/test/admin_socket_output_tests.h | 28 + ceph/src/test/bench/CMakeLists.txt | 10 +- ceph/src/test/bufferlist.cc | 86 +- ceph/src/test/cephtool-test-mds.sh | 2 +- ceph/src/test/cephtool-test-mon.sh | 2 +- ceph/src/test/cephtool-test-osd.sh | 2 +- ceph/src/test/cephtool-test-rados.sh | 2 +- .../cli-integration/rbd/formatted-output.t | 24 + ceph/src/test/cli/crushtool/add-item.t | 129 + .../src/test/cli/crushtool/arg-order-checks.t | 86 +- ceph/src/test/cli/crushtool/build.t | 4 +- ceph/src/test/cli/crushtool/help.t | 7 + ceph/src/test/cli/osdmaptool/clobber.t | 10 +- ceph/src/test/cli/osdmaptool/create-print.t | 26 +- ceph/src/test/cli/osdmaptool/create-racks.t | 26 +- ceph/src/test/cli/osdmaptool/crush.t | 2 +- ceph/src/test/cli/osdmaptool/help.t | 1 + .../test/cli/osdmaptool/missing-argument.t | 1 + ceph/src/test/cli/osdmaptool/upmap.t | 23 +- ceph/src/test/cli/radosgw-admin/help.t | 4 + ceph/src/test/cli/rbd/help.t | 4 +- ceph/src/test/cls_rbd/test_cls_rbd.cc | 15 + ceph/src/test/cls_rgw/test_cls_rgw.cc | 102 +- ceph/src/test/common/CMakeLists.txt | 6 + ceph/src/test/common/test_context.cc | 7 + ceph/src/test/common/test_crc32c.cc | 93 + ceph/src/test/common/test_iso_8601.cc | 60 + ceph/src/test/compressor/test_compression.cc | 3 + ceph/src/test/crush/CMakeLists.txt | 1 + ceph/src/test/crush/CrushWrapper.cc | 164 +- .../crush-choose-args-expected-one-more-0.txt | 76 + .../crush-choose-args-expected-one-more-3.txt | 76 + ceph/src/test/crush/crush-choose-args.sh | 150 + ceph/src/test/crush/crush.cc | 46 +- ceph/src/test/encoding/ceph_dencoder.cc | 8 +- ceph/src/test/encoding/test_sstring.h | 40 + ceph/src/test/encoding/types.h | 14 + ceph/src/test/erasure-code/CMakeLists.txt | 6 +- .../test/erasure-code/ErasureCodeExample.h | 4 +- ceph/src/test/fio/fio_ceph_objectstore.cc | 21 +- ceph/src/test/journal/test_Journaler.cc | 11 +- ceph/src/test/librados/CMakeLists.txt | 11 +- ceph/src/test/librados/TestCase.cc | 45 +- ceph/src/test/librados/list.cc | 2 + ceph/src/test/librados/misc.cc | 1 + ceph/src/test/librados/test.cc | 125 +- ceph/src/test/librados/test.h | 3 - ceph/src/test/librados/test_common.cc | 134 + ceph/src/test/librados/test_common.h | 7 + ceph/src/test/librados/tier.cc | 131 + .../librados_test_stub/LibradosTestStub.cc | 13 + .../test/librados_test_stub/TestIoCtxImpl.cc | 28 +- .../test/librados_test_stub/TestIoCtxImpl.h | 14 +- .../librados_test_stub/TestRadosClient.cc | 12 +- .../test/librados_test_stub/TestRadosClient.h | 18 +- ceph/src/test/libradosstriper/striping.cc | 1 + ceph/src/test/librbd/CMakeLists.txt | 3 +- .../test_mock_PreReleaseRequest.cc | 14 +- .../librbd/image/test_mock_RemoveRequest.cc | 4 + .../test/librbd/io/test_mock_ImageRequest.cc | 46 +- .../test/librbd/journal/test_mock_Replay.cc | 343 +- .../managed_lock/test_mock_AcquireRequest.cc | 3 +- .../managed_lock/test_mock_BreakRequest.cc | 204 +- ceph/src/test/librbd/mock/MockExclusiveLock.h | 5 + ceph/src/test/librbd/mock/MockImageCtx.h | 12 +- ceph/src/test/librbd/mock/MockObjectMap.h | 12 +- .../object_map/test_mock_InvalidateRequest.cc | 7 +- .../test_mock_SnapshotRollbackRequest.cc | 8 +- .../object_map/test_mock_UpdateRequest.cc | 10 +- .../operation/test_mock_ResizeRequest.cc | 8 + .../test_mock_SnapshotRollbackRequest.cc | 1 + ceph/src/test/librbd/test_ObjectMap.cc | 34 +- ceph/src/test/librbd/test_librbd.cc | 207 +- .../test/librbd/test_mock_ExclusiveLock.cc | 55 +- ceph/src/test/librbd/test_mock_Journal.cc | 4 +- ceph/src/test/librbd/test_mock_ManagedLock.cc | 2 +- ceph/src/test/librbd/test_mock_ObjectMap.cc | 13 +- ceph/src/test/mds/CMakeLists.txt | 1 - ceph/src/test/mgr/CMakeLists.txt | 2 + ceph/src/test/mgr/mgr-dashboard-smoke.sh | 67 + ceph/src/test/mon/misc.sh | 4 +- ceph/src/test/mon/osd-crush.sh | 23 +- ceph/src/test/mon/osd-pool-create.sh | 86 +- ceph/src/test/mon/test-mon-msg.cc | 8 +- ceph/src/test/mon/test_mon_workloadgen.cc | 2 +- ceph/src/test/msgr/perf_msgr_client.cc | 9 +- ceph/src/test/msgr/perf_msgr_server.cc | 1 - ceph/src/test/msgr/test_async_driver.cc | 17 +- ceph/src/test/msgr/test_msgr.cc | 12 +- ceph/src/test/objectstore/Allocator_test.cc | 12 + .../test/objectstore/TestObjectStoreState.cc | 2 +- .../test/objectstore/TestObjectStoreState.h | 11 +- ceph/src/test/objectstore/store_test.cc | 39 +- ceph/src/test/objectstore/test_bluefs.cc | 4 +- .../test/objectstore/test_bluestore_types.cc | 81 +- .../test/objectstore/workload_generator.cc | 8 +- .../src/test/objectstore/workload_generator.h | 10 +- ceph/src/test/old/testcrush.cc | 47 - ceph/src/test/osd/CMakeLists.txt | 7 + ceph/src/test/osd/Object.cc | 1 - ceph/src/test/osd/Object.h | 1 + ceph/src/test/osd/RadosModel.cc | 2 - ceph/src/test/osd/RadosModel.h | 245 +- ceph/src/test/osd/TestOSDMap.cc | 40 +- ceph/src/test/osd/TestPGLog.cc | 2 - ceph/src/test/osd/TestRados.cc | 103 +- ceph/src/test/osd/osd-config.sh | 6 + ceph/src/test/osd/osd-dup.sh | 8 +- ceph/src/test/osd/osd-scrub-repair.sh | 435 +- ceph/src/test/osd/osd-scrub-snaps.sh | 2 +- ceph/src/test/osd/test_ec_transaction.cc | 124 + ceph/src/test/osd/types.cc | 3 +- ceph/src/test/osdc/FakeWriteback.cc | 10 +- ceph/src/test/osdc/FakeWriteback.h | 10 +- ceph/src/test/osdc/MemWriteback.cc | 10 +- ceph/src/test/osdc/MemWriteback.h | 10 +- ceph/src/test/osdc/object_cacher_stress.cc | 21 +- ceph/src/test/perf_counters.cc | 25 +- ceph/src/test/perf_local.cc | 43 +- ceph/src/test/pybind/test_ceph_argparse.py | 4 +- ceph/src/test/pybind/test_rbd.py | 5 + .../test_mock_BootstrapRequest.cc | 117 +- .../image_sync/test_mock_ObjectCopyRequest.cc | 61 +- .../test_mock_SnapshotCopyRequest.cc | 175 +- .../test_mock_SnapshotCreateRequest.cc | 54 + .../src/test/rbd_mirror/test_ImageReplayer.cc | 27 +- ceph/src/test/rbd_mirror/test_ImageSync.cc | 19 +- .../src/test/rbd_mirror/test_LeaderWatcher.cc | 3 + .../rbd_mirror/test_mock_ImageReplayer.cc | 98 +- .../test/rbd_mirror/test_mock_ImageSync.cc | 134 +- .../test_mock_ImageSyncThrottler.cc | 456 +- .../rbd_mirror/test_mock_InstanceReplayer.cc | 29 +- .../rbd_mirror/test_mock_InstanceWatcher.cc | 369 +- .../rbd_mirror/test_mock_LeaderWatcher.cc | 10 + ceph/src/test/rgw/CMakeLists.txt | 32 +- ceph/src/test/rgw/rgw_multi/conn.py | 16 + ceph/src/test/rgw/rgw_multi/multisite.py | 59 +- ceph/src/test/rgw/rgw_multi/tests.py | 429 +- ceph/src/test/rgw/rgw_multi/tests_es.py | 274 + ceph/src/test/rgw/rgw_multi/tools.py | 82 + ceph/src/test/rgw/rgw_multi/zone_es.py | 256 + ceph/src/test/rgw/rgw_multi/zone_rados.py | 89 + ceph/src/test/rgw/test_multi.py | 42 +- ceph/src/test/rgw/test_rgw_compression.cc | 22 +- ceph/src/test/rgw/test_rgw_crypto.cc | 4 +- ceph/src/test/rgw/test_rgw_iam_policy.cc | 507 + ceph/src/test/rgw/test_rgw_string.cc | 76 + ceph/src/test/system/systest_runnable.cc | 6 +- ceph/src/test/test_admin_socket_output.cc | 128 + ceph/src/test/test_denc.cc | 118 + ceph/src/test/test_features.cc | 44 + ceph/src/test/test_filejournal.cc | 288 +- ceph/src/test/test_ipaddr.cc | 2 + ceph/src/test/test_mempool.cc | 115 +- ceph/src/test/test_rgw_admin_opstate.cc | 2 +- ceph/src/test/test_stress_watch.cc | 8 +- ceph/src/test/test_workqueue.cc | 12 +- ceph/src/test/vstart_wrapper.sh | 10 +- ceph/src/tools/CMakeLists.txt | 6 +- ceph/src/tools/ceph-monstore-update-crush.sh | 16 +- ceph/src/tools/ceph_kvstore_tool.cc | 54 +- ceph/src/tools/ceph_objectstore_tool.cc | 18 +- ceph/src/tools/cephfs/DataScan.cc | 1 + ceph/src/tools/cephfs/JournalTool.cc | 208 +- ceph/src/tools/cephfs/JournalTool.h | 3 +- ceph/src/tools/crushtool.cc | 84 +- ceph/src/tools/osdmaptool.cc | 12 +- ceph/src/tools/rados/rados.cc | 40 +- ceph/src/tools/rbd/ArgumentTypes.cc | 2 +- ceph/src/tools/rbd/ArgumentTypes.h | 2 - ceph/src/tools/rbd/CMakeLists.txt | 1 - ceph/src/tools/rbd/Utils.cc | 47 +- ceph/src/tools/rbd/Utils.h | 1 + ceph/src/tools/rbd/action/Bench.cc | 7 +- ceph/src/tools/rbd/action/Feature.cc | 11 +- ceph/src/tools/rbd/action/Group.cc | 3 - ceph/src/tools/rbd/action/Info.cc | 20 + ceph/src/tools/rbd/action/Kernel.cc | 4 +- ceph/src/tools/rbd/action/List.cc | 2 - ceph/src/tools/rbd/action/Trash.cc | 3 +- ceph/src/tools/rbd/rbd.cc | 2 +- ceph/src/tools/rbd_mirror/BaseRequest.h | 2 +- ceph/src/tools/rbd_mirror/ImageDeleter.cc | 8 +- ceph/src/tools/rbd_mirror/ImageReplayer.cc | 109 +- ceph/src/tools/rbd_mirror/ImageReplayer.h | 9 +- ceph/src/tools/rbd_mirror/ImageSync.cc | 72 +- ceph/src/tools/rbd_mirror/ImageSync.h | 24 +- .../tools/rbd_mirror/ImageSyncThrottler.cc | 276 +- .../src/tools/rbd_mirror/ImageSyncThrottler.h | 84 +- ceph/src/tools/rbd_mirror/InstanceReplayer.cc | 19 +- ceph/src/tools/rbd_mirror/InstanceReplayer.h | 14 +- ceph/src/tools/rbd_mirror/InstanceWatcher.cc | 514 +- ceph/src/tools/rbd_mirror/InstanceWatcher.h | 42 + ceph/src/tools/rbd_mirror/LeaderWatcher.cc | 28 +- ceph/src/tools/rbd_mirror/LeaderWatcher.h | 5 + ceph/src/tools/rbd_mirror/Mirror.cc | 18 +- ceph/src/tools/rbd_mirror/Mirror.h | 1 - ceph/src/tools/rbd_mirror/PoolReplayer.cc | 20 +- ceph/src/tools/rbd_mirror/PoolReplayer.h | 9 +- .../image_replayer/BootstrapRequest.cc | 56 +- .../image_replayer/BootstrapRequest.h | 13 +- .../image_replayer/OpenLocalImageRequest.cc | 26 +- .../image_sync/ObjectCopyRequest.cc | 51 +- .../rbd_mirror/image_sync/ObjectCopyRequest.h | 3 + .../image_sync/SnapshotCopyRequest.cc | 90 +- .../image_sync/SnapshotCopyRequest.h | 2 + .../image_sync/SnapshotCreateRequest.cc | 87 +- .../image_sync/SnapshotCreateRequest.h | 2 + .../rbd_mirror/instance_watcher/Types.cc | 51 +- .../tools/rbd_mirror/instance_watcher/Types.h | 60 +- .../tools/rbd_mirror/leader_watcher/Types.h | 6 +- .../pool_watcher/RefreshImagesRequest.cc | 2 +- ceph/src/tools/rbd_mirror/types.h | 4 - ceph/src/tools/rbd_nbd/rbd-nbd.cc | 324 +- ceph/src/tools/setup-virtualenv.sh | 3 + ceph/src/tracing/CMakeLists.txt | 4 + ceph/src/tracing/README.md | 22 + ceph/src/tracing/cyg_profile.c | 6 + ceph/src/tracing/cyg_profile.tp | 23 + ceph/src/tracing/cyg_profile_functions.c | 31 + ceph/src/tracing/librados.tp | 22 + ceph/src/tracing/librbd.tp | 22 + ceph/src/valgrind.supp | 38 + ceph/src/vstart.sh | 66 +- ceph/src/yasm-wrapper | 2 +- 2997 files changed, 535045 insertions(+), 48654 deletions(-) create mode 100644 ceph/cmake/modules/BuildBoost.cmake delete mode 100644 ceph/cmake/modules/Findatomic_ops.cmake create mode 100644 ceph/cmake/modules/Findpmem.cmake create mode 100644 ceph/debian/ceph-base.maintscript create mode 100644 ceph/doc/dev/perf_histograms.rst create mode 100644 ceph/doc/install/manual-freebsd-deployment.rst create mode 100644 ceph/doc/mgr/dashboard.rst create mode 100644 ceph/doc/mgr/restful.rst create mode 100644 ceph/doc/radosgw/bucketpolicy.rst delete mode 100644 ceph/doc/radosgw/config-fcgi.rst delete mode 100644 ceph/doc/radosgw/federated-config.rst create mode 100644 ceph/doc/radosgw/nfs.rst create mode 100644 ceph/doc/radosgw/pools.rst delete mode 100644 ceph/doc/radosgw/rgw-centos.conf delete mode 100644 ceph/doc/radosgw/rgw-debian.conf delete mode 100644 ceph/doc/radosgw/rgw.conf delete mode 100644 ceph/doc/radosgw/upgrade_to_jewel.rst create mode 100644 ceph/examples/librados/hello_radosstriper.cc rename ceph/qa/suites/fs/{standbyreplay/tasks/migration.yaml => basic_functional/tasks/test_journal_migration.yaml} (100%) delete mode 120000 ceph/qa/suites/fs/standbyreplay/begin.yaml delete mode 100644 ceph/qa/suites/fs/standbyreplay/clusters/standby-replay.yaml delete mode 120000 ceph/qa/suites/fs/standbyreplay/mount/fuse.yaml delete mode 120000 ceph/qa/suites/fs/standbyreplay/objectstore delete mode 120000 ceph/qa/suites/fs/standbyreplay/overrides/debug.yaml delete mode 120000 ceph/qa/suites/fs/standbyreplay/overrides/frag_enable.yaml delete mode 120000 ceph/qa/suites/fs/standbyreplay/overrides/whitelist_wrongly_marked_down.yaml rename ceph/qa/suites/{multimds/basic/tasks/cfuse_workunit_misc_test_o_trunc.yaml => krbd/rbd-nomount/tasks/krbd_fallocate.yaml} (57%) create mode 100644 ceph/qa/suites/multimds/basic/q_check_counter/check_counter.yaml delete mode 100644 ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_fsync.yaml delete mode 100644 ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iogen.yaml delete mode 100644 ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iozone.yaml delete mode 100644 ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_truncate_delay.yaml delete mode 120000 ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_trivial_sync.yaml delete mode 120000 ceph/qa/suites/multimds/thrash/tasks/cfuse_workunit_trivial_sync.yaml rename ceph/qa/suites/{fs/standbyreplay => rados/basic-luminous}/% (100%) create mode 120000 ceph/qa/suites/rados/basic-luminous/ceph.yaml create mode 120000 ceph/qa/suites/rados/basic-luminous/clusters create mode 120000 ceph/qa/suites/rados/basic-luminous/objectstore create mode 120000 ceph/qa/suites/rados/basic-luminous/rados.yaml rename ceph/qa/suites/rados/{basic/tasks => basic-luminous}/scrub_test.yaml (95%) create mode 100644 ceph/qa/suites/rados/rest/mgr-restful.yaml create mode 100644 ceph/qa/suites/rados/singleton-nomsgr/all/admin_socket_output.yaml create mode 100644 ceph/qa/suites/rados/singleton-nomsgr/all/health-warnings.yaml create mode 100644 ceph/qa/suites/rados/singleton-nomsgr/all/pool-access.yaml create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-big/ceph.yaml create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-big/d-require-luminous create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-isa/d-require-luminous create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-overwrites/ceph.yaml create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-overwrites/d-require-luminous create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-shec/ceph.yaml create mode 120000 ceph/qa/suites/rados/thrash-erasure-code-shec/d-require-luminous rename ceph/qa/suites/{fs/standbyreplay/overrides/+ => rados/thrash-luminous/%} (100%) create mode 120000 ceph/qa/suites/rados/thrash-luminous/0-size-min-size-overrides create mode 120000 ceph/qa/suites/rados/thrash-luminous/1-pg-log-overrides create mode 120000 ceph/qa/suites/rados/thrash-luminous/backoff create mode 120000 ceph/qa/suites/rados/thrash-luminous/ceph.yaml create mode 120000 ceph/qa/suites/rados/thrash-luminous/clusters create mode 120000 ceph/qa/suites/rados/thrash-luminous/msgr create mode 120000 ceph/qa/suites/rados/thrash-luminous/objectstore create mode 120000 ceph/qa/suites/rados/thrash-luminous/rados.yaml create mode 120000 ceph/qa/suites/rados/thrash-luminous/rocksdb.yaml create mode 120000 ceph/qa/suites/rados/thrash-luminous/thrashers create mode 100644 ceph/qa/suites/rados/thrash-luminous/workloads/redirect.yaml create mode 100644 ceph/qa/suites/rados/thrash-luminous/workloads/redirect_set_object.yaml delete mode 100644 ceph/qa/suites/rgw/multifs/frontend/apache.yaml rename ceph/{src/pybind/mgr/rest/app/__init__.py => qa/suites/rgw/multisite/%} (100%) create mode 100644 ceph/qa/suites/rgw/multisite/clusters.yaml create mode 100644 ceph/qa/suites/rgw/multisite/frontend/civetweb.yaml create mode 100644 ceph/qa/suites/rgw/multisite/overrides.yaml create mode 100644 ceph/qa/suites/rgw/multisite/realms/three-zone.yaml create mode 100644 ceph/qa/suites/rgw/multisite/realms/two-zonegroup.yaml create mode 100644 ceph/qa/suites/rgw/multisite/tasks/test_multi.yaml create mode 100644 ceph/qa/suites/rgw/multisite/valgrind.yaml delete mode 100644 ceph/qa/suites/rgw/singleton/all/radosgw-admin-data-sync.yaml delete mode 100644 ceph/qa/suites/rgw/singleton/all/radosgw-admin-multi-region.yaml delete mode 100644 ceph/qa/suites/rgw/singleton/all/radosgw-convert-to-region.yaml delete mode 100644 ceph/qa/suites/rgw/singleton/frontend/apache.yaml delete mode 100644 ceph/qa/suites/rgw/verify/frontend/apache.yaml delete mode 100644 ceph/qa/suites/rgw/verify/tasks/rgw_s3tests_multiregion.yaml delete mode 100644 ceph/qa/tasks/apache.conf.template create mode 100644 ceph/qa/tasks/dnsmasq.py delete mode 100644 ceph/qa/tasks/mod_fastcgi.conf.template delete mode 100644 ceph/qa/tasks/mod_proxy_fcgi.tcp.conf.template delete mode 100644 ceph/qa/tasks/mod_proxy_fcgi.uds.conf.template delete mode 100644 ceph/qa/tasks/radosgw_agent.py create mode 120000 ceph/qa/tasks/rgw_multi create mode 100644 ceph/qa/tasks/rgw_multisite.py create mode 100644 ceph/qa/tasks/rgw_multisite_tests.py create mode 100755 ceph/qa/workunits/rados/test_health_warnings.sh create mode 100755 ceph/qa/workunits/rados/test_pool_access.sh create mode 100755 ceph/qa/workunits/rbd/krbd_fallocate.sh create mode 100755 ceph/qa/workunits/rest/test-restful.sh create mode 100755 ceph/qa/workunits/rest/test_mgr_rest_api.py delete mode 100755 ceph/src/ceph-disk-udev create mode 100644 ceph/src/ceph_release create mode 100644 ceph/src/common/backport14.h rename ceph/src/common/{crc32c_intel_fast_asm.S => crc32c_intel_fast_asm.s} (100%) rename ceph/src/common/{crc32c_intel_fast_zero_asm.S => crc32c_intel_fast_zero_asm.s} (100%) create mode 100644 ceph/src/common/crc32c_ppc_fast_zero_asm.S create mode 100644 ceph/src/common/freebsd_errno.cc create mode 100644 ceph/src/common/iso_8601.cc create mode 100644 ceph/src/common/iso_8601.h create mode 100644 ceph/src/common/reverse.c create mode 100644 ceph/src/common/reverse.h create mode 100644 ceph/src/compressor/lz4/CMakeLists.txt create mode 100644 ceph/src/compressor/lz4/CompressionPluginLZ4.cc create mode 100644 ceph/src/compressor/lz4/CompressionPluginLZ4.h create mode 100644 ceph/src/compressor/lz4/LZ4Compressor.h create mode 100644 ceph/src/dmclock/README.before-modifying-files-here-or-below delete mode 100644 ceph/src/dmclock/cmake/modules/Findboost.cmake delete mode 100644 ceph/src/dmclock/cmake/modules/Findgtest.cmake delete mode 100644 ceph/src/dmclock/support/CMakeLists.txt delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.c delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.h delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/ec_highlevel_func.c delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/ec_multibinary.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx2.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_avx.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_sse.asm.s delete mode 100644 ceph/src/erasure-code/isa/isa-l/include/erasure_code.h delete mode 100644 ceph/src/erasure-code/isa/isa-l/include/gf_vect_mul.h delete mode 100644 ceph/src/erasure-code/isa/isa-l/include/reg_sizes.asm delete mode 100644 ceph/src/erasure-code/isa/isa-l/include/types.h delete mode 100644 ceph/src/fetch_config delete mode 100644 ceph/src/include/atomic.h create mode 100644 ceph/src/include/cpp-btree/btree_set.h rename ceph/src/librbd/{ => io}/AsyncOperation.cc (94%) rename ceph/src/librbd/{ => io}/AsyncOperation.h (83%) create mode 100644 ceph/src/messages/MMonMgrReport.h create mode 100644 ceph/src/mgr/Gil.h create mode 100644 ceph/src/mon/MgrStatMonitor.cc create mode 100644 ceph/src/mon/MgrStatMonitor.h create mode 100644 ceph/src/mon/PGStatService.h delete mode 100644 ceph/src/msg/async/rdma/Device.cc delete mode 100644 ceph/src/msg/async/rdma/Device.h delete mode 100644 ceph/src/msg/async/rdma/RDMAConnTCP.cc delete mode 100644 ceph/src/msg/async/rdma/RDMAConnTCP.h delete mode 100644 ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.h delete mode 100644 ceph/src/msg/async/rdma/ib_dbg.h create mode 100644 ceph/src/os/bluestore/PMEMDevice.cc create mode 100644 ceph/src/os/bluestore/PMEMDevice.h create mode 100644 ceph/src/perf_histogram.h create mode 100644 ceph/src/pybind/mgr/dashboard/HACKING.rst create mode 100644 ceph/src/pybind/mgr/dashboard/README.rst rename ceph/src/pybind/mgr/{rest => dashboard}/__init__.py (96%) create mode 100644 ceph/src/pybind/mgr/dashboard/base.html create mode 100644 ceph/src/pybind/mgr/dashboard/cephfs_clients.py create mode 100644 ceph/src/pybind/mgr/dashboard/clients.html create mode 100644 ceph/src/pybind/mgr/dashboard/filesystem.html create mode 100644 ceph/src/pybind/mgr/dashboard/health.html create mode 100644 ceph/src/pybind/mgr/dashboard/module.py create mode 100644 ceph/src/pybind/mgr/dashboard/osd_perf.html create mode 100644 ceph/src/pybind/mgr/dashboard/rbd.html create mode 100644 ceph/src/pybind/mgr/dashboard/rbd_ls.py create mode 100644 ceph/src/pybind/mgr/dashboard/remote_view_cache.py create mode 100644 ceph/src/pybind/mgr/dashboard/servers.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/.jshintrc create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/Gruntfile.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/LICENSE create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/README.md create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css.map create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.min.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.min.css.map create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/js/bootstrap.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/js/bootstrap.min.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/js/npm.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bower.json create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/alerts.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/background-variant.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/border-radius.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/buttons.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/center-block.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/clearfix.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/forms.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/gradients.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/grid-framework.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/grid.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/hide-text.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/image.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/labels.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/list-group.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/nav-divider.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/nav-vertical-align.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/opacity.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/pagination.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/panels.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/progress-bar.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/reset-filter.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/reset-text.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/resize.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/responsive-visibility.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/size.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/tab-focus.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/table-row.less create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/text-emphasis.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/text-overflow.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/mixins/vendor-prefixes.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/bootstrap-less/variables.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/.csslintrc create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/404_500_errors.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/AdminLTE.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/alerts.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/bootstrap-social.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/boxes.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/buttons.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/callout.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/carousel.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/control-sidebar.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/core.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/direct-chat.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/dropdown.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/forms.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/fullcalendar.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/header.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/info-box.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/invoice.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/labels.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/lockscreen.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/login_and_register.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/mailbox.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/miscellaneous.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/mixins.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/modal.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/navs.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/print.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/products.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/profile.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/progress-bars.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/select2.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/sidebar-mini.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/sidebar.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/_all-skins.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-black-light.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-black.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-blue-light.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-blue.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-green-light.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-green.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-purple-light.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-purple.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-red-light.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-red.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-yellow-light.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/skins/skin-yellow.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/small-box.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/social-widgets.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/table.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/timeline.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/users-list.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/build/less/variables.less create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/changelog.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/composer.json create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/AdminLTE.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/AdminLTE.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/_all-skins.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/_all-skins.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-black-light.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-black-light.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-black.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-black.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-blue-light.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-blue-light.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-blue.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-blue.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-green-light.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-green-light.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-green.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-green.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-purple-light.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-purple-light.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-purple.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-purple.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-red-light.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-red-light.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-red.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-red.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-yellow-light.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-yellow-light.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-yellow.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/css/skins/skin-yellow.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/avatar.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/avatar04.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/avatar2.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/avatar3.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/avatar5.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/boxed-bg.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/boxed-bg.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/american-express.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/cirrus.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/mastercard.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/mestro.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/paypal.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/paypal2.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/credit/visa.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/default-50x50.gif create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/icons.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/photo1.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/photo2.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/photo3.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/photo4.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user1-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user2-160x160.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user3-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user4-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user5-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user6-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user7-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/img/user8-128x128.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/js/app.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/js/app.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/js/demo.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/js/pages/dashboard.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/dist/js/pages/dashboard2.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/adminlte-options.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/advice.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/browsers.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/components.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/dependencies.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/download.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/faq.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/implementations.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/introduction.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/layout.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/license.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/plugins.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/include/upgrade.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/build/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/docs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/documentation/style.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/index2.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/package.json create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/UI/buttons.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/UI/general.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/UI/icons.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/UI/modals.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/UI/sliders.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/UI/timeline.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/calendar.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/charts/chartjs.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/charts/flot.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/charts/inline.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/charts/morris.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/404.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/500.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/blank.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/invoice-print.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/invoice.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/lockscreen.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/login.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/pace.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/profile.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/examples/register.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/forms/advanced.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/forms/editors.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/forms/general.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/layout/boxed.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/layout/collapsed-sidebar.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/layout/fixed.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/layout/top-nav.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/mailbox/compose.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/mailbox/mailbox.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/mailbox/read-mail.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/tables/data.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/tables/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/pages/widgets.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/bootstrap-slider/bootstrap-slider.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/bootstrap-slider/slider.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/chartjs/Chart.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/chartjs/Chart.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/CHANGES.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/LICENSE.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/README.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/adapters/jquery.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/build-config.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/ckeditor.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/config.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/contents.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/af.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ar.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/bg.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/bn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/bs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/cs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/cy.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/da.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/de-ch.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/de.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/el.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/en-au.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/en-ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/en-gb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/en.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/eo.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/es.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/et.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/eu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/fa.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/fi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/fo.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/fr-ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/fr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/gl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/gu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/he.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/hi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/hr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/hu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/id.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/is.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/it.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ja.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ka.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/km.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ko.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ku.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/lt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/lv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/mk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/mn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ms.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/nb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/nl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/no.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/pl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/pt-br.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/pt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ro.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ru.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/si.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/sk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/sl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/sq.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/sr-latn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/sr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/sv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/th.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/tr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/tt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/ug.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/uk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/vi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/zh-cn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/lang/zh.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/af.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ar.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/bg.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/cs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/cy.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/da.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/de-ch.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/de.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/el.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/en.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/eo.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/es.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/et.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/eu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/fa.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/fi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/fo.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/fr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/gl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/gu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/he.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/hi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/hr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/hu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/id.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/it.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ja.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/km.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ko.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ku.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/lt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/lv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/mk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/mn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/nb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/nl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/no.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/pl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/pt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ro.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ru.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/si.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/sk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/sl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/sq.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/sr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/sv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/th.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/tr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/tt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/ug.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/uk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/vi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/a11yhelp/dialogs/lang/zh.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/about/dialogs/about.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/about/dialogs/logo_ckeditor.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/clipboard/dialogs/paste.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/dialog/dialogDefinition.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/icons.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/icons_hidpi.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/image/dialogs/image.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/image/images/noimage.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/link/dialogs/anchor.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/link/dialogs/link.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/link/images/anchor.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/link/images/hidpi/anchor.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/magicline/images/hidpi/icon-rtl.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/magicline/images/hidpi/icon.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/magicline/images/icon-rtl.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/magicline/images/icon.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/pastefromword/filter/default.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/scayt/CHANGELOG.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/scayt/LICENSE.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/scayt/README.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/scayt/dialogs/options.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/scayt/dialogs/toolbar.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/_translationstatus.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/af.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ar.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/bg.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/cs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/cy.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/da.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/de-ch.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/de.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/el.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/en-gb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/en.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/eo.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/es.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/et.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/eu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/fa.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/fi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/fr-ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/fr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/gl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/he.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/hr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/hu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/id.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/it.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ja.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/km.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ko.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ku.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/lt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/lv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/nb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/nl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/no.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/pl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/pt-br.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/pt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ru.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/si.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/sk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/sl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/sq.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/sv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/th.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/tr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/tt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/ug.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/uk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/vi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/zh-cn.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/lang/zh.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/specialchar/dialogs/specialchar.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/table/dialogs/table.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/tabletools/dialogs/tableCell.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/LICENSE.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/README.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/dialogs/ciframe.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/dialogs/tmpFrameset.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/dialogs/wsc.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/dialogs/wsc.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/plugins/wsc/dialogs/wsc_ie.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/css/samples.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/img/github-top.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/img/header-bg.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/img/header-separator.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/img/logo.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/img/navigation-tip.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/js/sample.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/js/sf.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/ajax.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/api.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/appendto.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/assets/inlineall/logo.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/assets/outputxhtml/outputxhtml.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/assets/posteddata.php create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/assets/sample.jpg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/assets/uilanguages/languages.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/datafiltering.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/dialog/assets/my_dialog.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/dialog/dialog.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/divreplace.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/enterkey/enterkey.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.fla create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/htmlwriter/assets/outputforflash/outputforflash.swf create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/htmlwriter/assets/outputforflash/swfobject.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/htmlwriter/outputforflash.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/htmlwriter/outputhtml.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/inlineall.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/inlinebycode.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/inlinetextarea.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/jquery.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/magicline/magicline.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/readonly.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/replacebyclass.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/replacebycode.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/sample.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/sample.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/sample_posteddata.php create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/tabindex.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/toolbar/toolbar.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/uicolor.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/uilanguages.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/wysiwygarea/fullpage.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/old/xhtmlstyle.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/css/fontello.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/font/LICENSE.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/font/config.json create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/font/fontello.eot create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/font/fontello.svg create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/font/fontello.ttf create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/font/fontello.woff create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/js/toolbarmodifier.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/js/toolbartextmodifier.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/LICENSE create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/codemirror.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/codemirror.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/javascript.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/neo.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/show-hint.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/samples/toolbarconfigurator/lib/codemirror/show-hint.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/dialog.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/dialog_ie.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/dialog_ie7.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/dialog_ie8.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/dialog_iequirks.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/editor.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/editor_gecko.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/editor_ie.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/editor_ie7.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/editor_ie8.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/editor_iequirks.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/icons.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/icons_hidpi.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/arrow.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/close.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/hidpi/close.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/hidpi/lock-open.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/hidpi/lock.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/hidpi/refresh.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/lock-open.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/lock.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/refresh.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/images/spinner.gif create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/skins/moono/readme.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ckeditor/styles.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/bootstrap-colorpicker.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/bootstrap-colorpicker.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/bootstrap-colorpicker.min.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/bootstrap-colorpicker.min.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/img/alpha-horizontal.png create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/img/alpha.png create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/img/hue-horizontal.png create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/img/hue.png create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/colorpicker/img/saturation.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/dataTables.bootstrap.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/dataTables.bootstrap.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/dataTables.bootstrap.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/Readme.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/css/dataTables.autoFill.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/css/dataTables.autoFill.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/columns.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/complete-callback.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/fill-both.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/fill-horizontal.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/scrolling.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/examples/step-callback.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/images/filler.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/js/dataTables.autoFill.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/AutoFill/js/dataTables.autoFill.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/License.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/Readme.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/css/dataTables.colReorder.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/css/dataTables.colReorder.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/alt_insert.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/col_filter.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/colvis.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/fixedcolumns.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/fixedheader.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/jqueryui.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/new_init.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/predefined.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/realtime.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/reset.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/scrolling.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/server_side.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/examples/state_save.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/images/insert.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/js/dataTables.colReorder.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColReorder/js/dataTables.colReorder.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/License.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/Readme.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/css/dataTables.colVis.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/css/dataTables.colVis.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/css/dataTables.colvis.jqueryui.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/button_order.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/exclude_columns.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/group_columns.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/jqueryui.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/mouseover.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/new_init.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/restore.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/text.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/title_callback.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/two_tables.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/examples/two_tables_identical.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/js/dataTables.colVis.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/ColVis/js/dataTables.colVis.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/License.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/Readme.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/css/dataTables.fixedColumns.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/css/dataTables.fixedColumns.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/bootstrap.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/col_filter.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/colvis.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/css_size.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/index_column.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/left_right_columns.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/right_column.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/rowspan.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/server-side-processing.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/size_fixed.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/size_fluid.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/examples/two_columns.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/js/dataTables.fixedColumns.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedColumns/js/dataTables.fixedColumns.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/Readme.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/css/dataTables.fixedHeader.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/css/dataTables.fixedHeader.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/examples/header_footer.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/examples/top_left_right.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/examples/two_tables.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/examples/zIndexes.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/js/dataTables.fixedHeader.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/FixedHeader/js/dataTables.fixedHeader.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/Readme.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/css/dataTables.keyTable.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/css/dataTables.keyTable.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/examples/events.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/examples/html.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/examples/scrolling.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/js/dataTables.keyTable.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/KeyTable/js/dataTables.keyTable.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/License.txt rename ceph/src/pybind/mgr/{rest/app/management/__init__.py => dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/Readme.md} (100%) create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/css/dataTables.responsive.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/css/dataTables.responsive.scss create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/child-rows/column-control.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/child-rows/custom-renderer.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/child-rows/disable-child-rows.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/child-rows/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/child-rows/right-column.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/child-rows/whole-row-control.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/display-control/auto.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/display-control/classes.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/display-control/complexHeader.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/display-control/fixedHeader.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/display-control/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/display-control/init-classes.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/initialisation/ajax.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/initialisation/className.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/initialisation/default.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/initialisation/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/initialisation/new.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/initialisation/option.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/styling/bootstrap.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/styling/compact.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/styling/foundation.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/styling/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/examples/styling/scrolling.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/js/dataTables.responsive.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Responsive/js/dataTables.responsive.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/Readme.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/css/dataTables.scroller.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/css/dataTables.scroller.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/api_scrolling.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/data/2500.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/data/ssp.php create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/large_js_source.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/server-side_processing.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/examples/state_saving.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/images/loading-background.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/js/dataTables.scroller.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/Scroller/js/dataTables.scroller.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/Readme.md create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/css/dataTables.tableTools.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/css/dataTables.tableTools.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/ajax.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/alter_buttons.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/bootstrap.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/button_text.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/collection.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/defaults.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/index.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/jqueryui.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/multi_instance.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/multiple_tables.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/new_init.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/pdf_message.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/plug-in.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/select_column.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/select_multi.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/select_os.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/select_single.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/simple.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/examples/swf_path.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/collection.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/collection_hover.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/copy.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/copy_hover.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/csv.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/csv_hover.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/pdf.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/pdf_hover.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/print.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/print_hover.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/psd/collection.psd create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/psd/copy document.psd create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/psd/file_types.psd create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/psd/printer.psd create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/xls.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/images/xls_hover.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/js/dataTables.tableTools.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/js/dataTables.tableTools.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/swf/copy_csv_xls.swf create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/extensions/TableTools/swf/copy_csv_xls_pdf.swf create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/images/sort_asc.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/images/sort_asc_disabled.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/images/sort_both.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/images/sort_desc.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/images/sort_desc_disabled.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/jquery.dataTables.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/jquery.dataTables.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/jquery.dataTables.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/jquery.dataTables.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datatables/jquery.dataTables_themeroller.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/bootstrap-datepicker.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/datepicker3.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ar.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.az.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.bg.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ca.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.cs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.cy.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.da.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.de.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.el.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.es.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.et.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.fa.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.fi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.fr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.gl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.he.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.hr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.hu.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.id.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.is.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.it.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ja.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ka.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.kk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.kr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.lt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.lv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.mk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ms.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.nb.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.nl-BE.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.nl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.no.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.pl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.pt-BR.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.pt.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ro.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.rs-latin.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.rs.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ru.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.sk.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.sl.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.sq.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.sv.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.sw.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.th.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.tr.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.ua.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.vi.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.zh-CN.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/datepicker/locales/bootstrap-datepicker.zh-TW.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/daterangepicker/daterangepicker.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/daterangepicker/daterangepicker.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/daterangepicker/moment.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/daterangepicker/moment.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fastclick/fastclick.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fastclick/fastclick.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/excanvas.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/excanvas.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.colorhelpers.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.colorhelpers.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.canvas.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.canvas.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.categories.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.categories.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.crosshair.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.crosshair.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.errorbars.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.errorbars.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.fillbetween.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.fillbetween.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.image.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.image.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.navigate.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.navigate.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.pie.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.pie.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.resize.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.resize.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.selection.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.selection.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.stack.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.stack.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.symbol.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.symbol.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.threshold.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.threshold.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.time.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/flot/jquery.flot.time.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fullcalendar/fullcalendar.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fullcalendar/fullcalendar.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fullcalendar/fullcalendar.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fullcalendar/fullcalendar.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/fullcalendar/fullcalendar.print.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/all.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/_all.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/aero.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/aero.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/aero@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/blue.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/blue.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/blue@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/flat.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/flat.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/flat@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/green.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/green.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/green@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/grey.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/grey.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/grey@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/orange.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/orange.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/orange@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/pink.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/pink.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/pink@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/purple.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/purple.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/purple@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/red.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/red.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/red@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/yellow.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/yellow.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/flat/yellow@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/futurico/futurico.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/futurico/futurico.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/futurico/futurico@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/icheck.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/icheck.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/_all.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/aero.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/blue.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/green.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/grey.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/line.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/line.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/line@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/orange.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/pink.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/purple.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/red.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/line/yellow.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/_all.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/aero.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/aero.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/aero@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/blue.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/blue.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/blue@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/green.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/green.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/green@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/grey.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/grey.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/grey@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/minimal.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/minimal.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/minimal@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/orange.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/orange.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/orange@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/pink.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/pink.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/pink@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/purple.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/purple.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/purple@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/red.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/red.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/red@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/yellow.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/yellow.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/minimal/yellow@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/polaris/polaris.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/polaris/polaris.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/polaris/polaris@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/_all.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/aero.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/aero.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/aero@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/blue.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/blue.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/blue@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/green.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/green.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/green@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/grey.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/grey.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/grey@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/orange.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/orange.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/orange@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/pink.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/pink.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/pink@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/purple.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/purple.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/purple@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/red.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/red.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/red@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/square.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/square.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/square@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/yellow.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/yellow.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/iCheck/square/yellow@2x.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/jquery.inputmask.date.extensions.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/jquery.inputmask.extensions.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/jquery.inputmask.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/jquery.inputmask.numeric.extensions.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/jquery.inputmask.phone.extensions.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/jquery.inputmask.regex.extensions.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/phone-codes/phone-be.json create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/phone-codes/phone-codes.json create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/input-mask/phone-codes/readme.txt create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ionslider/img/sprite-skin-flat.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ionslider/img/sprite-skin-nice.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ionslider/ion.rangeSlider.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ionslider/ion.rangeSlider.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ionslider/ion.rangeSlider.skinFlat.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/ionslider/ion.rangeSlider.skinNice.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jQuery/jquery-2.2.3.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jQueryUI/jquery-ui.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jQueryUI/jquery-ui.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jvectormap/jquery-jvectormap-1.2.2.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jvectormap/jquery-jvectormap-1.2.2.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jvectormap/jquery-jvectormap-usa-en.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/jvectormap/jquery-jvectormap-world-mill-en.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/knob/jquery.knob.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/morris/morris.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/morris/morris.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/morris/morris.min.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/pace/pace.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/pace/pace.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/pace/pace.min.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/pace/pace.min.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ar.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/az.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/bg.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ca.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/cs.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/da.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/de.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/el.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/en.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/es.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/et.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/eu.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/fa.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/fi.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/fr.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/gl.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/he.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/hi.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/hr.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/hu.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/id.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/is.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/it.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ja.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/km.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ko.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/lt.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/lv.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/mk.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ms.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/nb.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/nl.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/pl.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/pt-BR.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/pt.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ro.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/ru.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/sk.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/sr-Cyrl.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/sr.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/sv.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/th.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/tr.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/uk.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/vi.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/zh-CN.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/i18n/zh-TW.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/select2.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/select2.full.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/select2.full.min.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/select2.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/select2.min.css create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/select2/select2.min.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/slimScroll/jquery.slimscroll.js create mode 100755 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/slimScroll/jquery.slimscroll.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/sparkline/jquery.sparkline.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/sparkline/jquery.sparkline.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/timepicker/bootstrap-timepicker.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/timepicker/bootstrap-timepicker.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/timepicker/bootstrap-timepicker.min.css create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/plugins/timepicker/bootstrap-timepicker.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/starter.html create mode 100644 ceph/src/pybind/mgr/dashboard/static/Ceph_Logo_Standard_RGB_White_120411_fa.png create mode 100644 ceph/src/pybind/mgr/dashboard/static/favicon.ico create mode 100644 ceph/src/pybind/mgr/dashboard/static/rivets.bundled.min.js create mode 100644 ceph/src/pybind/mgr/dashboard/static/underscore-min.js rename ceph/src/pybind/mgr/{rest/app => dashboard}/types.py (71%) delete mode 100644 ceph/src/pybind/mgr/rest/app/fixtures/ceph_fake.json delete mode 100644 ceph/src/pybind/mgr/rest/app/management/commands/api_docs.py delete mode 100644 ceph/src/pybind/mgr/rest/app/manager/osd_request_factory.py delete mode 100644 ceph/src/pybind/mgr/rest/app/manager/pool_request_factory.py delete mode 100644 ceph/src/pybind/mgr/rest/app/manager/request_collection.py delete mode 100644 ceph/src/pybind/mgr/rest/app/manager/request_factory.py delete mode 100644 ceph/src/pybind/mgr/rest/app/manager/user_request.py delete mode 100644 ceph/src/pybind/mgr/rest/app/models.py delete mode 100644 ceph/src/pybind/mgr/rest/app/serializers/fields.py delete mode 100644 ceph/src/pybind/mgr/rest/app/serializers/v2.py delete mode 100644 ceph/src/pybind/mgr/rest/app/settings.py delete mode 100644 ceph/src/pybind/mgr/rest/app/urls/__init__.py delete mode 100644 ceph/src/pybind/mgr/rest/app/urls/v2.py delete mode 100644 ceph/src/pybind/mgr/rest/app/util.py delete mode 100644 ceph/src/pybind/mgr/rest/app/views/__init__.py delete mode 100644 ceph/src/pybind/mgr/rest/app/views/paginated_mixin.py delete mode 100644 ceph/src/pybind/mgr/rest/app/views/rpc_view.py delete mode 100644 ceph/src/pybind/mgr/rest/app/views/v2.py delete mode 100644 ceph/src/pybind/mgr/rest/logger.py delete mode 100644 ceph/src/pybind/mgr/rest/module.py create mode 100644 ceph/src/pybind/mgr/restful/__init__.py create mode 100644 ceph/src/pybind/mgr/restful/api/__init__.py create mode 100644 ceph/src/pybind/mgr/restful/api/config.py create mode 100644 ceph/src/pybind/mgr/restful/api/crush.py create mode 100644 ceph/src/pybind/mgr/restful/api/doc.py create mode 100644 ceph/src/pybind/mgr/restful/api/mon.py create mode 100644 ceph/src/pybind/mgr/restful/api/osd.py create mode 100644 ceph/src/pybind/mgr/restful/api/pool.py create mode 100644 ceph/src/pybind/mgr/restful/api/request.py create mode 100644 ceph/src/pybind/mgr/restful/api/server.py create mode 100644 ceph/src/pybind/mgr/restful/common.py create mode 100644 ceph/src/pybind/mgr/restful/decorators.py create mode 100644 ceph/src/pybind/mgr/restful/hooks.py create mode 100644 ceph/src/pybind/mgr/restful/module.py create mode 100644 ceph/src/rapidjson/.gitattributes create mode 100644 ceph/src/rapidjson/.gitmodules create mode 100644 ceph/src/rapidjson/.travis.yml create mode 100644 ceph/src/rapidjson/CHANGELOG.md create mode 100644 ceph/src/rapidjson/CMakeLists.txt create mode 100644 ceph/src/rapidjson/CMakeModules/FindGTestSrc.cmake create mode 100644 ceph/src/rapidjson/RapidJSON.pc.in create mode 100644 ceph/src/rapidjson/RapidJSONConfig.cmake.in create mode 100644 ceph/src/rapidjson/RapidJSONConfigVersion.cmake.in create mode 100644 ceph/src/rapidjson/appveyor.yml create mode 100644 ceph/src/rapidjson/bin/data/glossary.json create mode 100644 ceph/src/rapidjson/bin/data/menu.json create mode 100644 ceph/src/rapidjson/bin/data/readme.txt create mode 100644 ceph/src/rapidjson/bin/data/sample.json create mode 100644 ceph/src/rapidjson/bin/data/webapp.json create mode 100644 ceph/src/rapidjson/bin/data/widget.json create mode 100644 ceph/src/rapidjson/bin/draft-04/schema create mode 100644 ceph/src/rapidjson/bin/encodings/utf16be.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf16bebom.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf16le.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf16lebom.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf32be.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf32bebom.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf32le.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf32lebom.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf8.json create mode 100644 ceph/src/rapidjson/bin/encodings/utf8bom.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail1.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail10.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail11.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail12.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail13.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail14.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail15.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail16.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail17.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail18.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail19.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail2.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail20.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail21.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail22.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail23.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail24.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail25.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail26.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail27.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail28.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail29.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail3.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail30.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail31.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail32.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail33.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail4.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail5.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail6.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail7.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail8.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/fail9.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/pass1.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/pass2.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/pass3.json create mode 100644 ceph/src/rapidjson/bin/jsonchecker/readme.txt create mode 100644 ceph/src/rapidjson/bin/jsonschema/.travis.yml create mode 100644 ceph/src/rapidjson/bin/jsonschema/LICENSE create mode 100644 ceph/src/rapidjson/bin/jsonschema/README.md create mode 100755 ceph/src/rapidjson/bin/jsonschema/bin/jsonschema_suite create mode 100644 ceph/src/rapidjson/bin/jsonschema/remotes/.DS_Store create mode 100644 ceph/src/rapidjson/bin/jsonschema/remotes/folder/folderInteger.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/remotes/integer.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/remotes/subSchemas.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/.DS_Store create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/additionalItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/additionalProperties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/default.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/dependencies.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/disallow.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/divisibleBy.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/enum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/extends.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/items.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/maxItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/maxLength.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/maximum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/minItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/minLength.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/minimum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/optional/bignum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/optional/format.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/optional/jsregex.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/optional/zeroTerminatedFloats.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/pattern.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/patternProperties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/properties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/ref.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/refRemote.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/required.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/type.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft3/uniqueItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/.DS_Store create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/additionalItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/additionalProperties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/allOf.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/anyOf.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/default.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/definitions.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/dependencies.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/enum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/items.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/maxItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/maxLength.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/maxProperties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/maximum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/minItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/minLength.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/minProperties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/minimum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/multipleOf.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/not.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/oneOf.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/optional/bignum.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/optional/format.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/optional/zeroTerminatedFloats.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/pattern.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/patternProperties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/properties.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/ref.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/refRemote.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/required.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/type.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tests/draft4/uniqueItems.json create mode 100644 ceph/src/rapidjson/bin/jsonschema/tox.ini create mode 100755 ceph/src/rapidjson/bin/types/booleans.json create mode 100755 ceph/src/rapidjson/bin/types/floats.json create mode 100755 ceph/src/rapidjson/bin/types/guids.json create mode 100755 ceph/src/rapidjson/bin/types/integers.json create mode 100755 ceph/src/rapidjson/bin/types/mixed.json create mode 100755 ceph/src/rapidjson/bin/types/nulls.json create mode 100755 ceph/src/rapidjson/bin/types/paragraphs.json create mode 100644 ceph/src/rapidjson/bin/types/readme.txt create mode 100644 ceph/src/rapidjson/doc/CMakeLists.txt create mode 100644 ceph/src/rapidjson/doc/Doxyfile.in create mode 100644 ceph/src/rapidjson/doc/Doxyfile.zh-cn.in create mode 100644 ceph/src/rapidjson/doc/diagram/architecture.dot create mode 100644 ceph/src/rapidjson/doc/diagram/architecture.png create mode 100644 ceph/src/rapidjson/doc/diagram/insituparsing.dot create mode 100644 ceph/src/rapidjson/doc/diagram/insituparsing.png create mode 100644 ceph/src/rapidjson/doc/diagram/iterative-parser-states-diagram.dot create mode 100644 ceph/src/rapidjson/doc/diagram/iterative-parser-states-diagram.png create mode 100644 ceph/src/rapidjson/doc/diagram/makefile create mode 100644 ceph/src/rapidjson/doc/diagram/move1.dot create mode 100644 ceph/src/rapidjson/doc/diagram/move1.png create mode 100644 ceph/src/rapidjson/doc/diagram/move2.dot create mode 100644 ceph/src/rapidjson/doc/diagram/move2.png create mode 100644 ceph/src/rapidjson/doc/diagram/move3.dot create mode 100644 ceph/src/rapidjson/doc/diagram/move3.png create mode 100644 ceph/src/rapidjson/doc/diagram/normalparsing.dot create mode 100644 ceph/src/rapidjson/doc/diagram/normalparsing.png create mode 100644 ceph/src/rapidjson/doc/diagram/simpledom.dot create mode 100644 ceph/src/rapidjson/doc/diagram/simpledom.png create mode 100644 ceph/src/rapidjson/doc/diagram/tutorial.dot create mode 100644 ceph/src/rapidjson/doc/diagram/tutorial.png create mode 100644 ceph/src/rapidjson/doc/diagram/utilityclass.dot create mode 100644 ceph/src/rapidjson/doc/diagram/utilityclass.png create mode 100644 ceph/src/rapidjson/doc/dom.md create mode 100644 ceph/src/rapidjson/doc/dom.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/encoding.md create mode 100644 ceph/src/rapidjson/doc/encoding.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/faq.md create mode 100644 ceph/src/rapidjson/doc/faq.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/features.md create mode 100644 ceph/src/rapidjson/doc/features.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/internals.md create mode 100644 ceph/src/rapidjson/doc/logo/rapidjson.png create mode 100644 ceph/src/rapidjson/doc/logo/rapidjson.svg create mode 100644 ceph/src/rapidjson/doc/misc/DoxygenLayout.xml create mode 100644 ceph/src/rapidjson/doc/misc/doxygenextra.css create mode 100644 ceph/src/rapidjson/doc/misc/footer.html create mode 100644 ceph/src/rapidjson/doc/misc/header.html create mode 100644 ceph/src/rapidjson/doc/npm.md create mode 100644 ceph/src/rapidjson/doc/performance.md create mode 100644 ceph/src/rapidjson/doc/performance.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/pointer.md create mode 100644 ceph/src/rapidjson/doc/pointer.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/sax.md create mode 100644 ceph/src/rapidjson/doc/sax.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/schema.md create mode 100644 ceph/src/rapidjson/doc/schema.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/stream.md create mode 100644 ceph/src/rapidjson/doc/stream.zh-cn.md create mode 100644 ceph/src/rapidjson/doc/tutorial.md create mode 100644 ceph/src/rapidjson/doc/tutorial.zh-cn.md create mode 100644 ceph/src/rapidjson/docker/debian/Dockerfile create mode 100644 ceph/src/rapidjson/example/CMakeLists.txt create mode 100644 ceph/src/rapidjson/example/capitalize/capitalize.cpp create mode 100644 ceph/src/rapidjson/example/condense/condense.cpp create mode 100644 ceph/src/rapidjson/example/filterkey/filterkey.cpp create mode 100644 ceph/src/rapidjson/example/filterkeydom/filterkeydom.cpp create mode 100644 ceph/src/rapidjson/example/jsonx/jsonx.cpp create mode 100644 ceph/src/rapidjson/example/messagereader/messagereader.cpp create mode 100644 ceph/src/rapidjson/example/parsebyparts/parsebyparts.cpp create mode 100644 ceph/src/rapidjson/example/pretty/pretty.cpp create mode 100644 ceph/src/rapidjson/example/prettyauto/prettyauto.cpp create mode 100644 ceph/src/rapidjson/example/schemavalidator/schemavalidator.cpp create mode 100644 ceph/src/rapidjson/example/serialize/serialize.cpp create mode 100644 ceph/src/rapidjson/example/simpledom/simpledom.cpp create mode 100644 ceph/src/rapidjson/example/simplereader/simplereader.cpp create mode 100644 ceph/src/rapidjson/example/simplewriter/simplewriter.cpp create mode 100644 ceph/src/rapidjson/example/tutorial/tutorial.cpp create mode 100644 ceph/src/rapidjson/include/rapidjson/allocators.h create mode 100644 ceph/src/rapidjson/include/rapidjson/document.h create mode 100644 ceph/src/rapidjson/include/rapidjson/encodedstream.h create mode 100644 ceph/src/rapidjson/include/rapidjson/encodings.h create mode 100644 ceph/src/rapidjson/include/rapidjson/error/en.h create mode 100644 ceph/src/rapidjson/include/rapidjson/error/error.h create mode 100644 ceph/src/rapidjson/include/rapidjson/filereadstream.h create mode 100644 ceph/src/rapidjson/include/rapidjson/filewritestream.h create mode 100644 ceph/src/rapidjson/include/rapidjson/fwd.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/biginteger.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/diyfp.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/dtoa.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/ieee754.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/itoa.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/meta.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/pow10.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/regex.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/stack.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/strfunc.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/strtod.h create mode 100644 ceph/src/rapidjson/include/rapidjson/internal/swap.h create mode 100644 ceph/src/rapidjson/include/rapidjson/istreamwrapper.h create mode 100644 ceph/src/rapidjson/include/rapidjson/memorybuffer.h create mode 100644 ceph/src/rapidjson/include/rapidjson/memorystream.h create mode 100644 ceph/src/rapidjson/include/rapidjson/msinttypes/inttypes.h create mode 100644 ceph/src/rapidjson/include/rapidjson/msinttypes/stdint.h create mode 100644 ceph/src/rapidjson/include/rapidjson/ostreamwrapper.h create mode 100644 ceph/src/rapidjson/include/rapidjson/pointer.h create mode 100644 ceph/src/rapidjson/include/rapidjson/prettywriter.h create mode 100644 ceph/src/rapidjson/include/rapidjson/rapidjson.h create mode 100644 ceph/src/rapidjson/include/rapidjson/reader.h create mode 100644 ceph/src/rapidjson/include/rapidjson/schema.h create mode 100644 ceph/src/rapidjson/include/rapidjson/stream.h create mode 100644 ceph/src/rapidjson/include/rapidjson/stringbuffer.h create mode 100644 ceph/src/rapidjson/include/rapidjson/writer.h create mode 100644 ceph/src/rapidjson/include_dirs.js create mode 100644 ceph/src/rapidjson/library.json create mode 100644 ceph/src/rapidjson/license.txt create mode 100644 ceph/src/rapidjson/package.json create mode 100644 ceph/src/rapidjson/rapidjson.autopkg create mode 100644 ceph/src/rapidjson/readme.md create mode 100644 ceph/src/rapidjson/readme.zh-cn.md create mode 100644 ceph/src/rapidjson/test/CMakeLists.txt create mode 100644 ceph/src/rapidjson/test/perftest/CMakeLists.txt create mode 100644 ceph/src/rapidjson/test/perftest/misctest.cpp create mode 100644 ceph/src/rapidjson/test/perftest/perftest.cpp create mode 100644 ceph/src/rapidjson/test/perftest/perftest.h create mode 100644 ceph/src/rapidjson/test/perftest/platformtest.cpp create mode 100644 ceph/src/rapidjson/test/perftest/rapidjsontest.cpp create mode 100644 ceph/src/rapidjson/test/perftest/schematest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/CMakeLists.txt create mode 100644 ceph/src/rapidjson/test/unittest/allocatorstest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/bigintegertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/documenttest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/dtoatest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/encodedstreamtest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/encodingstest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/filestreamtest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/fwdtest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/istreamwrappertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/itoatest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/jsoncheckertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/namespacetest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/ostreamwrappertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/pointertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/prettywritertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/readertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/regextest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/schematest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/simdtest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/strfunctest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/stringbuffertest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/strtodtest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/unittest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/unittest.h create mode 100644 ceph/src/rapidjson/test/unittest/valuetest.cpp create mode 100644 ceph/src/rapidjson/test/unittest/writertest.cpp create mode 100644 ceph/src/rapidjson/thirdparty/gtest/.travis.yml create mode 100644 ceph/src/rapidjson/thirdparty/gtest/CMakeLists.txt create mode 100644 ceph/src/rapidjson/thirdparty/gtest/README.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/CHANGES create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/CMakeLists.txt create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/CONTRIBUTORS create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/LICENSE create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/Makefile.am create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/README.md rename ceph/src/{pybind/mgr/rest/app/management/commands/__init__.py => rapidjson/thirdparty/gtest/googlemock/build-aux/.keep} (100%) create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/configure.ac create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/CheatSheet.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/CookBook.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/DesignDoc.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/DevGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/ForDummies.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/FrequentlyAskedQuestions.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/KnownIssues.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_5/CheatSheet.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_5/CookBook.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_5/Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_5/ForDummies.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_5/FrequentlyAskedQuestions.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_6/CheatSheet.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_6/CookBook.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_6/Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_6/ForDummies.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_6/FrequentlyAskedQuestions.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_7/CheatSheet.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_7/CookBook.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_7/Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_7/ForDummies.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/docs/v1_7/FrequentlyAskedQuestions.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-actions.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-cardinalities.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-matchers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-more-actions.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-more-matchers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-spec-builders.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-matchers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-port.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-internal-utils.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-port.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/make/Makefile create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock.sln create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_config.vsprops create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_main.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_test.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock.sln create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock.vcxproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_config.props create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_main.vcxproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_test.vcxproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock.sln create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock.vcxproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock_config.props create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock_main.vcxproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock_test.vcxproj create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/fuse_gmock_files.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/LICENSE create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/README create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/README.cppclean rename ceph/src/{pybind/mgr/rest/app/manager => rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp}/__init__.py (100%) mode change 100644 => 100755 create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/ast.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/gmock_class.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/gmock_class_test.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/keywords.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/tokenize.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/utils.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/generator/gmock_gen.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/gmock-config.in create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/gmock_doctor.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/upload.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/upload_gmock.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock-all.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock-cardinalities.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock-internal-utils.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock-matchers.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock-spec-builders.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/src/gmock_main.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-actions_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-cardinalities_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-actions_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-function-mockers_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-internal-utils_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-matchers_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-internal-utils_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-matchers_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-more-actions_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-nice-strict_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-port_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock-spec-builders_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_all_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_ex_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_leak_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_leak_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_link2_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_link_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_link_test.h create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_output_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_output_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_output_test_golden.txt create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_stress_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googlemock/test/gmock_test_utils.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/CHANGES create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/CMakeLists.txt create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/CONTRIBUTORS create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/LICENSE create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/Makefile.am create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/README.md rename ceph/src/{pybind/mgr/rest/app/serializers/__init__.py => rapidjson/thirdparty/gtest/googletest/build-aux/.keep} (100%) create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/cmake/internal_utils.cmake create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/codegear/gtest.cbproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/codegear/gtest.groupproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_all.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_link.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_main.cbproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_unittest.cbproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/configure.ac create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/AdvancedGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/DevGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/FAQ.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/Primer.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/PumpManual.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/Samples.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_5_AdvancedGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_5_Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_5_FAQ.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_5_Primer.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_5_PumpManual.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_5_XcodeGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_AdvancedGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_FAQ.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_Primer.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_PumpManual.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_Samples.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_6_XcodeGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_AdvancedGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_Documentation.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_FAQ.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_Primer.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_PumpManual.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_Samples.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/V1_7_XcodeGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/docs/XcodeGuide.md create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-death-test.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-message.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-param-test.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-param-test.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-printers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-spi.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-test-part.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-typed-test.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest_pred_impl.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest_prod.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/custom/gtest-port.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/custom/gtest-printers.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/custom/gtest.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-death-test-internal.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-filepath.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-internal.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-linked_ptr.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-param-util-generated.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-param-util-generated.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-param-util.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-port-arch.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-port.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-string.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-tuple.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-tuple.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-type-util.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-type-util.h.pump create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/m4/acx_pthread.m4 create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/m4/gtest.m4 create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/make/Makefile create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest-md.sln create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest-md.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest.sln create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_main-md.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_main.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_prod_test-md.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_prod_test.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_unittest-md.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_unittest.vcproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/prime_tables.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample1.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample1.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample10_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample1_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample2.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample2.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample2_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample3-inl.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample3_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample4.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample4.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample4_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample5_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample6_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample7_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample8_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/samples/sample9_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/common.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/fuse_gtest_files.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/gen_gtest_pred_impl.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/gtest-config.in create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/pump.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/release_docs.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/test/Makefile create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/upload.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/scripts/upload_gtest.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-all.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-death-test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-filepath.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-internal-inl.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-port.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-printers.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-test-part.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest-typed-test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/src/gtest_main.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-death-test_ex_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-death-test_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-filepath_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-linked_ptr_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-listener_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-message_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-options_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-param-test2_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-param-test_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-param-test_test.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-port_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-printers_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-test-part_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-tuple_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-typed-test2_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-typed-test_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-typed-test_test.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest-unittest-api_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_all_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_break_on_failure_unittest.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_break_on_failure_unittest_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_catch_exceptions_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_catch_exceptions_test_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_color_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_color_test_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_env_var_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_env_var_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_environment_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_filter_unittest.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_filter_unittest_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_help_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_help_test_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_list_tests_unittest.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_list_tests_unittest_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_main_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_no_test_unittest.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_output_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_output_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_output_test_golden_lin.txt create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_pred_impl_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_premature_exit_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_prod_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_repeat_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_shuffle_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_shuffle_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_sole_header_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_stress_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_test_utils.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_throw_on_failure_ex_test.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_throw_on_failure_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_throw_on_failure_test_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_uninitialized_test.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_uninitialized_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_unittest.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_outfile1_test_.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_outfile2_test_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_outfiles_test.py create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_output_unittest.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_output_unittest_.cc create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_test_utils.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/production.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/test/production.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Config/DebugProject.xcconfig create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Config/FrameworkTarget.xcconfig create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Config/General.xcconfig create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Config/ReleaseProject.xcconfig create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Config/StaticLibraryTarget.xcconfig create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Config/TestTarget.xcconfig create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Resources/Info.plist create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/Info.plist create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/runtests.sh create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/widget.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/widget.h create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/widget_test.cc create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Scripts/runtests.sh create mode 100755 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/Scripts/versiongenerate.py create mode 100644 ceph/src/rapidjson/thirdparty/gtest/googletest/xcode/gtest.xcodeproj/project.pbxproj create mode 100755 ceph/src/rapidjson/thirdparty/gtest/travis.sh create mode 100755 ceph/src/rapidjson/travis-doxygen.sh delete mode 100644 ceph/src/rgw/rgw_boost_asio_coroutine.h delete mode 100644 ceph/src/rgw/rgw_boost_asio_yield.h create mode 100644 ceph/src/rgw/rgw_es_main.cc create mode 100644 ceph/src/rgw/rgw_es_query.cc create mode 100644 ceph/src/rgw/rgw_es_query.h create mode 100644 ceph/src/rgw/rgw_iam_policy.cc create mode 100644 ceph/src/rgw/rgw_iam_policy.h create mode 100644 ceph/src/rgw/rgw_iam_policy_keywords.gperf create mode 100644 ceph/src/rgw/rgw_iam_policy_keywords.h create mode 100644 ceph/src/rgw/rgw_reshard.cc create mode 100644 ceph/src/rgw/rgw_reshard.h create mode 100644 ceph/src/rgw/rgw_sync_module_es_rest.cc create mode 100644 ceph/src/rgw/rgw_sync_module_es_rest.h create mode 100755 ceph/src/script/check_commands.sh create mode 100644 ceph/src/test/admin_socket_output.cc create mode 100644 ceph/src/test/admin_socket_output.h create mode 100644 ceph/src/test/admin_socket_output_tests.cc create mode 100644 ceph/src/test/admin_socket_output_tests.h create mode 100644 ceph/src/test/common/test_iso_8601.cc create mode 100644 ceph/src/test/crush/crush-choose-args-expected-one-more-0.txt create mode 100644 ceph/src/test/crush/crush-choose-args-expected-one-more-3.txt create mode 100755 ceph/src/test/crush/crush-choose-args.sh create mode 100644 ceph/src/test/encoding/test_sstring.h create mode 100644 ceph/src/test/librados/test_common.cc create mode 100644 ceph/src/test/librados/test_common.h create mode 100644 ceph/src/test/mgr/CMakeLists.txt create mode 100755 ceph/src/test/mgr/mgr-dashboard-smoke.sh create mode 100644 ceph/src/test/osd/test_ec_transaction.cc create mode 100644 ceph/src/test/rgw/rgw_multi/conn.py create mode 100644 ceph/src/test/rgw/rgw_multi/tests_es.py create mode 100644 ceph/src/test/rgw/rgw_multi/tools.py create mode 100644 ceph/src/test/rgw/rgw_multi/zone_es.py create mode 100644 ceph/src/test/rgw/rgw_multi/zone_rados.py create mode 100644 ceph/src/test/rgw/test_rgw_iam_policy.cc create mode 100644 ceph/src/test/rgw/test_rgw_string.cc create mode 100644 ceph/src/test/test_admin_socket_output.cc create mode 100644 ceph/src/test/test_features.cc create mode 100644 ceph/src/tracing/cyg_profile.c create mode 100644 ceph/src/tracing/cyg_profile.tp create mode 100644 ceph/src/tracing/cyg_profile_functions.c diff --git a/Makefile b/Makefile index d4fb8b6be..0885d4f23 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ RELEASE=5.0 PACKAGE=ceph -VER=12.0.3 -DEBREL=pve3 +VER=12.1.0 +DEBREL=pve1 SRCDIR=ceph BUILDSRC=${SRCDIR}-${VER} diff --git a/ceph/.gitmodules b/ceph/.gitmodules index 488cd8953..85a78ace7 100644 --- a/ceph/.gitmodules +++ b/ceph/.gitmodules @@ -55,3 +55,6 @@ [submodule "src/blkin"] path = src/blkin url = https://github.com/ceph/blkin +[submodule "src/rapidjson"] + path = src/rapidjson + url = https://github.com/ceph/rapidjson diff --git a/ceph/.mailmap b/ceph/.mailmap index 7177ca847..802ba32bb 100644 --- a/ceph/.mailmap +++ b/ceph/.mailmap @@ -59,6 +59,8 @@ Chen Dihao Chendi Xue Chendi Xue Cheng Cheng +Chu Hua-Rong +Chu Hua-Rong Chris Holcombe Christian Brunner Christian Marie @@ -140,9 +142,11 @@ Haomai Wang Haomai Wang Harry Harrington Hazem Amara +He Chuang Henry C Chang Hervé Rousseau Holger Macht +Hongtong Liu Hong Zhangoole Huamin Chen Huang Jun @@ -174,6 +178,8 @@ Jenkins Jenkins Jenkins Build Slave User Jenkins Jenkins Build Slave User +Jesse Williamson +Jesse Williamson Jiang Heng Jiantao He Jian Wen @@ -206,6 +212,7 @@ Jonas Keidel Jordan Dorne Josh Durgin Josh Durgin +Josh Durgin Josh Durgin Josh Durgin Kacper Kowalik @@ -218,11 +225,14 @@ Kiseleva Alyona Kongming Wu Lan De Laszlo Boszormenyi +Leo Zhang Luo Kexue Luo Runbing Luo Runbing +Li Hongjie Li Wang Linfei Hou +Liu Hong Liu Peiyan Li Tianqing Liu Yang @@ -353,7 +363,8 @@ Shehbaz Jaffer Shinobu Kinjo Shinobu Kinjo Shishir Gowda -shiqi <1454927420@qq.com> +Shiqi +Shiqi <1454927420@qq.com> Shu, Xinxin Shun Song Shun Song @@ -387,6 +398,7 @@ Tobias Suckow Tommi Virtanen Tommi Virtanen Tommi Virtanen +Tone Zhang Travis Rhoden Tyler Brekke Uday Mullangi @@ -434,6 +446,7 @@ Yannick Atchy Dalama Yankun Li Yan, Zheng Yan, Zheng +Yanchun Bai Yehua Chen Yehua Chen Yehuda Sadeh @@ -452,6 +465,7 @@ Yehuda Sadeh Yongqiang He Yongyue Sun You Ji +Yunfei Guan Yuan Zhou Yunchuan Wen Yuri Weinstein diff --git a/ceph/.organizationmap b/ceph/.organizationmap index 421ab8f67..17464131a 100644 --- a/ceph/.organizationmap +++ b/ceph/.organizationmap @@ -23,6 +23,7 @@ # 9 27 TCloud Computing # 10 22 GNU # +99Cloud Inc Yu Shengzuo Acaleph Alistair Israel Alcatel Lucent Joseph McDonald Alcatel Lucent Ker Liu @@ -66,14 +67,15 @@ China Mobile donglinpeng Gui Hecheng China Mobile Guo Zhandong China Mobile Jing Wenjun -China Mobile lihongjie +China Mobile Li Hongjie +China Mobile Liu Hong China Mobile lvshuhua China Mobile Zhang Shaowen China Mobile wangzhengyong Chinac Huan Zhang Chinac Xinxin Shu Choopa, LLC Adam Twardowski -Chunghwa Telecom hrchu +Chunghwa Telecom Chu Hua-Rong CISCO Johnu George CISCO Kai Zhang CISCO Roland Mechler @@ -206,6 +208,7 @@ Hostplex Hosting Andras Elso HP Blaine Gardner HP Joe Handzik Huazhong University of Science and Technology Luo Runbing +IBM Andrew Solomon IBM Michel Normand IBM Samuel Matzek ICT Zhang Huan @@ -214,6 +217,7 @@ Igalia Javier M. Mellid Igalia Juan A. Suarez Romero Imagination Technologies Ltd. Alistair Strachan iNic Bjørnar Ness +Indraprastha Institute of Information Technology, Delhi Vedant Nanda Indiana University Jayashree Candadai Inktank Alexandre Marangone Inktank Alex Elder @@ -278,6 +282,7 @@ Iron Systems Inc. Harpreet Dhillon Hongtong Liu Istuary Innovation Group Pan Liu Istuary Innovation Group Tang Jin +Istuary Innovation Group Yanchun Bai IT Refined Ron Allred IWeb David Moreau Simard Johannes Gutenberg-Universität Mainz Marcel Lauhoff @@ -296,6 +301,7 @@ LETV Ji Chen LETV Wu Xingyi Linaro Steve Capper Linaro wei xiao +Linaro Tone Zhang Linaro Yazen Ghannam Linaro Yibo Cai Los Alamos National Laboratory Esteban Molina-Estolano @@ -339,6 +345,7 @@ Pacific Northwest National Laboratory Evan Felix Scott Devoid Piston Cloud Computing Mike Lundy Pogoapp Paul Meserve +Proxmox Server Solutions GmbH Fabian Grünbichler Purdue University Mike Shuey Quadrature Capital Limited Jim Wright Quantum Corporation Bassam Tabbara @@ -481,14 +488,17 @@ SUSE João Eduardo Luís SUSE Karl Eichwalder SUSE Karol Mroz SUSE Kapil Sharma +SUSE Mohamad Gebai SUSE Michal Koutný SUSE Nathan Cutler SUSE Owen Synge SUSE Ricardo Dias +SUSE Sven Seeberg SUSE Thorsten Behrens SUSE Tim Serong SWITCH Jens-Christian Fischer SWITCH Simon Leinen +T2Cloud Leo Zhang TCloud Computing CC Lien TCloud Computing Henry C Chang TCloud Computing Herb Shiu @@ -509,6 +519,7 @@ The University of Arizona James Ryan Cresawn Bryan Stillwell Trendy Tech shiqi Trendy Tech Lei Zhang <243290414@qq.com> +Uber Technologies Inc. Henrik Korkuc Ubuntu Kylin Min Chen UMCloud Jiaying Ren UMCloud Rongze Zhu @@ -624,7 +635,6 @@ Unaffiliated koleosfuscus Unaffiliated Kyr Shatskyy Unaffiliated Laurent Guerby Unaffiliated Lee Revell -Unaffiliated Leo Zhang Unaffiliated Lucas Fantinel Unaffiliated Коренберг Марк Unaffiliated Matt Richards @@ -644,6 +654,7 @@ Unaffiliated oddomatik Unaffiliated Oleh Prypin Unaffiliated optimistyzy Unaffiliated Pascal Bach +Unaffiliated Patrick Dinnen Unaffiliated Patrick Donnelly Unaffiliated Peter Maloney Unaffiliated Petertc Chu @@ -699,6 +710,7 @@ Unaffiliated Xu Biao Unaffiliated Yang Honggang Unaffiliated Yann Dupont Unaffiliated Yannick Atchy Dalama +Unaffiliated Yao Zongyou Unaffiliated Yatin Kumbhare Unaffiliated YiQiang Chen Unaffiliated Yongyue Sun @@ -735,6 +747,7 @@ University of Maryland Liam Monahan University of Maryland Padraig O'Sullivan University of Toronto Shehbaz Jaffer University of Utah Xing Lin +Virtuozzo Andrey Parfenov VRT Stuart Longland Walmart Labs Pavan Rallabhandi Walmart Labs Sirisha Guduru @@ -748,11 +761,13 @@ X-ION Mouad Benchchaoui X-ION Stephan Renatus XSky hechuang XSky Haomai Wang +XSky He Chuang XSky Min Chen XSky Mingxin Liu XSky Tianshan Qu XSky Xinze Chi XSky Zhiqiang Wang +XTao Co. Ltd. Yunfei Guan Yahoo! Guang Yang Yahoo! Haifeng Liu Yahoo! Lei Dong diff --git a/ceph/AUTHORS b/ceph/AUTHORS index 2760f21ed..6d62a6457 100644 --- a/ceph/AUTHORS +++ b/ceph/AUTHORS @@ -1,17 +1,14 @@ Maintainer ---------- - Sage Weil - Component Technical Leads ------------------------- - Core, RADOS - Josh Durgin RBD - Jason Dillaman RBD (kernel) - Ilya Dryomov RGW - Yehuda Sadeh - Matt Benjamin + Matt Benjamin CephFS - John Spray CephFS (kernel) - Yan, Zheng Deployment - Alfredo Deza @@ -19,10 +16,18 @@ Teuthology - Zack Cerza Calamari - Gregory Meno Chef Cookbook - Guilhem Lettron +Release Manager +--------------- +Abhishek Lekshmanan + +Backport Team +------------- +Nathan Cutler +Shinobu Kinjo +Abhishek Lekshmanan Contributors ------------ - For a complete contributor list: git shortlog -sn diff --git a/ceph/CMakeLists.txt b/ceph/CMakeLists.txt index 0dad01fda..d6695b2a2 100644 --- a/ceph/CMakeLists.txt +++ b/ceph/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8.11) project(ceph) -set(VERSION 12.0.3) +set(VERSION 12.1.0) if(POLICY CMP0046) # Tweak policies (this one disables "missing" dependency warning) @@ -22,7 +22,15 @@ endif() if(POLICY CMP0065) cmake_policy(SET CMP0065 NEW) endif() - +if(POLICY CMP0051) + # cmake 3.1 and higher include generator expressions in SOURCES property. + # in BuildBoost.cmake, get_target_property( SOURCES) is used + # to retrieve the source files of a target. in that case, we are only + # interested in the *source* files. and i don't want to bother stripping off + # the TARGET_OBJECTS elements from the returned SOURCES. so let's stick with + # the old behavior now. + cmake_policy(SET CMP0051 OLD) +endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") if(CMAKE_SYSTEM_NAME MATCHES "Linux") @@ -105,11 +113,10 @@ CHECK_FUNCTION_EXISTS(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP) CHECK_FUNCTION_EXISTS(pthread_setname_np HAVE_PTHREAD_SETNAME_NP) CHECK_FUNCTION_EXISTS(pthread_getname_np HAVE_PTHREAD_GETNAME_NP) CHECK_FUNCTION_EXISTS(eventfd HAVE_EVENTFD) +CHECK_FUNCTION_EXISTS(getprogname HAVE_GETPROGNAME) -CHECK_INCLUDE_FILES("inttypes.h" HAVE_INTTYPES_H) CHECK_INCLUDE_FILES("linux/types.h" HAVE_LINUX_TYPES_H) CHECK_INCLUDE_FILES("linux/version.h" HAVE_LINUX_VERSION_H) -CHECK_INCLUDE_FILES("stdint.h" HAVE_STDINT_H) CHECK_INCLUDE_FILES("arpa/nameser_compat.h" HAVE_ARPA_NAMESER_COMPAT_H) CHECK_INCLUDE_FILES("sys/mount.h" HAVE_SYS_MOUNT_H) CHECK_INCLUDE_FILES("sys/param.h" HAVE_SYS_PARAM_H) @@ -218,6 +225,12 @@ if(WITH_SPDK) set(HAVE_SPDK TRUE) endif(WITH_SPDK) +option(WITH_PMEM "Enable PMEM" OFF) +if(WITH_PMEM) + find_package(pmem REQUIRED) + set(HAVE_PMEM ${PMEM_FOUND}) +endif(WITH_PMEM) + # needs mds and? XXX option(WITH_LIBCEPHFS "libcephfs client library" ON) @@ -251,14 +264,14 @@ if(WITH_LEVELDB) find_file(HAVE_LEVELDB_FILTER_POLICY leveldb/filter_policy.h PATHS ${LEVELDB_INCLUDE_DIR}) endif(WITH_LEVELDB) -find_package(atomic_ops REQUIRED) -message(STATUS "${ATOMIC_OPS_LIBRARIES}") -if(NOT ${ATOMIC_OPS_FOUND}) - set(NO_ATOMIC_OPS 1) -endif(NOT ${ATOMIC_OPS_FOUND}) - find_package(snappy REQUIRED) +option(WITH_LZ4 "LZ4 compression support" OFF) +if(WITH_LZ4) + find_package(LZ4 REQUIRED) + set(HAVE_LZ4 ${LZ4_FOUND}) +endif(WITH_LZ4) + #if allocator is set on command line make sure it matches below strings if(ALLOCATOR) if(${ALLOCATOR} MATCHES "tcmalloc(_minimal)?") @@ -345,7 +358,7 @@ endif(WITH_BLKIN) #option for RGW option(WITH_RADOSGW "Rados Gateway is enabled" ON) -option(WITH_RADOSGW_FCGI_FRONTEND "Rados Gateway's FCGI frontend is enabled" ON) +option(WITH_RADOSGW_FCGI_FRONTEND "Rados Gateway's FCGI frontend is enabled" OFF) option(WITH_RADOSGW_BEAST_FRONTEND "Rados Gateway's Beast frontend is enabled" ON) if(WITH_RADOSGW) find_package(EXPAT REQUIRED) @@ -437,6 +450,8 @@ if(${WITH_LTTNG}) endif() endif(${WITH_LTTNG}) +option(WITH_OSD_INSTRUMENT_FUNCTIONS OFF) + #option for Babeltrace option(HAVE_BABELTRACE "Babeltrace libraries are enabled" ON) if(${HAVE_BABELTRACE}) @@ -513,90 +528,42 @@ endif() # Boost option(WITH_SYSTEM_BOOST "require and build with system Boost" OFF) +# Boost::thread depends on Boost::atomic, so list it explicitly. set(BOOST_COMPONENTS - container thread system regex random program_options date_time iostreams coroutine context) + atomic thread system regex random program_options date_time iostreams + filesystem) +set(BOOST_HEADER_COMPONENTS container) + if(WITH_MGR) list(APPEND BOOST_COMPONENTS python) endif() -if (WITH_SYSTEM_BOOST) +if(WITH_RADOSGW_BEAST_FRONTEND) + list(APPEND BOOST_COMPONENTS coroutine context) +endif() + +set(Boost_USE_MULTITHREADED ON) +# require minimally the bundled version +if(WITH_SYSTEM_BOOST) if(ENABLE_SHARED) set(Boost_USE_STATIC_LIBS OFF) else() set(Boost_USE_STATIC_LIBS ON) endif() + find_package(Boost 1.61 COMPONENTS ${BOOST_COMPONENTS} REQUIRED) else() - set(BOOST_CFLAGS "-fPIC -w") # check on arm, etc <---XXX set(BOOST_J 1 CACHE STRING "max jobs for Boost build") # override w/-DBOOST_J= - message(STATUS "BUILDING Boost Libraries at j ${BOOST_J}") - # 1. prep w/required components - set(BOOST_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src/boost") - set(BOOST_PREFIX "${PROJECT_BINARY_DIR}/boost") - set(BOOST_BUILD "${PROJECT_BINARY_DIR}/boost-build") - string(REPLACE ";" "," BOOST_WITH_LIBS "${BOOST_COMPONENTS}") - execute_process(COMMAND "./bootstrap.sh" - "--prefix=${BOOST_PREFIX}" - "--with-libraries=${BOOST_WITH_LIBS}" - WORKING_DIRECTORY ${BOOST_SOURCE_DIR}) - set(BOOST_ROOT "${BOOST_PREFIX}") - set(b2 ./b2 - --build-dir=${BOOST_BUILD} -j${BOOST_J}) - if(CMAKE_VERBOSE_MAKEFILE) - list(APPEND b2 -d1) - else() - list(APPEND b2 -d0) - endif() - list(APPEND b2 - variant=release link=static threading=multi cxxflags=${BOOST_CFLAGS}) - if(NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) - # we are crosscompiling - if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) - set(b2_cc gcc) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) - set(b2_cc clang) - else() - message(SEND_ERROR "unknown compiler: ${CMAKE_CXX_COMPILER_ID}") - endif() - # edit the config.jam so, b2 will be able to use the specified toolset - execute_process( - COMMAND - sed -i - "s|using ${b2_cc} ;|using ${b2_cc} : ${CMAKE_SYSTEM_PROCESSOR} : ${CMAKE_CXX_COMPILER} ;|" - ${PROJECT_SOURCE_DIR}/src/boost/project-config.jam) - # use ${CMAKE_SYSTEM_PROCESSOR} as the version identifier of compiler - list(APPEND b2 toolset=${b2_cc}-${CMAKE_SYSTEM_PROCESSOR}) - endif() - # 2. install headers - execute_process(COMMAND - ${b2} - headers - WORKING_DIRECTORY ${BOOST_SOURCE_DIR}) - # 3. build and install libs - execute_process(COMMAND - ${b2} - install - WORKING_DIRECTORY ${BOOST_SOURCE_DIR}) - # 4. set hints for FindBoost.cmake set(Boost_USE_STATIC_LIBS ON) - set(Boost_NO_SYSTEM_PATHS ON) - include_directories(BEFORE ${BOOST_PREFIX}/include) - # fixup for CheckIncludeFileCXX - set(HAVE_BOOST_ASIO_COROUTINE ON) - - set(BOOST_ROOT ${BOOST_PREFIX}) - set(Boost_NO_SYSTEM_PATHS ON) + include(BuildBoost) + build_boost(1.63 + COMPONENTS ${BOOST_COMPONENTS} ${BOOST_HEADER_COMPONENTS}) + include_directories(BEFORE SYSTEM ${Boost_INCLUDE_DIRS}) endif() - set(Boost_USE_MULTITHREADED ON) -# require minimally the bundled version -find_package(Boost 1.61 COMPONENTS ${BOOST_COMPONENTS} REQUIRED) -include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) include_directories(SYSTEM ${PROJECT_BINARY_DIR}/include) -CHECK_INCLUDE_FILE_CXX("boost/asio/coroutine.hpp" HAVE_BOOST_ASIO_COROUTINE) - find_package(Threads REQUIRED) option(WITH_SELINUX "build SELinux policy" OFF) @@ -636,5 +603,5 @@ add_tags(ctags SRC_DIR src TAG_FILE tags EXCLUDE_OPTS ${CTAG_EXCLUDES} - EXCLUDES "*.js") + EXCLUDES "*.js" "*.css") add_custom_target(tags DEPENDS ctags) diff --git a/ceph/COPYING b/ceph/COPYING index 189b1acb2..b7371e4f9 100644 --- a/ceph/COPYING +++ b/ceph/COPYING @@ -30,10 +30,6 @@ Files: src/common/bloom_filter.hpp Copyright: Copyright (C) 2000 Arash Partow License: Boost Software License, Version 1.0 -Files: m4/acx_pthread.m4 -Copyright: Steven G. Johnson -License: GPLWithACException - Files: src/common/crc32c_intel*: Copyright: Copyright 2012-2013 Intel Corporation All Rights Reserved. diff --git a/ceph/PendingReleaseNotes b/ceph/PendingReleaseNotes index 6386dd977..7f57cc52a 100644 --- a/ceph/PendingReleaseNotes +++ b/ceph/PendingReleaseNotes @@ -1,36 +1,7 @@ >= 12.0.0 ------ -* The original librados rados_objects_list_open (C) and objects_begin - (C++) object listing API, deprecated in Hammer, has finally been - removed. Users of this interface must update their software to use - either the rados_nobjects_list_open (C) and nobjects_begin (C++) API or - the new rados_object_list_begin (C) and object_list_begin (C++) API - before updating the client-side librados library to Luminous. - - Object enumeration (via any API) with the latest librados version - and pre-Hammer OSDs is no longer supported. Note that no in-tree - Ceph services rely on object enumeration via the deprecated APIs, so - only external librados users might be affected. - - The newest (and recommended) rados_object_list_begin (C) and - object_list_begin (C++) API is only usable on clusters with the - SORTBITWISE flag enabled (Jewel and later). (Note that this flag is - required to be set before upgrading beyond Jewel.) -* CephFS clients without the 'p' flag in their authentication capability - string will no longer be able to set quotas or any layout fields. This - flag previously only restricted modification of the pool and namespace - fields in layouts. -* CephFS directory fragmentation (large directory support) is enabled - by default on new filesystems. To enable it on existing filesystems - use "ceph fs set allow_dirfrags". -* CephFS will generate a health warning if you have fewer standby daemons - than it thinks you wanted. By default this will be 1 if you ever had - a standby, and 0 if you did not. You can customize this using - ``ceph fs set standby_count_wanted ``. Setting it - to zero will effectively disable the health check. -* The "ceph mds tell ..." command has been removed. It is superceded - by "ceph tell mds. ..." * The "journaler allow split entries" config setting has been removed. +* The 'apply' mode of cephfs-journal-tool has been removed 12.0.0 ------ @@ -121,3 +92,93 @@ * The 'rados df' JSON output now prints numeric values as numbers instead of strings. +* There was a bug introduced in Jewel (#19119) that broke the mapping behavior + when an "out" OSD that still existed in the CRUSH map was removed with 'osd rm'. + This could result in 'misdirected op' and other errors. The bug is now fixed, + but the fix itself introduces the same risk because the behavior may vary between + clients and OSDs. To avoid problems, please ensure that all OSDs are removed + from the CRUSH map before deleting them. That is, be sure to do:: + + ceph osd crush rm osd.123 + + before:: + + ceph osd rm osd.123 + +12.0.2 +------ + +* The original librados rados_objects_list_open (C) and objects_begin + (C++) object listing API, deprecated in Hammer, has finally been + removed. Users of this interface must update their software to use + either the rados_nobjects_list_open (C) and nobjects_begin (C++) API or + the new rados_object_list_begin (C) and object_list_begin (C++) API + before updating the client-side librados library to Luminous. + + Object enumeration (via any API) with the latest librados version + and pre-Hammer OSDs is no longer supported. Note that no in-tree + Ceph services rely on object enumeration via the deprecated APIs, so + only external librados users might be affected. + + The newest (and recommended) rados_object_list_begin (C) and + object_list_begin (C++) API is only usable on clusters with the + SORTBITWISE flag enabled (Jewel and later). (Note that this flag is + required to be set before upgrading beyond Jewel.) +* CephFS clients without the 'p' flag in their authentication capability + string will no longer be able to set quotas or any layout fields. This + flag previously only restricted modification of the pool and namespace + fields in layouts. +* CephFS directory fragmentation (large directory support) is enabled + by default on new filesystems. To enable it on existing filesystems + use "ceph fs set allow_dirfrags". +* CephFS will generate a health warning if you have fewer standby daemons + than it thinks you wanted. By default this will be 1 if you ever had + a standby, and 0 if you did not. You can customize this using + ``ceph fs set standby_count_wanted ``. Setting it + to zero will effectively disable the health check. +* The "ceph mds tell ..." command has been removed. It is superceded + by "ceph tell mds. ..." + +12.1.0 +------ + +* The ``mon_osd_max_op_age`` option has been renamed to + ``mon_osd_warn_op_age`` (default: 32 seconds), to indicate we + generate a warning at this age. There is also a new + ``mon_osd_err_op_age_ratio`` that is a expressed as a multitple of + ``mon_osd_warn_op_age`` (default: 128, for roughly 60 minutes) to + control when an error is generated. + +* The default maximum size for a single RADOS object has been reduced from + 100GB to 128MB. The 100GB limit was completely impractical in practice + while the 128MB limit is a bit high but not unreasonable. If you have an + application written directly to librados that is using objects larger than + 128MB you may need to adjust ``osd_max_object_size``. + +* The semantics of the 'rados ls' and librados object listing + operations have always been a bit confusing in that "whiteout" + objects (which logically don't exist and will return ENOENT if you + try to access them) are included in the results. Previously + whiteouts only occurred in cache tier pools. In luminous, logically + deleted but snapshotted objects now result in a whiteout object, and + as a result they will appear in 'rados ls' results, even though + trying to read such an object will result in ENOENT. The 'rados + listsnaps' operation can be used in such a case to enumerate which + snapshots are present. + + This may seem a bit strange, but is less strange than having a + deleted-but-snapshotted object not appear at all and be completely + hidden from librados's ability to enumerate objects. Future + versions of Ceph will likely include an alternative object + enumeration interface that makes it more natural and efficient to + enumerate all objects along with their snapshot and clone metadata. + +* The deprecated 'crush_ruleset' property has finally been removed; please use + 'crush_rule' instead for the 'osd pool get ...' and 'osd pool set ..' commands. + +* The 'osd pool default crush replicated ruleset' option has been + removed and replaced by the 'osd pool default crush rule' option. + By default it is -1, which means the mon will pick the first type + replicated rule in the CRUSH map for replicated pools. Erasure + coded pools have rules that are automatically created for them if they are + not specified at pool creation time. diff --git a/ceph/alpine/APKBUILD b/ceph/alpine/APKBUILD index 8b49fc587..3fa716646 100644 --- a/ceph/alpine/APKBUILD +++ b/ceph/alpine/APKBUILD @@ -1,7 +1,7 @@ # Contributor: John Coyle # Maintainer: John Coyle pkgname=ceph -pkgver=12.0.3 +pkgver=12.1.0 pkgrel=0 pkgdesc="Ceph is a distributed object store and file system" pkgusers="ceph" @@ -38,7 +38,6 @@ makedepends=" keyutils-dev leveldb-dev libaio-dev - libatomic_ops-dev libedit-dev libressl-dev libtirpc-dev @@ -64,7 +63,7 @@ makedepends=" xmlstarlet yasm " -source="ceph-12.0.3.tar.bz2" +source="ceph-12.1.0.tar.bz2" subpackages=" $pkgname-base $pkgname-common @@ -117,7 +116,7 @@ _sysconfdir=/etc _udevrulesdir=/etc/udev/rules.d _python_sitelib=/usr/lib/python2.7/site-packages -builddir=$srcdir/ceph-12.0.3 +builddir=$srcdir/ceph-12.1.0 build() { export CEPH_BUILD_VIRTUALENV=$builddir @@ -167,7 +166,6 @@ package() { || return 1 chmod 0644 $pkgdir$_docdir/ceph/sample.ceph.conf || return 1 - chmod 0644 $pkgdir$_docdir/ceph/sample.fetch_config || return 1 # udev rules install -m 0644 -D udev/50-rbd.rules $pkgdir$_udevrulesdir/50-rbd.rules || return 1 @@ -193,7 +191,6 @@ base() { xfsprogs " - _pkg $_docdir/ceph sample.ceph.conf sample.fetch_config _pkg $_bindir crushtool monmaptool osdmaptool ceph-run ceph-detect-init _pkg $_sbindir ceph-create-keys mount.ceph _pkg $_libexecdir/ceph ceph_common.sh @@ -292,7 +289,7 @@ radosgw() { pkgdesc="Rados REST gateway which implements Amazon's S3 and OpenStack's Swift APIs." depends="ceph-common" - _pkg $_bindir radosgw radosgw-admin radosgw-token radosgw-object-expirer + _pkg $_bindir radosgw radosgw-admin radosgw-token radosgw-es radosgw-object-expirer mkdir -p $subpkgdir$_localstatedir/lib/ceph/radosgw } @@ -301,7 +298,7 @@ osd() { depends="ceph-base parted gptfdisk" _pkg $_bindir ceph-clsinfo ceph-bluefs-tool ceph-objectstore-tool ceph-osd - _pkg $_sbindir ceph-disk ceph-disk-udev + _pkg $_sbindir ceph-disk _pkg $_libexecdir/ceph ceph-osd-prestart.sh _pkg $_udevrulesdir 60-ceph-by-parttypeuuid.rules 95-ceph-osd.rules install -m 750 -o $_ceph_uid -g $_ceph_gid -d \ diff --git a/ceph/alpine/APKBUILD.in b/ceph/alpine/APKBUILD.in index 1a2ff4e0d..e82dd20a5 100644 --- a/ceph/alpine/APKBUILD.in +++ b/ceph/alpine/APKBUILD.in @@ -38,7 +38,6 @@ makedepends=" keyutils-dev leveldb-dev libaio-dev - libatomic_ops-dev libedit-dev libressl-dev libtirpc-dev @@ -167,7 +166,6 @@ package() { || return 1 chmod 0644 $pkgdir$_docdir/ceph/sample.ceph.conf || return 1 - chmod 0644 $pkgdir$_docdir/ceph/sample.fetch_config || return 1 # udev rules install -m 0644 -D udev/50-rbd.rules $pkgdir$_udevrulesdir/50-rbd.rules || return 1 @@ -193,7 +191,6 @@ base() { xfsprogs " - _pkg $_docdir/ceph sample.ceph.conf sample.fetch_config _pkg $_bindir crushtool monmaptool osdmaptool ceph-run ceph-detect-init _pkg $_sbindir ceph-create-keys mount.ceph _pkg $_libexecdir/ceph ceph_common.sh @@ -292,7 +289,7 @@ radosgw() { pkgdesc="Rados REST gateway which implements Amazon's S3 and OpenStack's Swift APIs." depends="ceph-common" - _pkg $_bindir radosgw radosgw-admin radosgw-token radosgw-object-expirer + _pkg $_bindir radosgw radosgw-admin radosgw-token radosgw-es radosgw-object-expirer mkdir -p $subpkgdir$_localstatedir/lib/ceph/radosgw } @@ -301,7 +298,7 @@ osd() { depends="ceph-base parted gptfdisk" _pkg $_bindir ceph-clsinfo ceph-bluefs-tool ceph-objectstore-tool ceph-osd - _pkg $_sbindir ceph-disk ceph-disk-udev + _pkg $_sbindir ceph-disk _pkg $_libexecdir/ceph ceph-osd-prestart.sh _pkg $_udevrulesdir 60-ceph-by-parttypeuuid.rules 95-ceph-osd.rules install -m 750 -o $_ceph_uid -g $_ceph_gid -d \ diff --git a/ceph/ceph.spec b/ceph/ceph.spec index f07f95cc2..e85a731a9 100644 --- a/ceph/ceph.spec +++ b/ceph/ceph.spec @@ -23,11 +23,10 @@ %endif %bcond_with make_check %bcond_with xio -%ifnarch s390 s390x -%bcond_without tcmalloc -%else -# no gperftools/tcmalloc on s390(x) +%ifarch s390 s390x %bcond_with tcmalloc +%else +%bcond_without tcmalloc %endif %bcond_with lowmem_builder %if 0%{?fedora} || 0%{?rhel} @@ -58,34 +57,41 @@ # disable dwz which compresses the debuginfo %global _find_debuginfo_dwz_opts %{nil} + ################################################################################# # main package definition ################################################################################# Name: ceph -Version: 12.0.3 +Version: 12.1.0 Release: 0%{?dist} +%if 0%{?fedora} || 0%{?rhel} Epoch: 1 +%endif + +# define %_epoch_prefix macro which will expand to the empty string if %epoch is undefined +%global _epoch_prefix %{?epoch:%{epoch}:} + Summary: User space components of the Ceph file system -License: LGPL-2.1 and CC-BY-SA-1.0 and GPL-2.0 and BSL-1.0 and GPL-2.0-with-autoconf-exception and BSD-3-Clause and MIT +License: LGPL-2.1 and CC-BY-SA-1.0 and GPL-2.0 and BSL-1.0 and BSD-3-Clause and MIT %if 0%{?suse_version} Group: System/Filesystems %endif URL: http://ceph.com/ -Source0: http://ceph.com/download/ceph-12.0.3.tar.bz2 +Source0: http://ceph.com/download/ceph-12.1.0.tar.bz2 %if 0%{?suse_version} %if 0%{?is_opensuse} ExclusiveArch: x86_64 aarch64 ppc64 ppc64le %else -ExclusiveArch: x86_64 aarch64 +ExclusiveArch: x86_64 aarch64 ppc64le s390x %endif %endif ################################################################################# # dependencies that apply across all distro families ################################################################################# -Requires: ceph-osd = %{epoch}:%{version}-%{release} -Requires: ceph-mds = %{epoch}:%{version}-%{release} -Requires: ceph-mgr = %{epoch}:%{version}-%{release} -Requires: ceph-mon = %{epoch}:%{version}-%{release} +Requires: ceph-osd = %{_epoch_prefix}%{version}-%{release} +Requires: ceph-mds = %{_epoch_prefix}%{version}-%{release} +Requires: ceph-mgr = %{_epoch_prefix}%{version}-%{release} +Requires: ceph-mon = %{_epoch_prefix}%{version}-%{release} Requires(post): binutils %if 0%{with cephfs_java} BuildRequires: java-devel @@ -97,6 +103,7 @@ BuildRequires: selinux-policy-devel BuildRequires: /usr/share/selinux/devel/policyhelp %endif BuildRequires: bc +BuildRequires: gperf BuildRequires: cmake BuildRequires: cryptsetup BuildRequires: fuse-devel @@ -108,7 +115,6 @@ BuildRequires: gperftools-devel >= 2.4 BuildRequires: jq BuildRequires: leveldb-devel > 1.2 BuildRequires: libaio-devel -BuildRequires: libatomic_ops-devel BuildRequires: libblkid-devel >= 2.17 BuildRequires: libcurl-devel BuildRequires: libudev-devel @@ -121,18 +127,19 @@ BuildRequires: pkgconfig BuildRequires: python BuildRequires: python-devel BuildRequires: python-nose -BuildRequires: python-prettytable +BuildRequires: python-pecan BuildRequires: python-requests BuildRequires: python-virtualenv +BuildRequires: python-werkzeug BuildRequires: snappy-devel BuildRequires: udev BuildRequires: util-linux BuildRequires: valgrind-devel +BuildRequires: which BuildRequires: xfsprogs BuildRequires: xfsprogs-devel BuildRequires: xmlstarlet BuildRequires: yasm -BuildRequires: libibverbs-devel ################################################################################# # distro-conditional dependencies @@ -151,8 +158,11 @@ BuildRequires: keyutils-devel BuildRequires: libopenssl-devel BuildRequires: lsb-release BuildRequires: openldap2-devel +BuildRequires: python-CherryPy BuildRequires: python-Cython +BuildRequires: python-PrettyTable BuildRequires: python-Sphinx +BuildRequires: rdma-core-devel %endif %if 0%{?fedora} || 0%{?rhel} Requires: systemd @@ -160,10 +170,13 @@ BuildRequires: boost-random BuildRequires: btrfs-progs BuildRequires: nss-devel BuildRequires: keyutils-libs-devel +BuildRequires: libibverbs-devel BuildRequires: openldap-devel BuildRequires: openssl-devel BuildRequires: redhat-lsb-core BuildRequires: Cython +BuildRequires: python-cherrypy +BuildRequires: python-prettytable BuildRequires: python-sphinx %endif # python34-... for RHEL, python3-... for all other supported distros @@ -187,14 +200,11 @@ BuildRequires: lttng-ust-devel BuildRequires: babeltrace-devel %endif %endif -# expat and fastcgi for RGW %if 0%{?suse_version} BuildRequires: libexpat-devel -BuildRequires: FastCGI-devel %endif %if 0%{?rhel} || 0%{?fedora} BuildRequires: expat-devel -BuildRequires: fcgi-devel %endif #hardened-cc1 %if 0%{?fedora} || 0%{?rhel} @@ -218,13 +228,13 @@ Summary: Ceph Base Package %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-common = %{epoch}:%{version}-%{release} -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: librgw2 = %{epoch}:%{version}-%{release} +Requires: ceph-common = %{_epoch_prefix}%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} %if 0%{with selinux} -Requires: ceph-selinux = %{epoch}:%{version}-%{release} +Requires: ceph-selinux = %{_epoch_prefix}%{version}-%{release} %endif Requires: python Requires: python-requests @@ -251,14 +261,19 @@ Summary: Ceph Common %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: python-rados = %{epoch}:%{version}-%{release} -Requires: python-rbd = %{epoch}:%{version}-%{release} -Requires: python-cephfs = %{epoch}:%{version}-%{release} -Requires: python-rgw = %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Requires: python-rbd = %{_epoch_prefix}%{version}-%{release} +Requires: python-cephfs = %{_epoch_prefix}%{version}-%{release} +Requires: python-rgw = %{_epoch_prefix}%{version}-%{release} +%if 0%{?fedora} || 0%{?rhel} Requires: python-prettytable +%endif +%if 0%{?suse_version} +Requires: python-PrettyTable +%endif Requires: python-requests %{?systemd_requires} %if 0%{?suse_version} @@ -276,7 +291,7 @@ Summary: Ceph Metadata Server Daemon %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} %description mds ceph-mds is the metadata server daemon for the Ceph distributed file system. One or more instances of ceph-mds collectively manage the file system @@ -287,7 +302,7 @@ Summary: Ceph Monitor Daemon %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} # For ceph-rest-api %if 0%{?fedora} || 0%{?rhel} Requires: python-flask @@ -303,12 +318,21 @@ of cluster membership, configuration, and state. %package mgr Summary: Ceph Manager Daemon -License: LGPL-2.1 and CC-BY-SA-1.0 and GPL-2.0 and BSL-1.0 and GPL-2.0-with-autoconf-exception and BSD-3-Clause and MIT %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} - +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} +%if 0%{?fedora} || 0%{?rhel} +Requires: python-cherrypy +Requires: python-werkzeug +Requires: pyOpenSSL +%endif +%if 0%{?suse_version} +Requires: python-CherryPy +Requires: python-Werkzeug +Requires: python-pyOpenSSL +%endif +Requires: python-pecan %description mgr ceph-mgr enables python modules that provide services (such as the REST module derived from Calamari) and expose CLI hooks. ceph-mgr gathers @@ -328,8 +352,8 @@ Summary: Ceph fuse-based client %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: librbd1 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} %description -n rbd-fuse FUSE based client to map Ceph rbd images to files @@ -338,8 +362,8 @@ Summary: Ceph daemon for mirroring RBD images %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-common = %{epoch}:%{version}-%{release} -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: ceph-common = %{_epoch_prefix}%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n rbd-mirror Daemon for mirroring RBD images between Ceph clusters, streaming changes asynchronously. @@ -349,8 +373,8 @@ Summary: Ceph RBD client base on NBD %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: librbd1 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} %description -n rbd-nbd NBD based client to map Ceph rbd images to local device @@ -359,12 +383,12 @@ Summary: Rados REST gateway %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-common = %{epoch}:%{version}-%{release} +Requires: ceph-common = %{_epoch_prefix}%{version}-%{release} %if 0%{with selinux} -Requires: ceph-selinux = %{epoch}:%{version}-%{release} +Requires: ceph-selinux = %{_epoch_prefix}%{version}-%{release} %endif -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: librgw2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} %if 0%{?rhel} || 0%{?fedora} Requires: mailcap %endif @@ -380,8 +404,7 @@ Summary: OCF-compliant resource agents for Ceph daemons %if 0%{?suse_version} Group: System/Filesystems %endif -License: LGPL-2.0 -Requires: ceph-base = %{epoch}:%{version} +Requires: ceph-base = %{_epoch_prefix}%{version} Requires: resource-agents %description resource-agents Resource agents for monitoring and managing Ceph daemons @@ -394,7 +417,7 @@ Summary: Ceph Object Storage Daemon %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} # for sgdisk, used by ceph-disk %if 0%{?fedora} || 0%{?rhel} Requires: gdisk @@ -413,9 +436,8 @@ Summary: RADOS distributed object store client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 %if 0%{?rhel} || 0%{?fedora} -Obsoletes: ceph-libs < %{epoch}:%{version}-%{release} +Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release} %endif %description -n librados2 RADOS is a reliable, autonomic distributed object storage cluster @@ -428,11 +450,10 @@ Summary: RADOS headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: librados2-devel = %{epoch}:%{version}-%{release} -Obsoletes: librados2-devel < %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: librados2-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: librados2-devel < %{_epoch_prefix}%{version}-%{release} %description -n librados-devel This package contains libraries and headers needed to develop programs that use RADOS object store. @@ -442,8 +463,7 @@ Summary: RADOS gateway client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n librgw2 This package provides a library implementation of the RADOS gateway (distributed object store with S3 and Swift personalities). @@ -453,11 +473,10 @@ Summary: RADOS gateway client library %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: librados-devel = %{epoch}:%{version}-%{release} -Requires: librgw2 = %{epoch}:%{version}-%{release} -Provides: librgw2-devel = %{epoch}:%{version}-%{release} -Obsoletes: librgw2-devel < %{epoch}:%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} +Provides: librgw2-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: librgw2-devel < %{_epoch_prefix}%{version}-%{release} %description -n librgw-devel This package contains libraries and headers needed to develop programs that use RADOS gateway client library. @@ -467,10 +486,9 @@ Summary: Python 2 libraries for the RADOS gateway %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librgw2 = %{epoch}:%{version}-%{release} -Requires: python-rados = %{epoch}:%{version}-%{release} -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-rgw This package contains Python 2 libraries for interacting with Cephs RADOS gateway. @@ -480,9 +498,8 @@ Summary: Python 3 libraries for the RADOS gateway %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librgw2 = %{epoch}:%{version}-%{release} -Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} +Requires: python%{python3_pkgversion}-rados = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-rgw This package contains Python 3 libraries for interacting with Cephs RADOS gateway. @@ -492,9 +509,8 @@ Summary: Python 2 libraries for the RADOS object store %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-rados This package contains Python 2 libraries for interacting with Cephs RADOS object store. @@ -504,9 +520,8 @@ Summary: Python 3 libraries for the RADOS object store %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 Requires: python%{python3_pkgversion} -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-rados This package contains Python 3 libraries for interacting with Cephs RADOS object store. @@ -516,8 +531,7 @@ Summary: RADOS striping interface %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n libradosstriper1 Striping interface built on top of the rados library, allowing to stripe bigger objects onto several standard rados objects using @@ -528,12 +542,11 @@ Summary: RADOS striping interface headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: libradosstriper1 = %{epoch}:%{version}-%{release} -Requires: librados-devel = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: libradosstriper1-devel = %{epoch}:%{version}-%{release} -Obsoletes: libradosstriper1-devel < %{epoch}:%{version}-%{release} +Requires: libradosstriper1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: libradosstriper1-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: libradosstriper1-devel < %{_epoch_prefix}%{version}-%{release} %description -n libradosstriper-devel This package contains libraries and headers needed to develop programs that use RADOS striping interface. @@ -543,10 +556,12 @@ Summary: RADOS block device client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +%if 0%{?suse_version} +Requires(post): coreutils +%endif %if 0%{?rhel} || 0%{?fedora} -Obsoletes: ceph-libs < %{epoch}:%{version}-%{release} +Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release} %endif %description -n librbd1 RBD is a block device striped across multiple distributed objects in @@ -559,12 +574,11 @@ Summary: RADOS block device headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: librados-devel = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: librbd1-devel = %{epoch}:%{version}-%{release} -Obsoletes: librbd1-devel < %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: librbd1-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: librbd1-devel < %{_epoch_prefix}%{version}-%{release} %description -n librbd-devel This package contains libraries and headers needed to develop programs that use RADOS block device. @@ -574,10 +588,9 @@ Summary: Python 2 libraries for the RADOS block device %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: python-rados = %{epoch}:%{version}-%{release} -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-rbd This package contains Python 2 libraries for interacting with Cephs RADOS block device. @@ -587,9 +600,8 @@ Summary: Python 3 libraries for the RADOS block device %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: python%{python3_pkgversion}-rados = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-rbd This package contains Python 3 libraries for interacting with Cephs RADOS block device. @@ -599,9 +611,8 @@ Summary: Ceph distributed file system client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 %if 0%{?rhel} || 0%{?fedora} -Obsoletes: ceph-libs < %{epoch}:%{version}-%{release} +Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release} Obsoletes: ceph-libcephfs %endif %description -n libcephfs2 @@ -615,12 +626,11 @@ Summary: Ceph distributed file system headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: librados-devel = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: libcephfs2-devel = %{epoch}:%{version}-%{release} -Obsoletes: libcephfs2-devel < %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: libcephfs2-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: libcephfs2-devel < %{_epoch_prefix}%{version}-%{release} %description -n libcephfs-devel This package contains libraries and headers needed to develop programs that use Cephs distributed file system. @@ -630,12 +640,11 @@ Summary: Python 2 libraries for Ceph distributed file system %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: libcephfs2 = %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} %if 0%{?suse_version} -Recommends: python-rados = %{epoch}:%{version}-%{release} +Recommends: python-rados = %{_epoch_prefix}%{version}-%{release} %endif -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-cephfs This package contains Python 2 libraries for interacting with Cephs distributed file system. @@ -645,9 +654,8 @@ Summary: Python 3 libraries for Ceph distributed file system %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: python%{python3_pkgversion}-rados = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-cephfs This package contains Python 3 libraries for interacting with Cephs distributed file system. @@ -657,7 +665,6 @@ Summary: Python 3 utility libraries for Ceph CLI %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 %description -n python%{python3_pkgversion}-ceph-argparse This package contains types and routines for Python 3 used by the Ceph CLI as well as the RESTful interface. These have to do with querying the daemons for @@ -670,9 +677,9 @@ Summary: Ceph benchmarks and test tools %if 0%{?suse_version} Group: System/Benchmark %endif -License: LGPL-2.0 Requires: ceph-common Requires: xmlstarlet +Requires: jq %description -n ceph-test This package contains Ceph benchmarks and test tools. %endif @@ -684,9 +691,8 @@ Summary: Java Native Interface library for CephFS Java bindings %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 Requires: java -Requires: libcephfs2 = %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} %description -n libcephfs_jni1 This package contains the Java Native Interface library for CephFS Java bindings. @@ -696,12 +702,11 @@ Summary: Development files for CephFS Java Native Interface library %if 0%{?suse_version} Group: Development/Libraries/Java %endif -License: LGPL-2.0 Requires: java -Requires: libcephfs_jni1 = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: libcephfs_jni1-devel = %{epoch}:%{version}-%{release} -Obsoletes: libcephfs_jni1-devel < %{epoch}:%{version}-%{release} +Requires: libcephfs_jni1 = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: libcephfs_jni1-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: libcephfs_jni1-devel < %{_epoch_prefix}%{version}-%{release} %description -n libcephfs_jni-devel This package contains the development files for CephFS Java Native Interface library. @@ -711,9 +716,8 @@ Summary: Java libraries for the Ceph File System %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 Requires: java -Requires: libcephfs_jni1 = %{epoch}:%{version}-%{release} +Requires: libcephfs_jni1 = %{_epoch_prefix}%{version}-%{release} Requires: junit BuildRequires: junit %description -n cephfs-java @@ -724,8 +728,7 @@ This package contains the Java libraries for the Ceph File System. %package -n rados-objclass-devel Summary: RADOS object class development kit Group: Development/Libraries -License: LGPL-2.0 -Requires: librados2-devel = %{epoch}:%{version}-%{release} +Requires: librados2-devel = %{_epoch_prefix}%{version}-%{release} %description -n rados-objclass-devel This package contains libraries and headers needed to develop RADOS object class plugins. @@ -737,8 +740,9 @@ Summary: SELinux support for Ceph MON, OSD and MDS %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} Requires: policycoreutils, libselinux-utils +Requires(post): ceph-base = %{_epoch_prefix}%{version}-%{release} Requires(post): selinux-policy-base >= %{_selinux_policy_version}, policycoreutils, gawk Requires(postun): policycoreutils %description selinux @@ -753,12 +757,11 @@ Summary: Compatibility package for Cephs python libraries %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 Obsoletes: python-ceph -Requires: python-rados = %{epoch}:%{version}-%{release} -Requires: python-rbd = %{epoch}:%{version}-%{release} -Requires: python-cephfs = %{epoch}:%{version}-%{release} -Requires: python-rgw = %{epoch}:%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Requires: python-rbd = %{_epoch_prefix}%{version}-%{release} +Requires: python-cephfs = %{_epoch_prefix}%{version}-%{release} +Requires: python-rgw = %{_epoch_prefix}%{version}-%{release} Provides: python-ceph %description -n python-ceph-compat This is a compatibility package to accommodate python-ceph split into @@ -770,7 +773,7 @@ python-rbd, python-rgw or python-cephfs instead. # common ################################################################################# %prep -%autosetup -p1 -n ceph-12.0.3 +%autosetup -p1 -n ceph-12.1.0 %build %if 0%{with cephfs_java} @@ -841,6 +844,11 @@ cmake .. \ $CEPH_EXTRA_CMAKE_ARGS \ %if 0%{with ocf} -DWITH_OCF=ON \ +%endif +%ifarch aarch64 armv7hl mips mipsel ppc ppc64 ppc64le %{ix86} x86_64 + -DWITH_RADOSGW_BEAST_FRONTEND=ON \ +%else + -DWITH_RADOSGW_BEAST_FRONTEND=OFF \ %endif -DBOOST_J=%{_smp_ncpus} @@ -876,7 +884,7 @@ install -m 0644 -D systemd/50-ceph.preset %{buildroot}%{_libexecdir}/systemd/sys mkdir -p %{buildroot}%{_sbindir} install -m 0644 -D src/logrotate.conf %{buildroot}%{_sysconfdir}/logrotate.d/ceph chmod 0644 %{buildroot}%{_docdir}/ceph/sample.ceph.conf -chmod 0644 %{buildroot}%{_docdir}/ceph/sample.fetch_config +install -m 0644 -D COPYING %{buildroot}%{_docdir}/ceph/COPYING # firewall templates and /sbin/mount.ceph symlink %if 0%{?suse_version} @@ -920,11 +928,6 @@ rm -rf %{buildroot} %files %files base -%defattr(-,root,root,-) -%docdir %{_docdir} -%dir %{_docdir}/ceph -%{_docdir}/ceph/sample.ceph.conf -%{_docdir}/ceph/sample.fetch_config %{_bindir}/crushtool %{_bindir}/monmaptool %{_bindir}/osdmaptool @@ -932,6 +935,7 @@ rm -rf %{buildroot} %{_bindir}/ceph-detect-init %{_libexecdir}/systemd/system-preset/50-ceph.preset %{_sbindir}/ceph-create-keys +%{_sbindir}/ceph-disk %{_sbindir}/rcceph %dir %{_libexecdir}/ceph %{_libexecdir}/ceph/ceph_common.sh @@ -950,7 +954,6 @@ rm -rf %{buildroot} %{_libdir}/libos_tp.so* %{_libdir}/libosd_tp.so* %endif -%config %{_sysconfdir}/bash_completion.d/ceph %config(noreplace) %{_sysconfdir}/logrotate.d/ceph %if 0%{?fedora} || 0%{?rhel} %config(noreplace) %{_sysconfdir}/sysconfig/ceph @@ -960,12 +963,14 @@ rm -rf %{buildroot} %config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon %config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds %endif +%{_unitdir}/ceph-disk@.service %{_unitdir}/ceph.target %{python_sitelib}/ceph_detect_init* %{python_sitelib}/ceph_disk* %{_mandir}/man8/ceph-deploy.8* %{_mandir}/man8/ceph-detect-init.8* %{_mandir}/man8/ceph-create-keys.8* +%{_mandir}/man8/ceph-disk.8* %{_mandir}/man8/ceph-run.8* %{_mandir}/man8/crushtool.8* %{_mandir}/man8/osdmaptool.8* @@ -982,11 +987,11 @@ rm -rf %{buildroot} %if 0%{?suse_version} %fillup_only if [ $1 -eq 1 ] ; then - /usr/bin/systemctl preset ceph.target >/dev/null 2>&1 || : + /usr/bin/systemctl preset ceph-disk@\*.service ceph.target >/dev/null 2>&1 || : fi %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_post ceph.target +%systemd_post ceph-disk@\*.service ceph.target %endif if [ $1 -eq 1 ] ; then /usr/bin/systemctl start ceph.target >/dev/null 2>&1 || : @@ -994,24 +999,38 @@ fi %preun base %if 0%{?suse_version} -%service_del_preun ceph.target +%service_del_preun ceph-disk@\*.service ceph.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_preun ceph.target +%systemd_preun ceph-disk@\*.service ceph.target %endif %postun base /sbin/ldconfig %if 0%{?suse_version} DISABLE_RESTART_ON_UPDATE="yes" -%service_del_postun ceph.target +%service_del_postun ceph-disk@\*.service ceph.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_postun ceph.target +%systemd_postun ceph-disk@\*.service ceph.target %endif +if [ $FIRST_ARG -ge 1 ] ; then + # Restart on upgrade, but only if "CEPH_AUTO_RESTART_ON_UPGRADE" is set to + # "yes". In any case: if units are not running, do not touch them. + SYSCONF_CEPH=%{_sysconfdir}/sysconfig/ceph + if [ -f $SYSCONF_CEPH -a -r $SYSCONF_CEPH ] ; then + source $SYSCONF_CEPH + fi + if [ "X$CEPH_AUTO_RESTART_ON_UPGRADE" = "Xyes" ] ; then + /usr/bin/systemctl try-restart ceph-disk@\*.service > /dev/null 2>&1 || : + fi +fi %files common -%defattr(-,root,root,-) +%docdir %{_docdir} +%docdir %{_docdir}/ceph +%doc %{_docdir}/ceph/sample.ceph.conf +%doc %{_docdir}/ceph/COPYING %{_bindir}/ceph %{_bindir}/ceph-authtool %{_bindir}/ceph-conf @@ -1058,6 +1077,7 @@ DISABLE_RESTART_ON_UPDATE="yes" %{_datadir}/ceph/id_rsa_drop.ceph.com %{_datadir}/ceph/id_rsa_drop.ceph.com.pub %dir %{_sysconfdir}/ceph/ +%config %{_sysconfdir}/bash_completion.d/ceph %config %{_sysconfdir}/bash_completion.d/rados %config %{_sysconfdir}/bash_completion.d/rbd %config %{_sysconfdir}/bash_completion.d/radosgw-admin @@ -1257,7 +1277,6 @@ if [ $FIRST_ARG -ge 1 ] ; then fi %files fuse -%defattr(-,root,root,-) %{_bindir}/ceph-fuse %{_mandir}/man8/ceph-fuse.8* %{_sbindir}/mount.fuse.ceph @@ -1265,12 +1284,10 @@ fi %{_unitdir}/ceph-fuse.target %files -n rbd-fuse -%defattr(-,root,root,-) %{_bindir}/rbd-fuse %{_mandir}/man8/rbd-fuse.8* %files -n rbd-mirror -%defattr(-,root,root,-) %{_bindir}/rbd-mirror %{_mandir}/man8/rbd-mirror.8* %{_unitdir}/ceph-rbd-mirror@.service @@ -1319,14 +1336,13 @@ if [ $FIRST_ARG -ge 1 ] ; then fi %files -n rbd-nbd -%defattr(-,root,root,-) %{_bindir}/rbd-nbd %{_mandir}/man8/rbd-nbd.8* %files radosgw -%defattr(-,root,root,-) %{_bindir}/radosgw %{_bindir}/radosgw-token +%{_bindir}/radosgw-es %{_bindir}/radosgw-object-expirer %{_mandir}/man8/radosgw.8* %dir %{_localstatedir}/lib/ceph/radosgw @@ -1380,31 +1396,27 @@ fi %{_bindir}/ceph-bluestore-tool %{_bindir}/ceph-objectstore-tool %{_bindir}/ceph-osd -%{_sbindir}/ceph-disk -%{_sbindir}/ceph-disk-udev %{_libexecdir}/ceph/ceph-osd-prestart.sh %dir %{_udevrulesdir} %{_udevrulesdir}/60-ceph-by-parttypeuuid.rules %{_udevrulesdir}/95-ceph-osd.rules %{_mandir}/man8/ceph-clsinfo.8* -%{_mandir}/man8/ceph-disk.8* %{_mandir}/man8/ceph-osd.8* %if 0%{?rhel} && ! 0%{?centos} -%{_sysconfdir}/cron.hourly/subman +%attr(0755,-,-) %{_sysconfdir}/cron.hourly/subman %endif %{_unitdir}/ceph-osd@.service %{_unitdir}/ceph-osd.target -%{_unitdir}/ceph-disk@.service %attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/osd %post osd %if 0%{?suse_version} if [ $1 -eq 1 ] ; then - /usr/bin/systemctl preset ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target >/dev/null 2>&1 || : + /usr/bin/systemctl preset ceph-osd@\*.service ceph-osd.target >/dev/null 2>&1 || : fi %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_post ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%systemd_post ceph-osd@\*.service ceph-osd.target %endif if [ $1 -eq 1 ] ; then /usr/bin/systemctl start ceph-osd.target >/dev/null 2>&1 || : @@ -1412,20 +1424,20 @@ fi %preun osd %if 0%{?suse_version} -%service_del_preun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%service_del_preun ceph-osd@\*.service ceph-osd.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_preun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%systemd_preun ceph-osd@\*.service ceph-osd.target %endif %postun osd test -n "$FIRST_ARG" || FIRST_ARG=$1 %if 0%{?suse_version} DISABLE_RESTART_ON_UPDATE="yes" -%service_del_postun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%service_del_postun ceph-osd@\*.service ceph-osd.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_postun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%systemd_postun ceph-osd@\*.service ceph-osd.target %endif if [ $FIRST_ARG -ge 1 ] ; then # Restart on upgrade, but only if "CEPH_AUTO_RESTART_ON_UPGRADE" is set to @@ -1435,14 +1447,13 @@ if [ $FIRST_ARG -ge 1 ] ; then source $SYSCONF_CEPH fi if [ "X$CEPH_AUTO_RESTART_ON_UPGRADE" = "Xyes" ] ; then - /usr/bin/systemctl try-restart ceph-disk@\*.service ceph-osd@\*.service > /dev/null 2>&1 || : + /usr/bin/systemctl try-restart ceph-osd@\*.service > /dev/null 2>&1 || : fi fi %if %{with ocf} %files resource-agents -%defattr(0755,root,root,-) %dir %{_prefix}/lib/ocf %dir %{_prefix}/lib/ocf/resource.d %dir %{_prefix}/lib/ocf/resource.d/ceph @@ -1451,7 +1462,6 @@ fi %endif %files -n librados2 -%defattr(-,root,root,-) %{_libdir}/librados.so.* %dir %{_libdir}/ceph %{_libdir}/ceph/libceph-common.so* @@ -1464,7 +1474,6 @@ fi %postun -n librados2 -p /sbin/ldconfig %files -n librados-devel -%defattr(-,root,root,-) %dir %{_includedir}/rados %{_includedir}/rados/librados.h %{_includedir}/rados/librados.hpp @@ -1484,17 +1493,14 @@ fi %{_mandir}/man8/librados-config.8* %files -n python-rados -%defattr(-,root,root,-) %{python_sitearch}/rados.so %{python_sitearch}/rados-*.egg-info %files -n python%{python3_pkgversion}-rados -%defattr(-,root,root,-) %{python3_sitearch}/rados.cpython*.so %{python3_sitearch}/rados-*.egg-info %files -n libradosstriper1 -%defattr(-,root,root,-) %{_libdir}/libradosstriper.so.* %post -n libradosstriper1 -p /sbin/ldconfig @@ -1502,14 +1508,12 @@ fi %postun -n libradosstriper1 -p /sbin/ldconfig %files -n libradosstriper-devel -%defattr(-,root,root,-) %dir %{_includedir}/radosstriper %{_includedir}/radosstriper/libradosstriper.h %{_includedir}/radosstriper/libradosstriper.hpp %{_libdir}/libradosstriper.so %files -n librbd1 -%defattr(-,root,root,-) %{_libdir}/librbd.so.* %if %{with lttng} %{_libdir}/librbd_tp.so.* @@ -1523,7 +1527,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n librbd1 -p /sbin/ldconfig %files -n librbd-devel -%defattr(-,root,root,-) %dir %{_includedir}/rbd %{_includedir}/rbd/librbd.h %{_includedir}/rbd/librbd.hpp @@ -1534,7 +1537,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %endif %files -n librgw2 -%defattr(-,root,root,-) %{_libdir}/librgw.so.* %post -n librgw2 -p /sbin/ldconfig @@ -1542,34 +1544,28 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n librgw2 -p /sbin/ldconfig %files -n librgw-devel -%defattr(-,root,root,-) %dir %{_includedir}/rados %{_includedir}/rados/librgw.h %{_includedir}/rados/rgw_file.h %{_libdir}/librgw.so %files -n python-rgw -%defattr(-,root,root,-) %{python_sitearch}/rgw.so %{python_sitearch}/rgw-*.egg-info %files -n python%{python3_pkgversion}-rgw -%defattr(-,root,root,-) %{python3_sitearch}/rgw.cpython*.so %{python3_sitearch}/rgw-*.egg-info %files -n python-rbd -%defattr(-,root,root,-) %{python_sitearch}/rbd.so %{python_sitearch}/rbd-*.egg-info %files -n python%{python3_pkgversion}-rbd -%defattr(-,root,root,-) %{python3_sitearch}/rbd.cpython*.so %{python3_sitearch}/rbd-*.egg-info %files -n libcephfs2 -%defattr(-,root,root,-) %{_libdir}/libcephfs.so.* %post -n libcephfs2 -p /sbin/ldconfig @@ -1577,27 +1573,23 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n libcephfs2 -p /sbin/ldconfig %files -n libcephfs-devel -%defattr(-,root,root,-) %dir %{_includedir}/cephfs %{_includedir}/cephfs/libcephfs.h %{_includedir}/cephfs/ceph_statx.h %{_libdir}/libcephfs.so %files -n python-cephfs -%defattr(-,root,root,-) %{python_sitearch}/cephfs.so %{python_sitearch}/cephfs-*.egg-info %{python_sitelib}/ceph_volume_client.py* %files -n python%{python3_pkgversion}-cephfs -%defattr(-,root,root,-) %{python3_sitearch}/cephfs.cpython*.so %{python3_sitearch}/cephfs-*.egg-info %{python3_sitelib}/ceph_volume_client.py %{python3_sitelib}/__pycache__/ceph_volume_client.cpython*.py* %files -n python%{python3_pkgversion}-ceph-argparse -%defattr(-,root,root,-) %{python3_sitelib}/ceph_argparse.py %{python3_sitelib}/__pycache__/ceph_argparse.cpython*.py* %{python3_sitelib}/ceph_daemon.py @@ -1605,7 +1597,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %if 0%{with ceph_test_package} %files -n ceph-test -%defattr(-,root,root,-) %{_bindir}/ceph-client-debug %{_bindir}/ceph_bench_log %{_bindir}/ceph_kvstorebench @@ -1636,8 +1627,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %{_bindir}/ceph-osdomap-tool %{_bindir}/ceph-kvstore-tool %{_bindir}/ceph-debugpack -%{_bindir}/dmclock-tests -%{_bindir}/dmclock-data-struct-tests %{_mandir}/man8/ceph-debugpack.8* %dir %{_libdir}/ceph %{_libdir}/ceph/ceph-monstore-update-crush.sh @@ -1645,7 +1634,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %if 0%{with cephfs_java} %files -n libcephfs_jni1 -%defattr(-,root,root,-) %{_libdir}/libcephfs_jni.so.* %post -n libcephfs_jni1 -p /sbin/ldconfig @@ -1653,23 +1641,19 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n libcephfs_jni1 -p /sbin/ldconfig %files -n libcephfs_jni-devel -%defattr(-,root,root,-) %{_libdir}/libcephfs_jni.so %files -n cephfs-java -%defattr(-,root,root,-) %{_javadir}/libcephfs.jar %{_javadir}/libcephfs-test.jar %endif %files -n rados-objclass-devel -%defattr(-,root,root,-) %dir %{_includedir}/rados %{_includedir}/rados/objclass.h %if 0%{with selinux} %files selinux -%defattr(-,root,root,-) %attr(0600,root,root) %{_datadir}/selinux/packages/ceph.pp %{_datadir}/selinux/devel/include/contrib/ceph.if %{_mandir}/man8/ceph_selinux.8* @@ -1703,8 +1687,14 @@ if test $STATUS -eq 0; then /usr/bin/systemctl stop ceph.target > /dev/null 2>&1 fi -# Now, relabel the files -/usr/sbin/fixfiles -C ${FILE_CONTEXT}.pre restore 2> /dev/null +# Relabel the files +# Use ceph-disk fix for first package install and fixfiles otherwise +if [ "$1" = "1" ]; then + /usr/sbin/ceph-disk fix --selinux +else + /usr/sbin/fixfiles -C ${FILE_CONTEXT}.pre restore 2> /dev/null +fi + rm -f ${FILE_CONTEXT}.pre # The fixfiles command won't fix label for /var/run/ceph /usr/sbin/restorecon -R /var/run/ceph > /dev/null 2>&1 diff --git a/ceph/ceph.spec.in b/ceph/ceph.spec.in index 339adc627..60d59c52c 100644 --- a/ceph/ceph.spec.in +++ b/ceph/ceph.spec.in @@ -23,11 +23,10 @@ %endif %bcond_with make_check %bcond_with xio -%ifnarch s390 s390x -%bcond_without tcmalloc -%else -# no gperftools/tcmalloc on s390(x) +%ifarch s390 s390x %bcond_with tcmalloc +%else +%bcond_without tcmalloc %endif %bcond_with lowmem_builder %if 0%{?fedora} || 0%{?rhel} @@ -58,15 +57,22 @@ # disable dwz which compresses the debuginfo %global _find_debuginfo_dwz_opts %{nil} + ################################################################################# # main package definition ################################################################################# Name: ceph Version: @VERSION@ Release: @RPM_RELEASE@%{?dist} +%if 0%{?fedora} || 0%{?rhel} Epoch: 1 +%endif + +# define %_epoch_prefix macro which will expand to the empty string if %epoch is undefined +%global _epoch_prefix %{?epoch:%{epoch}:} + Summary: User space components of the Ceph file system -License: LGPL-2.1 and CC-BY-SA-1.0 and GPL-2.0 and BSL-1.0 and GPL-2.0-with-autoconf-exception and BSD-3-Clause and MIT +License: LGPL-2.1 and CC-BY-SA-1.0 and GPL-2.0 and BSL-1.0 and BSD-3-Clause and MIT %if 0%{?suse_version} Group: System/Filesystems %endif @@ -76,16 +82,16 @@ Source0: http://ceph.com/download/@TARBALL_BASENAME@.tar.bz2 %if 0%{?is_opensuse} ExclusiveArch: x86_64 aarch64 ppc64 ppc64le %else -ExclusiveArch: x86_64 aarch64 +ExclusiveArch: x86_64 aarch64 ppc64le s390x %endif %endif ################################################################################# # dependencies that apply across all distro families ################################################################################# -Requires: ceph-osd = %{epoch}:%{version}-%{release} -Requires: ceph-mds = %{epoch}:%{version}-%{release} -Requires: ceph-mgr = %{epoch}:%{version}-%{release} -Requires: ceph-mon = %{epoch}:%{version}-%{release} +Requires: ceph-osd = %{_epoch_prefix}%{version}-%{release} +Requires: ceph-mds = %{_epoch_prefix}%{version}-%{release} +Requires: ceph-mgr = %{_epoch_prefix}%{version}-%{release} +Requires: ceph-mon = %{_epoch_prefix}%{version}-%{release} Requires(post): binutils %if 0%{with cephfs_java} BuildRequires: java-devel @@ -97,6 +103,7 @@ BuildRequires: selinux-policy-devel BuildRequires: /usr/share/selinux/devel/policyhelp %endif BuildRequires: bc +BuildRequires: gperf BuildRequires: cmake BuildRequires: cryptsetup BuildRequires: fuse-devel @@ -108,7 +115,6 @@ BuildRequires: gperftools-devel >= 2.4 BuildRequires: jq BuildRequires: leveldb-devel > 1.2 BuildRequires: libaio-devel -BuildRequires: libatomic_ops-devel BuildRequires: libblkid-devel >= 2.17 BuildRequires: libcurl-devel BuildRequires: libudev-devel @@ -121,18 +127,19 @@ BuildRequires: pkgconfig BuildRequires: python BuildRequires: python-devel BuildRequires: python-nose -BuildRequires: python-prettytable +BuildRequires: python-pecan BuildRequires: python-requests BuildRequires: python-virtualenv +BuildRequires: python-werkzeug BuildRequires: snappy-devel BuildRequires: udev BuildRequires: util-linux BuildRequires: valgrind-devel +BuildRequires: which BuildRequires: xfsprogs BuildRequires: xfsprogs-devel BuildRequires: xmlstarlet BuildRequires: yasm -BuildRequires: libibverbs-devel ################################################################################# # distro-conditional dependencies @@ -151,8 +158,11 @@ BuildRequires: keyutils-devel BuildRequires: libopenssl-devel BuildRequires: lsb-release BuildRequires: openldap2-devel +BuildRequires: python-CherryPy BuildRequires: python-Cython +BuildRequires: python-PrettyTable BuildRequires: python-Sphinx +BuildRequires: rdma-core-devel %endif %if 0%{?fedora} || 0%{?rhel} Requires: systemd @@ -160,10 +170,13 @@ BuildRequires: boost-random BuildRequires: btrfs-progs BuildRequires: nss-devel BuildRequires: keyutils-libs-devel +BuildRequires: libibverbs-devel BuildRequires: openldap-devel BuildRequires: openssl-devel BuildRequires: redhat-lsb-core BuildRequires: Cython +BuildRequires: python-cherrypy +BuildRequires: python-prettytable BuildRequires: python-sphinx %endif # python34-... for RHEL, python3-... for all other supported distros @@ -187,14 +200,11 @@ BuildRequires: lttng-ust-devel BuildRequires: babeltrace-devel %endif %endif -# expat and fastcgi for RGW %if 0%{?suse_version} BuildRequires: libexpat-devel -BuildRequires: FastCGI-devel %endif %if 0%{?rhel} || 0%{?fedora} BuildRequires: expat-devel -BuildRequires: fcgi-devel %endif #hardened-cc1 %if 0%{?fedora} || 0%{?rhel} @@ -218,13 +228,13 @@ Summary: Ceph Base Package %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-common = %{epoch}:%{version}-%{release} -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: librgw2 = %{epoch}:%{version}-%{release} +Requires: ceph-common = %{_epoch_prefix}%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} %if 0%{with selinux} -Requires: ceph-selinux = %{epoch}:%{version}-%{release} +Requires: ceph-selinux = %{_epoch_prefix}%{version}-%{release} %endif Requires: python Requires: python-requests @@ -251,14 +261,19 @@ Summary: Ceph Common %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: python-rados = %{epoch}:%{version}-%{release} -Requires: python-rbd = %{epoch}:%{version}-%{release} -Requires: python-cephfs = %{epoch}:%{version}-%{release} -Requires: python-rgw = %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Requires: python-rbd = %{_epoch_prefix}%{version}-%{release} +Requires: python-cephfs = %{_epoch_prefix}%{version}-%{release} +Requires: python-rgw = %{_epoch_prefix}%{version}-%{release} +%if 0%{?fedora} || 0%{?rhel} Requires: python-prettytable +%endif +%if 0%{?suse_version} +Requires: python-PrettyTable +%endif Requires: python-requests %{?systemd_requires} %if 0%{?suse_version} @@ -276,7 +291,7 @@ Summary: Ceph Metadata Server Daemon %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} %description mds ceph-mds is the metadata server daemon for the Ceph distributed file system. One or more instances of ceph-mds collectively manage the file system @@ -287,7 +302,7 @@ Summary: Ceph Monitor Daemon %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} # For ceph-rest-api %if 0%{?fedora} || 0%{?rhel} Requires: python-flask @@ -303,12 +318,21 @@ of cluster membership, configuration, and state. %package mgr Summary: Ceph Manager Daemon -License: LGPL-2.1 and CC-BY-SA-1.0 and GPL-2.0 and BSL-1.0 and GPL-2.0-with-autoconf-exception and BSD-3-Clause and MIT %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} - +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} +%if 0%{?fedora} || 0%{?rhel} +Requires: python-cherrypy +Requires: python-werkzeug +Requires: pyOpenSSL +%endif +%if 0%{?suse_version} +Requires: python-CherryPy +Requires: python-Werkzeug +Requires: python-pyOpenSSL +%endif +Requires: python-pecan %description mgr ceph-mgr enables python modules that provide services (such as the REST module derived from Calamari) and expose CLI hooks. ceph-mgr gathers @@ -328,8 +352,8 @@ Summary: Ceph fuse-based client %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: librbd1 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} %description -n rbd-fuse FUSE based client to map Ceph rbd images to files @@ -338,8 +362,8 @@ Summary: Ceph daemon for mirroring RBD images %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-common = %{epoch}:%{version}-%{release} -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: ceph-common = %{_epoch_prefix}%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n rbd-mirror Daemon for mirroring RBD images between Ceph clusters, streaming changes asynchronously. @@ -349,8 +373,8 @@ Summary: Ceph RBD client base on NBD %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: librbd1 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} %description -n rbd-nbd NBD based client to map Ceph rbd images to local device @@ -359,12 +383,12 @@ Summary: Rados REST gateway %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-common = %{epoch}:%{version}-%{release} +Requires: ceph-common = %{_epoch_prefix}%{version}-%{release} %if 0%{with selinux} -Requires: ceph-selinux = %{epoch}:%{version}-%{release} +Requires: ceph-selinux = %{_epoch_prefix}%{version}-%{release} %endif -Requires: librados2 = %{epoch}:%{version}-%{release} -Requires: librgw2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} %if 0%{?rhel} || 0%{?fedora} Requires: mailcap %endif @@ -380,8 +404,7 @@ Summary: OCF-compliant resource agents for Ceph daemons %if 0%{?suse_version} Group: System/Filesystems %endif -License: LGPL-2.0 -Requires: ceph-base = %{epoch}:%{version} +Requires: ceph-base = %{_epoch_prefix}%{version} Requires: resource-agents %description resource-agents Resource agents for monitoring and managing Ceph daemons @@ -394,7 +417,7 @@ Summary: Ceph Object Storage Daemon %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} # for sgdisk, used by ceph-disk %if 0%{?fedora} || 0%{?rhel} Requires: gdisk @@ -413,9 +436,8 @@ Summary: RADOS distributed object store client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 %if 0%{?rhel} || 0%{?fedora} -Obsoletes: ceph-libs < %{epoch}:%{version}-%{release} +Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release} %endif %description -n librados2 RADOS is a reliable, autonomic distributed object storage cluster @@ -428,11 +450,10 @@ Summary: RADOS headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: librados2-devel = %{epoch}:%{version}-%{release} -Obsoletes: librados2-devel < %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: librados2-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: librados2-devel < %{_epoch_prefix}%{version}-%{release} %description -n librados-devel This package contains libraries and headers needed to develop programs that use RADOS object store. @@ -442,8 +463,7 @@ Summary: RADOS gateway client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n librgw2 This package provides a library implementation of the RADOS gateway (distributed object store with S3 and Swift personalities). @@ -453,11 +473,10 @@ Summary: RADOS gateway client library %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: librados-devel = %{epoch}:%{version}-%{release} -Requires: librgw2 = %{epoch}:%{version}-%{release} -Provides: librgw2-devel = %{epoch}:%{version}-%{release} -Obsoletes: librgw2-devel < %{epoch}:%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} +Provides: librgw2-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: librgw2-devel < %{_epoch_prefix}%{version}-%{release} %description -n librgw-devel This package contains libraries and headers needed to develop programs that use RADOS gateway client library. @@ -467,10 +486,9 @@ Summary: Python 2 libraries for the RADOS gateway %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librgw2 = %{epoch}:%{version}-%{release} -Requires: python-rados = %{epoch}:%{version}-%{release} -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-rgw This package contains Python 2 libraries for interacting with Cephs RADOS gateway. @@ -480,9 +498,8 @@ Summary: Python 3 libraries for the RADOS gateway %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librgw2 = %{epoch}:%{version}-%{release} -Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release} +Requires: librgw2 = %{_epoch_prefix}%{version}-%{release} +Requires: python%{python3_pkgversion}-rados = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-rgw This package contains Python 3 libraries for interacting with Cephs RADOS gateway. @@ -492,9 +509,8 @@ Summary: Python 2 libraries for the RADOS object store %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-rados This package contains Python 2 libraries for interacting with Cephs RADOS object store. @@ -504,9 +520,8 @@ Summary: Python 3 libraries for the RADOS object store %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 Requires: python%{python3_pkgversion} -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-rados This package contains Python 3 libraries for interacting with Cephs RADOS object store. @@ -516,8 +531,7 @@ Summary: RADOS striping interface %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} %description -n libradosstriper1 Striping interface built on top of the rados library, allowing to stripe bigger objects onto several standard rados objects using @@ -528,12 +542,11 @@ Summary: RADOS striping interface headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: libradosstriper1 = %{epoch}:%{version}-%{release} -Requires: librados-devel = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: libradosstriper1-devel = %{epoch}:%{version}-%{release} -Obsoletes: libradosstriper1-devel < %{epoch}:%{version}-%{release} +Requires: libradosstriper1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: libradosstriper1-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: libradosstriper1-devel < %{_epoch_prefix}%{version}-%{release} %description -n libradosstriper-devel This package contains libraries and headers needed to develop programs that use RADOS striping interface. @@ -543,10 +556,12 @@ Summary: RADOS block device client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 -Requires: librados2 = %{epoch}:%{version}-%{release} +Requires: librados2 = %{_epoch_prefix}%{version}-%{release} +%if 0%{?suse_version} +Requires(post): coreutils +%endif %if 0%{?rhel} || 0%{?fedora} -Obsoletes: ceph-libs < %{epoch}:%{version}-%{release} +Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release} %endif %description -n librbd1 RBD is a block device striped across multiple distributed objects in @@ -559,12 +574,11 @@ Summary: RADOS block device headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: librados-devel = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: librbd1-devel = %{epoch}:%{version}-%{release} -Obsoletes: librbd1-devel < %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: librbd1-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: librbd1-devel < %{_epoch_prefix}%{version}-%{release} %description -n librbd-devel This package contains libraries and headers needed to develop programs that use RADOS block device. @@ -574,10 +588,9 @@ Summary: Python 2 libraries for the RADOS block device %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: python-rados = %{epoch}:%{version}-%{release} -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-rbd This package contains Python 2 libraries for interacting with Cephs RADOS block device. @@ -587,9 +600,8 @@ Summary: Python 3 libraries for the RADOS block device %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: librbd1 = %{epoch}:%{version}-%{release} -Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release} +Requires: librbd1 = %{_epoch_prefix}%{version}-%{release} +Requires: python%{python3_pkgversion}-rados = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-rbd This package contains Python 3 libraries for interacting with Cephs RADOS block device. @@ -599,9 +611,8 @@ Summary: Ceph distributed file system client library %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 %if 0%{?rhel} || 0%{?fedora} -Obsoletes: ceph-libs < %{epoch}:%{version}-%{release} +Obsoletes: ceph-libs < %{_epoch_prefix}%{version}-%{release} Obsoletes: ceph-libcephfs %endif %description -n libcephfs2 @@ -615,12 +626,11 @@ Summary: Ceph distributed file system headers %if 0%{?suse_version} Group: Development/Libraries/C and C++ %endif -License: LGPL-2.0 -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: librados-devel = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: libcephfs2-devel = %{epoch}:%{version}-%{release} -Obsoletes: libcephfs2-devel < %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: librados-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: libcephfs2-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: libcephfs2-devel < %{_epoch_prefix}%{version}-%{release} %description -n libcephfs-devel This package contains libraries and headers needed to develop programs that use Cephs distributed file system. @@ -630,12 +640,11 @@ Summary: Python 2 libraries for Ceph distributed file system %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: libcephfs2 = %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} %if 0%{?suse_version} -Recommends: python-rados = %{epoch}:%{version}-%{release} +Recommends: python-rados = %{_epoch_prefix}%{version}-%{release} %endif -Obsoletes: python-ceph < %{epoch}:%{version}-%{release} +Obsoletes: python-ceph < %{_epoch_prefix}%{version}-%{release} %description -n python-cephfs This package contains Python 2 libraries for interacting with Cephs distributed file system. @@ -645,9 +654,8 @@ Summary: Python 3 libraries for Ceph distributed file system %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 -Requires: libcephfs2 = %{epoch}:%{version}-%{release} -Requires: python%{python3_pkgversion}-rados = %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} +Requires: python%{python3_pkgversion}-rados = %{_epoch_prefix}%{version}-%{release} %description -n python%{python3_pkgversion}-cephfs This package contains Python 3 libraries for interacting with Cephs distributed file system. @@ -657,7 +665,6 @@ Summary: Python 3 utility libraries for Ceph CLI %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 %description -n python%{python3_pkgversion}-ceph-argparse This package contains types and routines for Python 3 used by the Ceph CLI as well as the RESTful interface. These have to do with querying the daemons for @@ -670,9 +677,9 @@ Summary: Ceph benchmarks and test tools %if 0%{?suse_version} Group: System/Benchmark %endif -License: LGPL-2.0 Requires: ceph-common Requires: xmlstarlet +Requires: jq %description -n ceph-test This package contains Ceph benchmarks and test tools. %endif @@ -684,9 +691,8 @@ Summary: Java Native Interface library for CephFS Java bindings %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 Requires: java -Requires: libcephfs2 = %{epoch}:%{version}-%{release} +Requires: libcephfs2 = %{_epoch_prefix}%{version}-%{release} %description -n libcephfs_jni1 This package contains the Java Native Interface library for CephFS Java bindings. @@ -696,12 +702,11 @@ Summary: Development files for CephFS Java Native Interface library %if 0%{?suse_version} Group: Development/Libraries/Java %endif -License: LGPL-2.0 Requires: java -Requires: libcephfs_jni1 = %{epoch}:%{version}-%{release} -Obsoletes: ceph-devel < %{epoch}:%{version}-%{release} -Provides: libcephfs_jni1-devel = %{epoch}:%{version}-%{release} -Obsoletes: libcephfs_jni1-devel < %{epoch}:%{version}-%{release} +Requires: libcephfs_jni1 = %{_epoch_prefix}%{version}-%{release} +Obsoletes: ceph-devel < %{_epoch_prefix}%{version}-%{release} +Provides: libcephfs_jni1-devel = %{_epoch_prefix}%{version}-%{release} +Obsoletes: libcephfs_jni1-devel < %{_epoch_prefix}%{version}-%{release} %description -n libcephfs_jni-devel This package contains the development files for CephFS Java Native Interface library. @@ -711,9 +716,8 @@ Summary: Java libraries for the Ceph File System %if 0%{?suse_version} Group: System/Libraries %endif -License: LGPL-2.0 Requires: java -Requires: libcephfs_jni1 = %{epoch}:%{version}-%{release} +Requires: libcephfs_jni1 = %{_epoch_prefix}%{version}-%{release} Requires: junit BuildRequires: junit %description -n cephfs-java @@ -724,8 +728,7 @@ This package contains the Java libraries for the Ceph File System. %package -n rados-objclass-devel Summary: RADOS object class development kit Group: Development/Libraries -License: LGPL-2.0 -Requires: librados2-devel = %{epoch}:%{version}-%{release} +Requires: librados2-devel = %{_epoch_prefix}%{version}-%{release} %description -n rados-objclass-devel This package contains libraries and headers needed to develop RADOS object class plugins. @@ -737,8 +740,9 @@ Summary: SELinux support for Ceph MON, OSD and MDS %if 0%{?suse_version} Group: System/Filesystems %endif -Requires: ceph-base = %{epoch}:%{version}-%{release} +Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} Requires: policycoreutils, libselinux-utils +Requires(post): ceph-base = %{_epoch_prefix}%{version}-%{release} Requires(post): selinux-policy-base >= %{_selinux_policy_version}, policycoreutils, gawk Requires(postun): policycoreutils %description selinux @@ -753,12 +757,11 @@ Summary: Compatibility package for Cephs python libraries %if 0%{?suse_version} Group: Development/Languages/Python %endif -License: LGPL-2.0 Obsoletes: python-ceph -Requires: python-rados = %{epoch}:%{version}-%{release} -Requires: python-rbd = %{epoch}:%{version}-%{release} -Requires: python-cephfs = %{epoch}:%{version}-%{release} -Requires: python-rgw = %{epoch}:%{version}-%{release} +Requires: python-rados = %{_epoch_prefix}%{version}-%{release} +Requires: python-rbd = %{_epoch_prefix}%{version}-%{release} +Requires: python-cephfs = %{_epoch_prefix}%{version}-%{release} +Requires: python-rgw = %{_epoch_prefix}%{version}-%{release} Provides: python-ceph %description -n python-ceph-compat This is a compatibility package to accommodate python-ceph split into @@ -841,6 +844,11 @@ cmake .. \ $CEPH_EXTRA_CMAKE_ARGS \ %if 0%{with ocf} -DWITH_OCF=ON \ +%endif +%ifarch aarch64 armv7hl mips mipsel ppc ppc64 ppc64le %{ix86} x86_64 + -DWITH_RADOSGW_BEAST_FRONTEND=ON \ +%else + -DWITH_RADOSGW_BEAST_FRONTEND=OFF \ %endif -DBOOST_J=%{_smp_ncpus} @@ -876,7 +884,7 @@ install -m 0644 -D systemd/50-ceph.preset %{buildroot}%{_libexecdir}/systemd/sys mkdir -p %{buildroot}%{_sbindir} install -m 0644 -D src/logrotate.conf %{buildroot}%{_sysconfdir}/logrotate.d/ceph chmod 0644 %{buildroot}%{_docdir}/ceph/sample.ceph.conf -chmod 0644 %{buildroot}%{_docdir}/ceph/sample.fetch_config +install -m 0644 -D COPYING %{buildroot}%{_docdir}/ceph/COPYING # firewall templates and /sbin/mount.ceph symlink %if 0%{?suse_version} @@ -920,11 +928,6 @@ rm -rf %{buildroot} %files %files base -%defattr(-,root,root,-) -%docdir %{_docdir} -%dir %{_docdir}/ceph -%{_docdir}/ceph/sample.ceph.conf -%{_docdir}/ceph/sample.fetch_config %{_bindir}/crushtool %{_bindir}/monmaptool %{_bindir}/osdmaptool @@ -932,6 +935,7 @@ rm -rf %{buildroot} %{_bindir}/ceph-detect-init %{_libexecdir}/systemd/system-preset/50-ceph.preset %{_sbindir}/ceph-create-keys +%{_sbindir}/ceph-disk %{_sbindir}/rcceph %dir %{_libexecdir}/ceph %{_libexecdir}/ceph/ceph_common.sh @@ -950,7 +954,6 @@ rm -rf %{buildroot} %{_libdir}/libos_tp.so* %{_libdir}/libosd_tp.so* %endif -%config %{_sysconfdir}/bash_completion.d/ceph %config(noreplace) %{_sysconfdir}/logrotate.d/ceph %if 0%{?fedora} || 0%{?rhel} %config(noreplace) %{_sysconfdir}/sysconfig/ceph @@ -960,12 +963,14 @@ rm -rf %{buildroot} %config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon %config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds %endif +%{_unitdir}/ceph-disk@.service %{_unitdir}/ceph.target %{python_sitelib}/ceph_detect_init* %{python_sitelib}/ceph_disk* %{_mandir}/man8/ceph-deploy.8* %{_mandir}/man8/ceph-detect-init.8* %{_mandir}/man8/ceph-create-keys.8* +%{_mandir}/man8/ceph-disk.8* %{_mandir}/man8/ceph-run.8* %{_mandir}/man8/crushtool.8* %{_mandir}/man8/osdmaptool.8* @@ -982,11 +987,11 @@ rm -rf %{buildroot} %if 0%{?suse_version} %fillup_only if [ $1 -eq 1 ] ; then - /usr/bin/systemctl preset ceph.target >/dev/null 2>&1 || : + /usr/bin/systemctl preset ceph-disk@\*.service ceph.target >/dev/null 2>&1 || : fi %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_post ceph.target +%systemd_post ceph-disk@\*.service ceph.target %endif if [ $1 -eq 1 ] ; then /usr/bin/systemctl start ceph.target >/dev/null 2>&1 || : @@ -994,24 +999,38 @@ fi %preun base %if 0%{?suse_version} -%service_del_preun ceph.target +%service_del_preun ceph-disk@\*.service ceph.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_preun ceph.target +%systemd_preun ceph-disk@\*.service ceph.target %endif %postun base /sbin/ldconfig %if 0%{?suse_version} DISABLE_RESTART_ON_UPDATE="yes" -%service_del_postun ceph.target +%service_del_postun ceph-disk@\*.service ceph.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_postun ceph.target +%systemd_postun ceph-disk@\*.service ceph.target %endif +if [ $FIRST_ARG -ge 1 ] ; then + # Restart on upgrade, but only if "CEPH_AUTO_RESTART_ON_UPGRADE" is set to + # "yes". In any case: if units are not running, do not touch them. + SYSCONF_CEPH=%{_sysconfdir}/sysconfig/ceph + if [ -f $SYSCONF_CEPH -a -r $SYSCONF_CEPH ] ; then + source $SYSCONF_CEPH + fi + if [ "X$CEPH_AUTO_RESTART_ON_UPGRADE" = "Xyes" ] ; then + /usr/bin/systemctl try-restart ceph-disk@\*.service > /dev/null 2>&1 || : + fi +fi %files common -%defattr(-,root,root,-) +%docdir %{_docdir} +%docdir %{_docdir}/ceph +%doc %{_docdir}/ceph/sample.ceph.conf +%doc %{_docdir}/ceph/COPYING %{_bindir}/ceph %{_bindir}/ceph-authtool %{_bindir}/ceph-conf @@ -1058,6 +1077,7 @@ DISABLE_RESTART_ON_UPDATE="yes" %{_datadir}/ceph/id_rsa_drop.ceph.com %{_datadir}/ceph/id_rsa_drop.ceph.com.pub %dir %{_sysconfdir}/ceph/ +%config %{_sysconfdir}/bash_completion.d/ceph %config %{_sysconfdir}/bash_completion.d/rados %config %{_sysconfdir}/bash_completion.d/rbd %config %{_sysconfdir}/bash_completion.d/radosgw-admin @@ -1257,7 +1277,6 @@ if [ $FIRST_ARG -ge 1 ] ; then fi %files fuse -%defattr(-,root,root,-) %{_bindir}/ceph-fuse %{_mandir}/man8/ceph-fuse.8* %{_sbindir}/mount.fuse.ceph @@ -1265,12 +1284,10 @@ fi %{_unitdir}/ceph-fuse.target %files -n rbd-fuse -%defattr(-,root,root,-) %{_bindir}/rbd-fuse %{_mandir}/man8/rbd-fuse.8* %files -n rbd-mirror -%defattr(-,root,root,-) %{_bindir}/rbd-mirror %{_mandir}/man8/rbd-mirror.8* %{_unitdir}/ceph-rbd-mirror@.service @@ -1319,14 +1336,13 @@ if [ $FIRST_ARG -ge 1 ] ; then fi %files -n rbd-nbd -%defattr(-,root,root,-) %{_bindir}/rbd-nbd %{_mandir}/man8/rbd-nbd.8* %files radosgw -%defattr(-,root,root,-) %{_bindir}/radosgw %{_bindir}/radosgw-token +%{_bindir}/radosgw-es %{_bindir}/radosgw-object-expirer %{_mandir}/man8/radosgw.8* %dir %{_localstatedir}/lib/ceph/radosgw @@ -1380,31 +1396,27 @@ fi %{_bindir}/ceph-bluestore-tool %{_bindir}/ceph-objectstore-tool %{_bindir}/ceph-osd -%{_sbindir}/ceph-disk -%{_sbindir}/ceph-disk-udev %{_libexecdir}/ceph/ceph-osd-prestart.sh %dir %{_udevrulesdir} %{_udevrulesdir}/60-ceph-by-parttypeuuid.rules %{_udevrulesdir}/95-ceph-osd.rules %{_mandir}/man8/ceph-clsinfo.8* -%{_mandir}/man8/ceph-disk.8* %{_mandir}/man8/ceph-osd.8* %if 0%{?rhel} && ! 0%{?centos} -%{_sysconfdir}/cron.hourly/subman +%attr(0755,-,-) %{_sysconfdir}/cron.hourly/subman %endif %{_unitdir}/ceph-osd@.service %{_unitdir}/ceph-osd.target -%{_unitdir}/ceph-disk@.service %attr(750,ceph,ceph) %dir %{_localstatedir}/lib/ceph/osd %post osd %if 0%{?suse_version} if [ $1 -eq 1 ] ; then - /usr/bin/systemctl preset ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target >/dev/null 2>&1 || : + /usr/bin/systemctl preset ceph-osd@\*.service ceph-osd.target >/dev/null 2>&1 || : fi %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_post ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%systemd_post ceph-osd@\*.service ceph-osd.target %endif if [ $1 -eq 1 ] ; then /usr/bin/systemctl start ceph-osd.target >/dev/null 2>&1 || : @@ -1412,20 +1424,20 @@ fi %preun osd %if 0%{?suse_version} -%service_del_preun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%service_del_preun ceph-osd@\*.service ceph-osd.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_preun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%systemd_preun ceph-osd@\*.service ceph-osd.target %endif %postun osd test -n "$FIRST_ARG" || FIRST_ARG=$1 %if 0%{?suse_version} DISABLE_RESTART_ON_UPDATE="yes" -%service_del_postun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%service_del_postun ceph-osd@\*.service ceph-osd.target %endif %if 0%{?fedora} || 0%{?rhel} -%systemd_postun ceph-disk@\*.service ceph-osd@\*.service ceph-osd.target +%systemd_postun ceph-osd@\*.service ceph-osd.target %endif if [ $FIRST_ARG -ge 1 ] ; then # Restart on upgrade, but only if "CEPH_AUTO_RESTART_ON_UPGRADE" is set to @@ -1435,14 +1447,13 @@ if [ $FIRST_ARG -ge 1 ] ; then source $SYSCONF_CEPH fi if [ "X$CEPH_AUTO_RESTART_ON_UPGRADE" = "Xyes" ] ; then - /usr/bin/systemctl try-restart ceph-disk@\*.service ceph-osd@\*.service > /dev/null 2>&1 || : + /usr/bin/systemctl try-restart ceph-osd@\*.service > /dev/null 2>&1 || : fi fi %if %{with ocf} %files resource-agents -%defattr(0755,root,root,-) %dir %{_prefix}/lib/ocf %dir %{_prefix}/lib/ocf/resource.d %dir %{_prefix}/lib/ocf/resource.d/ceph @@ -1451,7 +1462,6 @@ fi %endif %files -n librados2 -%defattr(-,root,root,-) %{_libdir}/librados.so.* %dir %{_libdir}/ceph %{_libdir}/ceph/libceph-common.so* @@ -1464,7 +1474,6 @@ fi %postun -n librados2 -p /sbin/ldconfig %files -n librados-devel -%defattr(-,root,root,-) %dir %{_includedir}/rados %{_includedir}/rados/librados.h %{_includedir}/rados/librados.hpp @@ -1484,17 +1493,14 @@ fi %{_mandir}/man8/librados-config.8* %files -n python-rados -%defattr(-,root,root,-) %{python_sitearch}/rados.so %{python_sitearch}/rados-*.egg-info %files -n python%{python3_pkgversion}-rados -%defattr(-,root,root,-) %{python3_sitearch}/rados.cpython*.so %{python3_sitearch}/rados-*.egg-info %files -n libradosstriper1 -%defattr(-,root,root,-) %{_libdir}/libradosstriper.so.* %post -n libradosstriper1 -p /sbin/ldconfig @@ -1502,14 +1508,12 @@ fi %postun -n libradosstriper1 -p /sbin/ldconfig %files -n libradosstriper-devel -%defattr(-,root,root,-) %dir %{_includedir}/radosstriper %{_includedir}/radosstriper/libradosstriper.h %{_includedir}/radosstriper/libradosstriper.hpp %{_libdir}/libradosstriper.so %files -n librbd1 -%defattr(-,root,root,-) %{_libdir}/librbd.so.* %if %{with lttng} %{_libdir}/librbd_tp.so.* @@ -1523,7 +1527,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n librbd1 -p /sbin/ldconfig %files -n librbd-devel -%defattr(-,root,root,-) %dir %{_includedir}/rbd %{_includedir}/rbd/librbd.h %{_includedir}/rbd/librbd.hpp @@ -1534,7 +1537,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %endif %files -n librgw2 -%defattr(-,root,root,-) %{_libdir}/librgw.so.* %post -n librgw2 -p /sbin/ldconfig @@ -1542,34 +1544,28 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n librgw2 -p /sbin/ldconfig %files -n librgw-devel -%defattr(-,root,root,-) %dir %{_includedir}/rados %{_includedir}/rados/librgw.h %{_includedir}/rados/rgw_file.h %{_libdir}/librgw.so %files -n python-rgw -%defattr(-,root,root,-) %{python_sitearch}/rgw.so %{python_sitearch}/rgw-*.egg-info %files -n python%{python3_pkgversion}-rgw -%defattr(-,root,root,-) %{python3_sitearch}/rgw.cpython*.so %{python3_sitearch}/rgw-*.egg-info %files -n python-rbd -%defattr(-,root,root,-) %{python_sitearch}/rbd.so %{python_sitearch}/rbd-*.egg-info %files -n python%{python3_pkgversion}-rbd -%defattr(-,root,root,-) %{python3_sitearch}/rbd.cpython*.so %{python3_sitearch}/rbd-*.egg-info %files -n libcephfs2 -%defattr(-,root,root,-) %{_libdir}/libcephfs.so.* %post -n libcephfs2 -p /sbin/ldconfig @@ -1577,27 +1573,23 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n libcephfs2 -p /sbin/ldconfig %files -n libcephfs-devel -%defattr(-,root,root,-) %dir %{_includedir}/cephfs %{_includedir}/cephfs/libcephfs.h %{_includedir}/cephfs/ceph_statx.h %{_libdir}/libcephfs.so %files -n python-cephfs -%defattr(-,root,root,-) %{python_sitearch}/cephfs.so %{python_sitearch}/cephfs-*.egg-info %{python_sitelib}/ceph_volume_client.py* %files -n python%{python3_pkgversion}-cephfs -%defattr(-,root,root,-) %{python3_sitearch}/cephfs.cpython*.so %{python3_sitearch}/cephfs-*.egg-info %{python3_sitelib}/ceph_volume_client.py %{python3_sitelib}/__pycache__/ceph_volume_client.cpython*.py* %files -n python%{python3_pkgversion}-ceph-argparse -%defattr(-,root,root,-) %{python3_sitelib}/ceph_argparse.py %{python3_sitelib}/__pycache__/ceph_argparse.cpython*.py* %{python3_sitelib}/ceph_daemon.py @@ -1605,7 +1597,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %if 0%{with ceph_test_package} %files -n ceph-test -%defattr(-,root,root,-) %{_bindir}/ceph-client-debug %{_bindir}/ceph_bench_log %{_bindir}/ceph_kvstorebench @@ -1636,8 +1627,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %{_bindir}/ceph-osdomap-tool %{_bindir}/ceph-kvstore-tool %{_bindir}/ceph-debugpack -%{_bindir}/dmclock-tests -%{_bindir}/dmclock-data-struct-tests %{_mandir}/man8/ceph-debugpack.8* %dir %{_libdir}/ceph %{_libdir}/ceph/ceph-monstore-update-crush.sh @@ -1645,7 +1634,6 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %if 0%{with cephfs_java} %files -n libcephfs_jni1 -%defattr(-,root,root,-) %{_libdir}/libcephfs_jni.so.* %post -n libcephfs_jni1 -p /sbin/ldconfig @@ -1653,23 +1641,19 @@ ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1 %postun -n libcephfs_jni1 -p /sbin/ldconfig %files -n libcephfs_jni-devel -%defattr(-,root,root,-) %{_libdir}/libcephfs_jni.so %files -n cephfs-java -%defattr(-,root,root,-) %{_javadir}/libcephfs.jar %{_javadir}/libcephfs-test.jar %endif %files -n rados-objclass-devel -%defattr(-,root,root,-) %dir %{_includedir}/rados %{_includedir}/rados/objclass.h %if 0%{with selinux} %files selinux -%defattr(-,root,root,-) %attr(0600,root,root) %{_datadir}/selinux/packages/ceph.pp %{_datadir}/selinux/devel/include/contrib/ceph.if %{_mandir}/man8/ceph_selinux.8* @@ -1703,8 +1687,14 @@ if test $STATUS -eq 0; then /usr/bin/systemctl stop ceph.target > /dev/null 2>&1 fi -# Now, relabel the files -/usr/sbin/fixfiles -C ${FILE_CONTEXT}.pre restore 2> /dev/null +# Relabel the files +# Use ceph-disk fix for first package install and fixfiles otherwise +if [ "$1" = "1" ]; then + /usr/sbin/ceph-disk fix --selinux +else + /usr/sbin/fixfiles -C ${FILE_CONTEXT}.pre restore 2> /dev/null +fi + rm -f ${FILE_CONTEXT}.pre # The fixfiles command won't fix label for /var/run/ceph /usr/sbin/restorecon -R /var/run/ceph > /dev/null 2>&1 diff --git a/ceph/cmake/modules/BuildBoost.cmake b/ceph/cmake/modules/BuildBoost.cmake new file mode 100644 index 000000000..2b5f87740 --- /dev/null +++ b/ceph/cmake/modules/BuildBoost.cmake @@ -0,0 +1,184 @@ +# This module builds Boost +# executables are. It sets the following variables: +# +# Boost_FOUND : boolean - system has Boost +# Boost_LIBRARIES : list(filepath) - the libraries needed to use Boost +# Boost_INCLUDE_DIRS : list(path) - the Boost include directories +# +# Following hints are respected +# +# Boost_USE_STATIC_LIBS : boolean (default: OFF) +# Boost_USE_MULTITHREADED : boolean (default: OFF) +# BOOST_J: integer (defanult 1) + +function(do_build_boost version) + cmake_parse_arguments(Boost_BUILD "" "" COMPONENTS ${ARGN}) + set(boost_features "variant=release") + if(Boost_USE_MULTITHREADED) + list(APPEND boost_features "threading=multi") + else() + list(APPEND boost_features "threading=single") + endif() + if(Boost_USE_STATIC_LIBS) + list(APPEND boost_features "link=static") + else() + list(APPEND boost_features "link=shared") + endif() + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND boost_features "address-model=64") + else() + list(APPEND boost_features "address-model=32") + endif() + set(BOOST_CXXFLAGS "-fPIC -w") # check on arm, etc <---XXX + list(APPEND boost_features "cxxflags=${BOOST_CXXFLAGS}") + + string(REPLACE ";" "," boost_with_libs "${Boost_BUILD_COMPONENTS}") + # build b2 and prepare the project-config.jam for boost + set(configure_command + ./bootstrap.sh --prefix= + --with-libraries=${boost_with_libs}) + + set(b2 ./b2) + if(BOOST_J) + message(STATUS "BUILDING Boost Libraries at j ${BOOST_J}") + list(APPEND b2 -j${BOOST_J}) + endif() + if(CMAKE_VERBOSE_MAKEFILE) + list(APPEND b2 -d1) + else() + list(APPEND b2 -d0) + endif() + + if(NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) + # we are crosscompiling + if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) + set(b2_cc gcc) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(b2_cc clang) + else() + message(SEND_ERROR "unknown compiler: ${CMAKE_CXX_COMPILER_ID}") + endif() + # edit the config.jam so, b2 will be able to use the specified toolset + execute_process( + COMMAND + sed -i + "s|using ${b2_cc} ;|using ${b2_cc} : ${CMAKE_SYSTEM_PROCESSOR} : ${CMAKE_CXX_COMPILER} ;|" + ${PROJECT_SOURCE_DIR}/src/boost/project-config.jam) + # use ${CMAKE_SYSTEM_PROCESSOR} as the version identifier of compiler + list(APPEND b2 toolset=${b2_cc}-${CMAKE_SYSTEM_PROCESSOR}) + endif() + + set(build_command + ${b2} headers stage + #"--buildid=ceph" # changes lib names--can omit for static + ${boost_features}) + set(install_command + ${b2} install) + set(boost_root_dir "${CMAKE_BINARY_DIR}/boost") + if(EXISTS "${PROJECT_SOURCE_DIR}/src/boost/libs/config/include/boost/config.hpp") + message(STATUS "boost already in src") + set(source_dir + SOURCE_DIR "${PROJECT_SOURCE_DIR}/src/boost") + elseif(version VERSION_GREATER 1.63) + message(FATAL_ERROR "Unknown BOOST_REQUESTED_VERSION: ${version}") + else() + message(STATUS "boost will be downloaded from sf.net") + set(boost_version 1.63.0) + set(boost_md5 1c837ecd990bb022d07e7aab32b09847) + string(REPLACE "." "_" boost_version_underscore ${boost_version} ) + set(boost_url http://downloads.sourceforge.net/project/boost/boost/${boost_version}/boost_${boost_version_underscore}.tar.bz2) + set(source_dir + URL ${boost_url} + URL_MD5 ${boost_md5}) + if(CMAKE_VERSION VERSION_GREATER 3.0) + list(APPEND source_dir DOWNLOAD_NO_PROGRESS 1) + endif() + endif() + # build all components in a single shot + include(ExternalProject) + ExternalProject_Add(Boost + ${source_dir} + CONFIGURE_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${configure_command} + BUILD_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${build_command} + BUILD_IN_SOURCE 1 + INSTALL_COMMAND ${install_command} + PREFIX "${boost_root_dir}") +endfunction() + +macro(build_boost version) + do_build_boost(version ${ARGN}) + ExternalProject_Get_Property(Boost install_dir) + set(Boost_INCLUDE_DIRS ${install_dir}/include) + set(Boost_INCLUDE_DIR ${install_dir}/include) + # create the directory so cmake won't complain when looking at the imported + # target + file(MAKE_DIRECTORY ${Boost_INCLUDE_DIRS}) + cmake_parse_arguments(Boost_BUILD "" "" COMPONENTS ${ARGN}) + foreach(c ${Boost_BUILD_COMPONENTS}) + string(TOUPPER ${c} upper_c) + if(Boost_USE_STATIC_LIBS) + add_library(Boost::${c} STATIC IMPORTED) + else() + add_library(Boost::${c} SHARED IMPORTED) + endif() + add_dependencies(Boost::${c} Boost) + if(Boost_USE_STATIC_LIBS) + set(Boost_${upper_c}_LIBRARY + ${install_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}boost_${c}${CMAKE_STATIC_LIBRARY_SUFFIX}) + else() + set(Boost_${upper_c}_LIBRARY + ${install_dir}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}boost_${c}${CMAKE_SHARED_LIBRARY_SUFFIX}) + endif() + set_target_properties(Boost::${c} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${Boost_${upper_c}_LIBRARY}") + list(APPEND Boost_LIBRARIES ${Boost_${upper_c}_LIBRARY}) + endforeach() + + # for header-only libraries + if(CMAKE_VERSION VERSION_LESS 3.3) + # only ALIAS and INTERFACE target names allow ":" in it, but + # INTERFACE library is not allowed until cmake 3.1 + add_custom_target(Boost.boost DEPENDS Boost) + else() + add_library(Boost.boost INTERFACE IMPORTED) + set_target_properties(Boost.boost PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") + add_dependencies(Boost.boost Boost) + endif() + find_package_handle_standard_args(Boost DEFAULT_MSG + Boost_INCLUDE_DIRS Boost_LIBRARIES) + mark_as_advanced(Boost_LIBRARIES BOOST_INCLUDE_DIRS) +endmacro() + +function(maybe_add_boost_dep target) + get_target_property(imported ${target} IMPORTED) + if(imported) + return() + endif() + get_target_property(type ${target} TYPE) + if(NOT type MATCHES "OBJECT_LIBRARY|STATIC_LIBRARY|SHARED_LIBRARY|EXECUTABLE") + return() + endif() + get_target_property(sources ${target} SOURCES) + foreach(src ${sources}) + get_filename_component(ext ${src} EXT) + # assuming all cxx source files include boost header(s) + if(ext MATCHES ".cc|.cpp|.cxx") + add_dependencies(${target} Boost.boost) + return() + endif() + endforeach() +endfunction() + +# override add_library() to add Boost headers dependency +function(add_library target) + _add_library(${target} ${ARGN}) + maybe_add_boost_dep(${target}) +endfunction() + +function(add_executable target) + _add_executable(${target} ${ARGN}) + maybe_add_boost_dep(${target}) +endfunction() diff --git a/ceph/cmake/modules/Findatomic_ops.cmake b/ceph/cmake/modules/Findatomic_ops.cmake deleted file mode 100644 index c6714b77f..000000000 --- a/ceph/cmake/modules/Findatomic_ops.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# - Find atomic_ops -# Find the native ATOMIC_OPS headers and libraries. -# -# ATOMIC_OPS_INCLUDE_DIRS - where to find atomic_ops.h, etc. -# ATOMIC_OPS_LIBRARIES - List of libraries when using atomic_ops. -# ATOMIC_OPS_FOUND - True if atomic_ops found. - -# Look for the header file. -FIND_PATH(ATOMIC_OPS_INCLUDE_DIR NAMES atomic_ops.h) - -# Look for the library. -FIND_LIBRARY(ATOMIC_OPS_LIBRARY NAMES atomic_ops) - -# handle the QUIETLY and REQUIRED arguments and set ATOMIC_OPS_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(atomic_ops DEFAULT_MSG ATOMIC_OPS_LIBRARY ATOMIC_OPS_INCLUDE_DIR) - -# Copy the results to the output variables. -IF(ATOMIC_OPS_FOUND) - SET(ATOMIC_OPS_LIBRARIES ${ATOMIC_OPS_LIBRARY}) - SET(ATOMIC_OPS_INCLUDE_DIRS ${ATOMIC_OPS_INCLUDE_DIR}) -ELSE(ATOMIC_OPS_FOUND) - SET(ATOMIC_OPS_LIBRARIES) - SET(ATOMIC_OPS_INCLUDE_DIRS) -ENDIF(ATOMIC_OPS_FOUND) - -MARK_AS_ADVANCED(ATOMIC_OPS_INCLUDE_DIR ATOMIC_OPS_LIBRARY) diff --git a/ceph/cmake/modules/Findpmem.cmake b/ceph/cmake/modules/Findpmem.cmake new file mode 100644 index 000000000..efcf68288 --- /dev/null +++ b/ceph/cmake/modules/Findpmem.cmake @@ -0,0 +1,15 @@ +# Try to find libpmem +# +# Once done, this will define +# +# PMEM_FOUND +# PMEM_INCLUDE_DIR +# PMEM_LIBRARY + +find_path(PMEM_INCLUDE_DIR NAMES libpmem.h) +find_library(PMEM_LIBRARY NAMES pmem) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(pmem DEFAULT_MSG PMEM_LIBRARY PMEM_INCLUDE_DIR) + +mark_as_advanced(PMEM_INCLUDE_DIR PMEM_LIBRARY) diff --git a/ceph/cmake/modules/SIMDExt.cmake b/ceph/cmake/modules/SIMDExt.cmake index 43d039e10..5330835aa 100644 --- a/ceph/cmake/modules/SIMDExt.cmake +++ b/ceph/cmake/modules/SIMDExt.cmake @@ -75,34 +75,38 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i386|i686|amd64|x86_64|AMD64") set(HAVE_INTEL 1) - CHECK_C_COMPILER_FLAG(-msse HAVE_INTEL_SSE) - if(HAVE_INTEL_SSE) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse") - endif() - CHECK_C_COMPILER_FLAG(-msse2 HAVE_INTEL_SSE2) - if(HAVE_INTEL_SSE2) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse2") - endif() - CHECK_C_COMPILER_FLAG(-msse3 HAVE_INTEL_SSE3) - if(HAVE_INTEL_SSE3) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse3") - endif() - CHECK_C_COMPILER_FLAG(-mssse3 HAVE_INTEL_SSSE3) - if(HAVE_INTEL_SSSE3) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -mssse3") - endif() - CHECK_C_COMPILER_FLAG(-mpclmul HAVE_INTEL_PCLMUL) - if(HAVE_INTEL_PCLMUL) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -mpclmul") - endif() - CHECK_C_COMPILER_FLAG(-msse4.1 HAVE_INTEL_SSE4_1) - if(HAVE_INTEL_SSE4_1) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse4.1") - endif() - CHECK_C_COMPILER_FLAG(-msse4.2 HAVE_INTEL_SSE4_2) - if(HAVE_INTEL_SSE4_2) - set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse4.2") - endif() + if(CMAKE_SYSTEM_PROCESSOR MATCHES "i686|amd64|x86_64|AMD64") + CHECK_C_COMPILER_FLAG(-msse HAVE_INTEL_SSE) + if(HAVE_INTEL_SSE) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse") + endif() + if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64") + CHECK_C_COMPILER_FLAG(-msse2 HAVE_INTEL_SSE2) + if(HAVE_INTEL_SSE2) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse2") + endif() + CHECK_C_COMPILER_FLAG(-msse3 HAVE_INTEL_SSE3) + if(HAVE_INTEL_SSE3) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse3") + endif() + CHECK_C_COMPILER_FLAG(-mssse3 HAVE_INTEL_SSSE3) + if(HAVE_INTEL_SSSE3) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -mssse3") + endif() + CHECK_C_COMPILER_FLAG(-mpclmul HAVE_INTEL_PCLMUL) + if(HAVE_INTEL_PCLMUL) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -mpclmul") + endif() + CHECK_C_COMPILER_FLAG(-msse4.1 HAVE_INTEL_SSE4_1) + if(HAVE_INTEL_SSE4_1) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse4.1") + endif() + CHECK_C_COMPILER_FLAG(-msse4.2 HAVE_INTEL_SSE4_2) + if(HAVE_INTEL_SSE4_2) + set(SIMD_COMPILE_FLAGS "${SIMD_COMPILE_FLAGS} -msse4.2") + endif() + endif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64") + endif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686|amd64|x86_64|AMD64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(powerpc|ppc)64le") set(HAVE_PPC64LE 1) message(STATUS " we are ppc64le") diff --git a/ceph/debian/ceph-base.install b/ceph/debian/ceph-base.install index 55ba5e204..2a56cabee 100644 --- a/ceph/debian/ceph-base.install +++ b/ceph/debian/ceph-base.install @@ -1,4 +1,3 @@ -etc/bash_completion.d/ceph etc/init.d/ceph usr/sbin/ceph-create-keys usr/bin/ceph-detect-init @@ -11,7 +10,6 @@ usr/lib/ceph/ceph_common.sh usr/lib/ceph/erasure-code/* usr/lib/rados-classes/* usr/share/doc/ceph/sample.ceph.conf -usr/share/doc/ceph/sample.fetch_config usr/share/man/man8/ceph-debugpack.8 usr/share/man/man8/ceph-deploy.8 usr/share/man/man8/ceph-run.8 diff --git a/ceph/debian/ceph-base.maintscript b/ceph/debian/ceph-base.maintscript new file mode 100644 index 000000000..38e36d454 --- /dev/null +++ b/ceph/debian/ceph-base.maintscript @@ -0,0 +1,2 @@ +rm_conffile /etc/logrotate.d/ceph.logrotate -- "$@" +rm_conffile /etc/logrotate.d/ceph -- "$@" diff --git a/ceph/debian/ceph-common.install b/ceph/debian/ceph-common.install index ba7eb7005..11e24f494 100755 --- a/ceph/debian/ceph-common.install +++ b/ceph/debian/ceph-common.install @@ -1,5 +1,6 @@ #! /usr/bin/dh-exec --with=install +etc/bash_completion.d/ceph etc/bash_completion.d/rados etc/bash_completion.d/radosgw-admin etc/bash_completion.d/rbd diff --git a/ceph/debian/ceph-osd.install b/ceph/debian/ceph-osd.install index 9f520ec47..b1532d5e9 100644 --- a/ceph/debian/ceph-osd.install +++ b/ceph/debian/ceph-osd.install @@ -1,7 +1,6 @@ lib/udev/rules.d/95-ceph-osd.rules lib/udev/rules.d/60-ceph-by-parttypeuuid.rules usr/sbin/ceph-disk -usr/sbin/ceph-disk-udev usr/bin/ceph-clsinfo usr/bin/ceph-objectstore-tool usr/bin/ceph-bluestore-tool diff --git a/ceph/debian/ceph-test.install b/ceph/debian/ceph-test.install index 4fdf179e3..15b04664e 100644 --- a/ceph/debian/ceph-test.install +++ b/ceph/debian/ceph-test.install @@ -26,7 +26,5 @@ usr/bin/ceph_xattr_bench usr/bin/ceph-monstore-tool usr/bin/ceph-osdomap-tool usr/bin/ceph-kvstore-tool -usr/bin/dmclock-tests -usr/bin/dmclock-data-struct-tests usr/share/java/libcephfs-test.jar usr/lib/ceph/ceph-monstore-update-crush.sh diff --git a/ceph/debian/changelog b/ceph/debian/changelog index 147e18631..9a6469c30 100644 --- a/ceph/debian/changelog +++ b/ceph/debian/changelog @@ -1,3 +1,9 @@ +ceph (12.1.0-1) stable; urgency=medium + + * New upstream release + + -- Ceph Release Team Thu, 22 Jun 2017 15:43:47 +0000 + ceph (12.0.3-1) stable; urgency=medium * New upstream release diff --git a/ceph/debian/control b/ceph/debian/control index eb91c40b6..a9ce89021 100644 --- a/ceph/debian/control +++ b/ceph/debian/control @@ -9,6 +9,7 @@ Uploaders: Ken Dreyer , Alfredo Deza Build-Depends: bc, btrfs-tools, + gperf, cmake, cpio, cryptsetup-bin | cryptsetup, @@ -25,13 +26,11 @@ Build-Depends: bc, jq, junit4, libaio-dev, - libatomic-ops-dev, libbabeltrace-ctf-dev, libbabeltrace-dev, libblkid-dev (>= 2.17), libcurl4-gnutls-dev, libexpat1-dev, - libfcgi-dev, libfuse-dev, libgoogle-perftools-dev [i386 amd64 arm64], libibverbs-dev, @@ -50,10 +49,13 @@ Build-Depends: bc, pkg-config, python (>= 2.7), python-all-dev, + python-cherrypy3, python-nose, + python-pecan, python-prettytable, python-setuptools, python-sphinx, + python-werkzeug, python3-all-dev, python3-setuptools, virtualenv | python-virtualenv, @@ -159,12 +161,16 @@ Description: debugging symbols for ceph-mds Package: ceph-mgr Architecture: linux-any Depends: ceph-base (= ${binary:Version}), + python-openssl, + python-pecan, + python-werkzeug, ${misc:Depends}, ${python:Depends}, + python-cherrypy3, ${shlibs:Depends} Replaces: ceph (<< 0.93-417) Breaks: ceph (<< 0.93-417) -Description: metadata server for the ceph distributed file system +Description: manager for the ceph distributed storage system Ceph is a massively scalable, open-source, distributed storage system that runs on commodity hardware and delivers object, block and file system storage. @@ -646,7 +652,7 @@ Description: debugging symbols for radosgw Package: ceph-test Architecture: linux-any -Depends: ceph-common, curl, xmlstarlet, ${misc:Depends}, ${shlibs:Depends} +Depends: ceph-common, curl, xmlstarlet, jq, ${misc:Depends}, ${shlibs:Depends} Description: Ceph test and benchmarking tools This package contains tools for testing and benchmarking Ceph. diff --git a/ceph/debian/copyright b/ceph/debian/copyright index c4c4a3b67..362ae78f2 100644 --- a/ceph/debian/copyright +++ b/ceph/debian/copyright @@ -33,10 +33,6 @@ Files: src/common/bloom_filter.hpp Copyright: Copyright (C) 2000 Arash Partow License: Boost Software License, Version 1.0 -Files: m4/acx_pthread.m4 -Copyright: Steven G. Johnson -License: GPLWithACException - Files: src/common/crc32c_intel*: Copyright: Copyright 2012-2013 Intel Corporation All Rights Reserved. diff --git a/ceph/debian/radosgw.install b/ceph/debian/radosgw.install index 192f2329b..9f2c8debb 100644 --- a/ceph/debian/radosgw.install +++ b/ceph/debian/radosgw.install @@ -1,4 +1,5 @@ usr/bin/radosgw usr/bin/radosgw-token +usr/bin/radosgw-es usr/bin/radosgw-object-expirer usr/share/man/man8/radosgw.8 diff --git a/ceph/debian/rules b/ceph/debian/rules index f8fb8117d..d4b3c97f7 100755 --- a/ceph/debian/rules +++ b/ceph/debian/rules @@ -22,6 +22,13 @@ ifeq ($(DEB_HOST_ARCH), armel) extraopts += -DWITH_ATOMIC_OPS=OFF endif +ifneq (,$(filter $(DEB_HOST_ARCH), arm armel armhf arm64 i386 amd64 mips mipsel powerpc ppc64)) + # beast depends on libboost_context which only support the archs above + extraopts += -DWITH_RADOSGW_BEAST_FRONTEND=ON +else + extraopts += -DWITH_RADOSGW_BEAST_FRONTEND=OFF +endif + %: dh $@ --buildsystem=cmake --with javahelper,python2,python3,systemd --parallel @@ -52,8 +59,8 @@ override_dh_installdocs: dh_installdocs -a --all ChangeLog override_dh_installlogrotate: - cp src/logrotate.conf debian/ceph-base.ceph.logrotate - dh_installlogrotate -pceph-base --name=ceph + cp src/logrotate.conf debian/ceph-common.logrotate + dh_installlogrotate -pceph-common override_dh_installinit: # dh_installinit is only set up to handle one upstart script diff --git a/ceph/do_cmake.sh b/ceph/do_cmake.sh index 2e9de99e9..9b04cb114 100755 --- a/ceph/do_cmake.sh +++ b/ceph/do_cmake.sh @@ -4,9 +4,16 @@ if test -e build; then echo 'build dir already exists; rm -rf build and re-run' exit 1 fi + +ARGS="" +if which ccache ; then + echo "enabling ccache" + ARGS+="-DWITH_CCACHE=ON" +fi + mkdir build cd build -cmake -DBOOST_J=$(nproc) "$@" .. +cmake -DBOOST_J=$(nproc) $ARGS "$@" .. # minimal config to find plugins cat < ceph.conf diff --git a/ceph/doc/api/index.rst b/ceph/doc/api/index.rst index 4b62dd6b1..67d774cfa 100644 --- a/ceph/doc/api/index.rst +++ b/ceph/doc/api/index.rst @@ -33,14 +33,6 @@ See `librgw-py`_. .. _librgw-py: ../radosgw/api -Calamari APIs -============= - -See `Calamari API`_. - -.. _Calamari API: http://ceph.com/calamari/docs/calamari_rest/index.html - - Ceph Object Store APIs ====================== diff --git a/ceph/doc/architecture.rst b/ceph/doc/architecture.rst index e851bb76d..f9bdfa282 100644 --- a/ceph/doc/architecture.rst +++ b/ceph/doc/architecture.rst @@ -207,10 +207,10 @@ of failure or bottleneck when using ``cephx``. The monitor returns an authentication data structure similar to a Kerberos ticket that contains a session key for use in obtaining Ceph services. This session key is itself encrypted with the user's permanent secret key, so that only the user can -request services from the Ceph monitor(s). The client then uses the session key +request services from the Ceph Monitor(s). The client then uses the session key to request its desired services from the monitor, and the monitor provides the client with a ticket that will authenticate the client to the OSDs that actually -handle data. Ceph monitors and OSDs share a secret, so the client can use the +handle data. Ceph Monitors and OSDs share a secret, so the client can use the ticket provided by the monitor with any OSD or metadata server in the cluster. Like Kerberos, ``cephx`` tickets expire, so an attacker cannot use an expired ticket or session key obtained surreptitiously. This form of authentication will @@ -338,7 +338,7 @@ dispatch--which is a **huge** bottleneck at the petabyte-to-exabyte scale. Ceph eliminates the bottleneck: Ceph's OSD Daemons AND Ceph Clients are cluster aware. Like Ceph clients, each Ceph OSD Daemon knows about other Ceph OSD Daemons in the cluster. This enables Ceph OSD Daemons to interact directly with -other Ceph OSD Daemons and Ceph monitors. Additionally, it enables Ceph Clients +other Ceph OSD Daemons and Ceph Monitors. Additionally, it enables Ceph Clients to interact directly with Ceph OSD Daemons. The ability of Ceph Clients, Ceph Monitors and Ceph OSD Daemons to interact with @@ -360,13 +360,15 @@ ability to leverage this computing power leads to several major benefits: Ceph Client requests. If a Ceph OSD Daemon is ``down`` and ``in`` the Ceph Storage Cluster, this status may indicate the failure of the Ceph OSD Daemon. If a Ceph OSD Daemon is not running (e.g., it crashes), the Ceph OSD - Daemon cannot notify the Ceph Monitor that it is ``down``. The Ceph Monitor - can ping a Ceph OSD Daemon periodically to ensure that it is running. - However, Ceph also empowers Ceph OSD Daemons to determine if a neighboring - OSD is ``down``, to update the cluster map and to report it to the Ceph - monitor(s). This means that Ceph monitors can remain light weight processes. - See `Monitoring OSDs`_ and `Heartbeats`_ for additional details. - + Daemon cannot notify the Ceph Monitor that it is ``down``. The OSDs + periodically send messages to the Ceph Monitor (``MPGStats`` pre-luminous, + and a new ``MOSDBeacon`` in luminous). If the Ceph Monitor doesn't see that + message after a configurable period of time then it marks the OSD down. + This mechanism is a failsafe, however. Normally, Ceph OSD Daemons will + determine if a neighboring OSD is down and report it to the Ceph Monitor(s). + This assures that Ceph Monitors are lightweight processes. See `Monitoring + OSDs`_ and `Heartbeats`_ for additional details. + #. **Data Scrubbing:** As part of maintaining data consistency and cleanliness, Ceph OSD Daemons can scrub objects within placement groups. That is, Ceph OSD Daemons can compare object metadata in one placement group with its @@ -1579,7 +1581,7 @@ instance for high availability. .. _Monitoring OSDs and PGs: ../rados/operations/monitoring-osd-pg .. _Heartbeats: ../rados/configuration/mon-osd-interaction .. _Monitoring OSDs: ../rados/operations/monitoring-osd-pg/#monitoring-osds -.. _CRUSH - Controlled, Scalable, Decentralized Placement of Replicated Data: http://ceph.com/papers/weil-crush-sc06.pdf +.. _CRUSH - Controlled, Scalable, Decentralized Placement of Replicated Data: https://ceph.com/wp-content/uploads/2016/08/weil-crush-sc06.pdf .. _Data Scrubbing: ../rados/configuration/osd-config-ref#scrubbing .. _Report Peering Failure: ../rados/configuration/mon-osd-interaction#osds-report-peering-failure .. _Troubleshooting Peering Failure: ../rados/troubleshooting/troubleshooting-pg#placement-group-down-peering-failure diff --git a/ceph/doc/cephfs/administration.rst b/ceph/doc/cephfs/administration.rst index 7375a7618..23bd5fc6a 100644 --- a/ceph/doc/cephfs/administration.rst +++ b/ceph/doc/cephfs/administration.rst @@ -42,6 +42,38 @@ creation of multiple filesystems use ``ceph fs flag set enable_multiple true``. fs rm_data_pool +Settings +-------- + +:: + + fs set max_file_size + +CephFS has a configurable maximum file size, and it's 1TB by default. +You may wish to set this limit higher if you expect to store large files +in CephFS. It is a 64-bit field. + +Setting ``max_file_size`` to 0 does not disable the limit. It would +simply limit clients to only creating empty files. + + +Maximum file sizes and performance +---------------------------------- + +CephFS enforces the maximum file size limit at the point of appending to +files or setting their size. It does not affect how anything is stored. + +When users create a file of an enormous size (without necessarily +writing any data to it), some operations (such as deletes) cause the MDS +to have to do a large number of operations to check if any of the RADOS +objects within the range that could exist (according to the file size) +really existed. + +The ``max_file_size`` setting prevents users from creating files that +appear to be eg. exabytes in size, causing load on the MDS as it tries +to enumerate the objects during operations like stats or deletes. + + Daemons ------- @@ -126,6 +158,11 @@ filesystem. Legacy ------ +The ``ceph mds set`` command is the deprecated version of ``ceph fs set``, +from before there was more than one filesystem per cluster. It operates +on whichever filesystem is marked as the default (see ``ceph fs +set-default``.) + :: mds stat diff --git a/ceph/doc/cephfs/eviction.rst b/ceph/doc/cephfs/eviction.rst index bd201cebb..e1400a1ce 100644 --- a/ceph/doc/cephfs/eviction.rst +++ b/ceph/doc/cephfs/eviction.rst @@ -1,4 +1,5 @@ +=============================== Ceph filesystem client eviction =============================== @@ -6,114 +7,139 @@ When a filesystem client is unresponsive or otherwise misbehaving, it may be necessary to forcibly terminate its access to the filesystem. This process is called *eviction*. -This process is somewhat thorough in order to protect against data inconsistency -resulting from misbehaving clients. +Evicting a CephFS client prevents it from communicating further with MDS +daemons and OSD daemons. If a client was doing buffered IO to the filesystem, +any un-flushed data will be lost. + +Clients may either be evicted automatically (if they fail to communicate +promptly with the MDS), or manually (by the system administrator). + +The client eviction process applies to clients of all kinds, this includes +FUSE mounts, kernel mounts, nfs-ganesha gateways, and any process using +libcephfs. + +Automatic client eviction +========================= + +There are two situations in which a client may be evicted automatically: + +On an active MDS daemon, if a client has not communicated with the MDS for +over ``mds_session_autoclose`` seconds (300 seconds by default), then it +will be evicted automatically. + +During MDS startup (including on failover), the MDS passes through a +state called ``reconnect``. During this state, it waits for all the +clients to connect to the new MDS daemon. If any clients fail to do +so within the time window (``mds_reconnect_timeout``, 45 seconds by default) +then they will be evicted. + +A warning message is sent to the cluster log if either of these situations +arises. -OSD blacklisting ----------------- +Manual client eviction +====================== -First, prevent the client from performing any more data operations by *blacklisting* -it at the RADOS level. You may be familiar with this concept as *fencing* in other -storage systems. +Sometimes, the administrator may want to evict a client manually. This +could happen if a client is died and the administrator does not +want to wait for its session to time out, or it could happen if +a client is misbehaving and the administrator does not have access to +the client node to unmount it. -Identify the client to evict from the MDS session list: +It is useful to inspect the list of clients first: :: - # ceph daemon mds.a session ls + ceph tell mds.0 client ls + [ - { "id": 4117, - "num_leases": 0, - "num_caps": 1, - "state": "open", - "replay_requests": 0, - "reconnecting": false, - "inst": "client.4117 172.16.79.251:0\/3271", - "client_metadata": { "entity_id": "admin", - "hostname": "fedoravm.localdomain", - "mount_point": "\/home\/user\/mnt"}}] - -In this case the 'fedoravm' client has address ``172.16.79.251:0/3271``, so we blacklist -it as follows: + { + "id": 4305, + "num_leases": 0, + "num_caps": 3, + "state": "open", + "replay_requests": 0, + "completed_requests": 0, + "reconnecting": false, + "inst": "client.4305 172.21.9.34:0/422650892", + "client_metadata": { + "ceph_sha1": "ae81e49d369875ac8b569ff3e3c456a31b8f3af5", + "ceph_version": "ceph version 12.0.0-1934-gae81e49 (ae81e49d369875ac8b569ff3e3c456a31b8f3af5)", + "entity_id": "0", + "hostname": "senta04", + "mount_point": "/tmp/tmpcMpF1b/mnt.0", + "pid": "29377", + "root": "/" + } + } + ] + + + +Once you have identified the client you want to evict, you can +do that using its unique ID, or various other attributes to identify it: :: + + # These all work + ceph tell mds.0 client evict id=4305 + ceph tell mds.0 client evict client_metadata.=4305 + - # ceph osd blacklist add 172.16.79.251:0/3271 - blacklisting 172.16.79.251:0/3271 until 2014-12-09 13:09:56.569368 (3600 sec) +Advanced: Un-blacklisting a client +================================== -OSD epoch barrier ------------------ +Ordinarily, a blacklisted client may not reconnect to the servers: it +must be unmounted and then mounted anew. -While the evicted client is now marked as blacklisted in the central (mon) copy of the OSD -map, it is now necessary to ensure that this OSD map update has propagated to all daemons -involved in subsequent filesystem I/O. To do this, use the ``osdmap barrier`` MDS admin -socket command. +However, in some situations it may be useful to permit a client that +was evicted to attempt to reconnect. -First read the latest OSD epoch: +Because CephFS uses the RADOS OSD blacklist to control client eviction, +CephFS clients can be permitted to reconnect by removing them from +the blacklist: :: - # ceph osd dump - epoch 12 - fsid fd61ca96-53ff-4311-826c-f36b176d69ea - created 2014-12-09 12:03:38.595844 - modified 2014-12-09 12:09:56.619957 - ... + ceph osd blacklist ls + # ... identify the address of the client ... + ceph osd blacklist rm
-In this case it is 12. Now request the MDS to barrier on this epoch: +Doing this may put data integrity at risk if other clients have accessed +files that the blacklisted client was doing buffered IO to. It is also not +guaranteed to result in a fully functional client -- the best way to get +a fully healthy client back after an eviction is to unmount the client +and do a fresh mount. -:: +If you are trying to reconnect clients in this way, you may also +find it useful to set ``client_reconnect_stale`` to true in the +FUSE client, to prompt the client to try to reconnect. - # ceph daemon mds.a osdmap barrier 12 +Advanced: Configuring blacklisting +================================== -MDS session eviction --------------------- +If you are experiencing frequent client evictions, due to slow +client hosts or an unreliable network, and you cannot fix the underlying +issue, then you may want to ask the MDS to be less strict. -Finally, it is safe to evict the client's MDS session, such that any capabilities it held -may be issued to other clients. The ID here is the ``id`` attribute from the ``session ls`` -output: +It is possible to respond to slow clients by simply dropping their +MDS sessions, but permit them to re-open sessions and permit them +to continue talking to OSDs. To enable this mode, set +``mds_session_blacklist_on_timeout`` to false on your MDS nodes. -:: +For the equivalent behaviour on manual evictions, set +``mds_session_blacklist_on_evict`` to false. + +Note that if blacklisting is disabled, then evicting a client will +only have an effect on the MDS you send the command to. On a system +with multiple active MDS daemons, you would need to send an +eviction command to each active daemon. When blacklisting is enabled +(the default), sending an eviction to command to just a single +MDS is sufficient, because the blacklist propagates it to the others. + +Advanced options +================ + +``mds_blacklist_interval`` - this setting controls how many seconds +entries will remain in the blacklist for. - # ceph daemon mds.a session evict 4117 - -That's it! The client has now been evicted, and any resources it had locked will -now be available for other clients. - -Background: OSD epoch barrier ------------------------------ - -The purpose of the barrier is to ensure that when we hand out any -capabilities which might allow touching the same RADOS objects, the -clients we hand out the capabilities to must have a sufficiently recent -OSD map to not race with cancelled operations (from ENOSPC) or -blacklisted clients (from evictions) - -More specifically, the cases where we set an epoch barrier are: - - * Client eviction (where the client is blacklisted and other clients - must wait for a post-blacklist epoch to touch the same objects) - * OSD map full flag handling in the client (where the client may - cancel some OSD ops from a pre-full epoch, so other clients must - wait until the full epoch or later before touching the same objects). - * MDS startup, because we don't persist the barrier epoch, so must - assume that latest OSD map is always required after a restart. - -Note that this is a global value for simplicity: we could maintain this on -a per-inode basis. We don't, because: - - * It would be more complicated - * It would use an extra 4 bytes of memory for every inode - * It would not be much more efficient as almost always everyone has the latest - OSD map anyway, in most cases everyone will breeze through this barrier - rather than waiting. - * We only do this barrier in very rare cases, so any benefit from per-inode - granularity would only very rarely be seen. - -The epoch barrier is transmitted along with all capability messages, and -instructs the receiver of the message to avoid sending any more RADOS -operations to OSDs until it has seen this OSD epoch. This mainly applies -to clients (doing their data writes directly to files), but also applies -to the MDS because things like file size probing and file deletion are -done directly from the MDS. diff --git a/ceph/doc/cephfs/file-layouts.rst b/ceph/doc/cephfs/file-layouts.rst index a26801657..4124e1e06 100644 --- a/ceph/doc/cephfs/file-layouts.rst +++ b/ceph/doc/cephfs/file-layouts.rst @@ -34,6 +34,14 @@ stripe_count object_size Integer in bytes. File data is chunked into RADOS objects of this size. +.. tip:: + + RADOS enforces a configurable limit on object sizes: if you increase CephFS + object sizes beyond that limit then writes may not succeed. The OSD + setting is ``rados_max_object_size``, which is 128MB by default. + Very large RADOS objects may prevent smooth operation of the cluster, + so increasing the object size limit past the default is not recommended. + Reading layouts with ``getfattr`` --------------------------------- diff --git a/ceph/doc/cephfs/multimds.rst b/ceph/doc/cephfs/multimds.rst index 942a786d6..dd13d927c 100644 --- a/ceph/doc/cephfs/multimds.rst +++ b/ceph/doc/cephfs/multimds.rst @@ -122,6 +122,7 @@ extended attribute of directories. The name of this extended attribute is ``ceph.dir.pin``. Users can set this attribute using standard commands: :: + setfattr -n ceph.dir.pin -v 2 path/to/dir The value of the extended attribute is the rank to assign the directory subtree @@ -133,9 +134,11 @@ children. However, the parents pin can be overriden by setting the child directory's export pin. For example: :: + mkdir -p a/b # "a" and "a/b" both start without an export pin set setfattr -n ceph.dir.pin -v 1 a/ # a and b are now pinned to rank 1 setfattr -n ceph.dir.pin -v 0 a/b # a/b is now pinned to rank 0 and a/ and the rest of its children are still pinned to rank 1 + diff --git a/ceph/doc/dev/blkin.rst b/ceph/doc/dev/blkin.rst index 942720249..8e0320fe1 100644 --- a/ceph/doc/dev/blkin.rst +++ b/ceph/doc/dev/blkin.rst @@ -16,7 +16,7 @@ in realtime. The LTTng traces can then be visualized with Twitter's Zipkin_. .. _Dapper: http://static.googleusercontent.com/media/research.google.com/el//pubs/archive/36356.pdf -.. _Zipkin: http://twitter.github.io/zipkin/ +.. _Zipkin: http://zipkin.io/ Installing Blkin diff --git a/ceph/doc/dev/dev_cluster_deployement.rst b/ceph/doc/dev/dev_cluster_deployement.rst index 2f910750f..0e6244e04 100644 --- a/ceph/doc/dev/dev_cluster_deployement.rst +++ b/ceph/doc/dev/dev_cluster_deployement.rst @@ -45,10 +45,6 @@ Options Add *config* to all sections in the ceph configuration. -.. option:: -r - - Start radosgw on port starting from 8000. - .. option:: --nodaemon Use ceph-run as wrapper for mon/osd/mds. @@ -73,10 +69,6 @@ Options Launch the osd/mds/mon/all the ceph binaries using valgrind with the specified tool and arguments. -.. option:: --{mon,osd,mds}_num - - Set the count of mon/osd/mds daemons - .. option:: --bluestore Use bluestore as the objectstore backend for osds diff --git a/ceph/doc/dev/development-workflow.rst b/ceph/doc/dev/development-workflow.rst index 9374d8b69..9561899bf 100644 --- a/ceph/doc/dev/development-workflow.rst +++ b/ceph/doc/dev/development-workflow.rst @@ -55,7 +55,7 @@ Release Cycle Four times a year, the development roadmap is discussed online during -the `Ceph Developer Summit `_. A +the `Ceph Developer Summit `_. A new stable release (hammer, infernalis, jewel ...) is published at the same frequency. Every other release (firefly, hammer, jewel...) is a `Long Term Stable (LTS) <../../releases>`_. See `Understanding the release cycle @@ -126,7 +126,7 @@ Running and interpreting teuthology integration tests The :doc:`/dev/sepia` runs `teuthology `_ integration tests `on a regular basis `_ and the results are posted on `pulpito `_ and the -`ceph-qa mailing list `_. +`ceph-qa mailing list `_. * The job failures are `analyzed by quality engineers and developers `_ diff --git a/ceph/doc/dev/documenting.rst b/ceph/doc/dev/documenting.rst index afd6efa95..602f3c769 100644 --- a/ceph/doc/dev/documenting.rst +++ b/ceph/doc/dev/documenting.rst @@ -30,7 +30,7 @@ API`_ provides a complete example. It is pulled into Sphinx by `librados.rst`_, which is rendered at :doc:`/rados/api/librados`. .. _`librados C API`: https://github.com/ceph/ceph/blob/master/src/include/rados/librados.h -.. _`librados.rst`: https://raw.github.com/ceph/ceph/master/doc/api/librados.rst +.. _`librados.rst`: https://github.com/ceph/ceph/raw/master/doc/rados/api/librados.rst Drawing diagrams ================ diff --git a/ceph/doc/dev/index.rst b/ceph/doc/dev/index.rst index d3217b72d..abefa34a2 100644 --- a/ceph/doc/dev/index.rst +++ b/ceph/doc/dev/index.rst @@ -135,7 +135,7 @@ in the body of the message. There are also `other Ceph-related mailing lists`_. -.. _`other Ceph-related mailing lists`: https://ceph.com/resources/mailing-list-irc/ +.. _`other Ceph-related mailing lists`: https://ceph.com/irc/ IRC --- @@ -145,7 +145,7 @@ time using `Internet Relay Chat`_. .. _`Internet Relay Chat`: http://www.irchelp.org/ -See https://ceph.com/resources/mailing-list-irc/ for how to set up your IRC +See https://ceph.com/irc/ for how to set up your IRC client and a list of channels. Submitting patches @@ -750,7 +750,7 @@ The results of the nightlies are published at http://pulpito.ceph.com/ and http://pulpito.ovh.sepia.ceph.com:8081/. The developer nick shows in the test results URL and in the first column of the Pulpito dashboard. The results are also reported on the `ceph-qa mailing list -`_ for analysis. +`_ for analysis. Suites inventory ---------------- @@ -1132,11 +1132,14 @@ Reducing the number of tests ---------------------------- The ``rados`` suite generates thousands of tests out of a few hundred -files. For instance, all tests in the `rados/thrash suite -`_ -run for ``xfs``, ``btrfs`` and ``ext4`` because they are combined (via -special file ``%``) with the `fs directory -`_ +files. This happens because teuthology constructs test matrices from +subdirectories wherever it encounters a file named ``%``. For instance, +all tests in the `rados/basic suite +`_ +run with different messenger types: ``simple``, ``async`` and +``random``, because they are combined (via the special file ``%``) with +the `msgr directory +`_ All integration tests are required to be run before a Ceph release is published. When merely verifying whether a contribution can be merged without @@ -1199,9 +1202,9 @@ Getting ceph-workbench Since testing in the cloud is done using the `ceph-workbench ceph-qa-suite`_ tool, you will need to install that first. It is designed to be installed via Docker, so if you don't have Docker running on your -development machine, take care of that first. The Docker project has a good -tutorial called `Get Started with Docker Engine for Linux -`_ if you unsure how to proceed. +development machine, take care of that first. You can follow `the official +tutorial`_ to install if +you have not installed yet. Once Docker is up and running, install ``ceph-workbench`` by following the `Installation instructions in the ceph-workbench documentation @@ -1434,28 +1437,14 @@ Refer to :doc:`install/build-ceph`. You can do step 2 separately while it is building. -Step 2 - s3-tests ------------------ - -The test suite is in a separate git repo, and is written in python. Perform the -following steps for jewel:: - - git clone git://github.com/ceph/s3-tests - cd s3-tests - git checkout ceph-jewel - ./bootstrap - -For kraken, checkout the ``ceph-kraken`` branch instead of ``ceph-jewel``. For -master, use ``ceph-master``. - -Step 3 - vstart +Step 2 - vstart --------------- When the build completes, and still in the top-level directory of the git -clone where you built Ceph, do the following:: +clone where you built Ceph, do the following, for cmake builds:: - cd src/ - ./vstart.sh -n -r --mds_num 0 + cd build/ + RGW=1 ../vstart.sh -n This will produce a lot of output as the vstart cluster is started up. At the end you should see a message like:: @@ -1464,51 +1453,13 @@ end you should see a message like:: This means the cluster is running. -Step 4 - prepare S3 environment -------------------------------- - -The s3-tests suite expects to run in a particular environment (S3 users, keys, -configuration file). - -Before you try to prepare the environment, make sure you don't have any -existing keyring or ``ceph.conf`` files in ``/etc/ceph``. - -For jewel, Abhishek Lekshmanan wrote a script that can be used for this -purpose. Assuming you are testing jewel, run the following commands from the -``src/`` directory of your ceph clone (where you just started the vstart -cluster):: - - pushd ~ - wget https://gist.githubusercontent.com/theanalyst/2fee6bc2780f67c79cad7802040fcddc/raw/b497ddba053d9a6fb5d91b73924cbafcfc32f137/s3tests-bootstrap.sh - popd - sh ~/s3tests-bootstrap.sh -If the script is successful, it will display a blob of JSON and create a file -called ``s3.conf`` in the current directory. - -Step 5 - run s3-tests +Step 3 - run s3-tests --------------------- -To actually run the tests, take note of the full path to the ``s3.conf`` file -created in the previous step and then move to the directory where you cloned -``s3-tests`` in Step 2. - -First, verify that the test suite is there and can be run:: - - S3TEST_CONF=/path/to/s3.conf ./virtualenv/bin/nosetests -a '!fails_on_rgw' -v --collect-only - -This should complete quickly - it is like a "dry run" of all the tests in the -suite. - -Finally, run the test suite itself:: - - S3TEST_CONF=/path/to/s3.conf ./virtualenv/bin/nosetests -a '!fails_on_rgw' -v - -Note: the following test is expected to error - this is a problem in the test -setup (WIP), not an actual test failure:: - - ERROR: s3tests.functional.test_s3.test_bucket_acl_grant_email +To run the s3tests suite do the following:: + $ ../qa/workunits/rgw/run-s3tests.sh .. WIP .. === diff --git a/ceph/doc/dev/osd_internals/erasure_coding/developer_notes.rst b/ceph/doc/dev/osd_internals/erasure_coding/developer_notes.rst index cdab34ce4..a9ef9b55c 100644 --- a/ceph/doc/dev/osd_internals/erasure_coding/developer_notes.rst +++ b/ceph/doc/dev/osd_internals/erasure_coding/developer_notes.rst @@ -189,7 +189,7 @@ in the registry. The `ErasureCodePluginExample `_ reads: +object can be generated. The `ErasureCodePluginExample plugin `_ reads: :: diff --git a/ceph/doc/dev/perf_counters.rst b/ceph/doc/dev/perf_counters.rst index 11ecd20e9..398d51a00 100644 --- a/ceph/doc/dev/perf_counters.rst +++ b/ceph/doc/dev/perf_counters.rst @@ -39,89 +39,121 @@ The ``perf schema`` command dumps a json description of which values are availab +------+-------------------------------------+ | 2 | unsigned 64-bit integer value | +------+-------------------------------------+ -| 4 | average (sum + count pair) | +| 4 | average (sum + count pair), where | +------+-------------------------------------+ | 8 | counter (vs gauge) | +------+-------------------------------------+ -Every value will have either bit 1 or 2 set to indicate the type (float or integer). If bit 8 is set (counter), the reader may want to subtract off the previously read value to get the delta during the previous interval. +Every value will have either bit 1 or 2 set to indicate the type +(float or integer). -If bit 4 is set (average), there will be two values to read, a sum and a count. If it is a counter, the average for the previous interval would be sum delta (since the previous read) divided by the count delta. Alternatively, dividing the values outright would provide the lifetime average value. Normally these are used to measure latencies (number of requests and a sum of request latencies), and the average for the previous interval is what is interesting. +If bit 8 is set (counter), the value is monotonically increasing and +the reader may want to subtract off the previously read value to get +the delta during the previous interval. + +If bit 4 is set (average), there will be two values to read, a sum and +a count. If it is a counter, the average for the previous interval +would be sum delta (since the previous read) divided by the count +delta. Alternatively, dividing the values outright would provide the +lifetime average value. Normally these are used to measure latencies +(number of requests and a sum of request latencies), and the average +for the previous interval is what is interesting. + +Instead of interpreting the bit fields, the ``metric type`` has a +value of either ``guage`` or ``counter``, and the ``value type`` +property will be one of ``real``, ``integer``, ``real-integer-pair`` +(for a sum + real count pair), or ``integer-integer-pair`` (for a +sum + integer count pair). Here is an example of the schema output:: - { - "throttle-msgr_dispatch_throttler-hbserver" : { - "get_or_fail_fail" : { - "type" : 10 - }, - "get_sum" : { - "type" : 10 - }, - "max" : { - "type" : 10 - }, - "put" : { - "type" : 10 - }, - "val" : { - "type" : 10 - }, - "take" : { - "type" : 10 - }, - "get_or_fail_success" : { - "type" : 10 - }, - "wait" : { - "type" : 5 - }, - "get" : { - "type" : 10 - }, - "take_sum" : { - "type" : 10 - }, - "put_sum" : { - "type" : 10 - } - }, - "throttle-msgr_dispatch_throttler-client" : { - "get_or_fail_fail" : { - "type" : 10 - }, - "get_sum" : { - "type" : 10 - }, - "max" : { - "type" : 10 - }, - "put" : { - "type" : 10 - }, - "val" : { - "type" : 10 - }, - "take" : { - "type" : 10 - }, - "get_or_fail_success" : { - "type" : 10 - }, - "wait" : { - "type" : 5 - }, - "get" : { - "type" : 10 - }, - "take_sum" : { - "type" : 10 - }, - "put_sum" : { - "type" : 10 - } - } - } + { + "throttle-bluestore_throttle_bytes": { + "val": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "Currently available throttle", + "nick": "" + }, + "max": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "Max value for throttle", + "nick": "" + }, + "get_started": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Number of get calls, increased before wait", + "nick": "" + }, + "get": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Gets", + "nick": "" + }, + "get_sum": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Got data", + "nick": "" + }, + "get_or_fail_fail": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Get blocked during get_or_fail", + "nick": "" + }, + "get_or_fail_success": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Successful get during get_or_fail", + "nick": "" + }, + "take": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Takes", + "nick": "" + }, + "take_sum": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Taken data", + "nick": "" + }, + "put": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Puts", + "nick": "" + }, + "put_sum": { + "type": 10, + "metric_type": "counter", + "value_type": "integer", + "description": "Put data", + "nick": "" + }, + "wait": { + "type": 5, + "metric_type": "gauge", + "value_type": "real-integer-pair", + "description": "Waiting latency", + "nick": "" + } + } Dump diff --git a/ceph/doc/dev/perf_histograms.rst b/ceph/doc/dev/perf_histograms.rst new file mode 100644 index 000000000..a1f49644e --- /dev/null +++ b/ceph/doc/dev/perf_histograms.rst @@ -0,0 +1,677 @@ +================= + Perf histograms +================= + +The perf histograms build on perf counters infrastructure. Histograms are built for a number of counters and simplify gathering data on which groups of counter values occur most often over time. +Perf histograms are currently unsigned 64-bit integer counters, so they're mostly useful for time and sizes. Data dumped by perf histogram can then be feed into other analysis tools/scripts. + +Access +------ + +The perf histogram data are accessed via the admin socket. For example:: + + ceph daemon osd.0 perf histogram schema + ceph daemon osd.0 perf histogram dump + + +Collections +----------- + +The histograms are grouped into named collections, normally representing a subsystem or an instance of a subsystem. For example, the internal ``throttle`` mechanism reports statistics on how it is throttling, and each instance is named something like:: + + + op_r_latency_out_bytes_histogram + op_rw_latency_in_bytes_histogram + op_rw_latency_out_bytes_histogram + ... + + +Schema +------ + +The ``perf histogram schema`` command dumps a json description of which values are available, and what their type is. Each named value as a ``type`` bitfield, with the 5-th bit always set and following bits defined. + ++------+-------------------------------------+ +| bit | meaning | ++======+=====================================+ +| 1 | floating point value | ++------+-------------------------------------+ +| 2 | unsigned 64-bit integer value | ++------+-------------------------------------+ +| 4 | average (sum + count pair) | ++------+-------------------------------------+ +| 8 | counter (vs gauge) | ++------+-------------------------------------+ + +In other words, histogram of type "18" is a histogram of unsigned 64-bit integer values (16 + 2). + +Here is an example of the schema output:: + +{ + "AsyncMessenger::Worker-0": {}, + "AsyncMessenger::Worker-1": {}, + "AsyncMessenger::Worker-2": {}, + "mutex-WBThrottle::lock": {}, + "objecter": {}, + "osd": { + "op_r_latency_out_bytes_histogram": { + "type": 18, + "description": "Histogram of operation latency (including queue time) + data read", + "nick": "" + }, + "op_w_latency_in_bytes_histogram": { + "type": 18, + "description": "Histogram of operation latency (including queue time) + data written", + "nick": "" + }, + "op_rw_latency_in_bytes_histogram": { + "type": 18, + "description": "Histogram of rw operation latency (including queue time) + data written", + "nick": "" + }, + "op_rw_latency_out_bytes_histogram": { + "type": 18, + "description": "Histogram of rw operation latency (including queue time) + data read", + "nick": "" + } + } +} + + +Dump +---- + +The actual dump is similar to the schema, except that there are actual value groups. For example:: + + "osd": { + "op_r_latency_out_bytes_histogram": { + "axes": [ + { + "name": "Latency (usec)", + "min": 0, + "quant_size": 100000, + "buckets": 32, + "scale_type": "log2", + "ranges": [ + { + "max": -1 + }, + { + "min": 0, + "max": 99999 + }, + { + "min": 100000, + "max": 199999 + }, + { + "min": 200000, + "max": 399999 + }, + { + "min": 400000, + "max": 799999 + }, + { + "min": 800000, + "max": 1599999 + }, + { + "min": 1600000, + "max": 3199999 + }, + { + "min": 3200000, + "max": 6399999 + }, + { + "min": 6400000, + "max": 12799999 + }, + { + "min": 12800000, + "max": 25599999 + }, + { + "min": 25600000, + "max": 51199999 + }, + { + "min": 51200000, + "max": 102399999 + }, + { + "min": 102400000, + "max": 204799999 + }, + { + "min": 204800000, + "max": 409599999 + }, + { + "min": 409600000, + "max": 819199999 + }, + { + "min": 819200000, + "max": 1638399999 + }, + { + "min": 1638400000, + "max": 3276799999 + }, + { + "min": 3276800000, + "max": 6553599999 + }, + { + "min": 6553600000, + "max": 13107199999 + }, + { + "min": 13107200000, + "max": 26214399999 + }, + { + "min": 26214400000, + "max": 52428799999 + }, + { + "min": 52428800000, + "max": 104857599999 + }, + { + "min": 104857600000, + "max": 209715199999 + }, + { + "min": 209715200000, + "max": 419430399999 + }, + { + "min": 419430400000, + "max": 838860799999 + }, + { + "min": 838860800000, + "max": 1677721599999 + }, + { + "min": 1677721600000, + "max": 3355443199999 + }, + { + "min": 3355443200000, + "max": 6710886399999 + }, + { + "min": 6710886400000, + "max": 13421772799999 + }, + { + "min": 13421772800000, + "max": 26843545599999 + }, + { + "min": 26843545600000, + "max": 53687091199999 + }, + }, + { + "min": 53687091200000 + } + ] + }, + { + "name": "Request size (bytes)", + "min": 0, + "quant_size": 512, + "buckets": 32, + "scale_type": "log2", + "ranges": [ + { + "max": -1 + }, + { + "min": 0, + "max": 511 + }, + { + "min": 512, + "max": 1023 + }, + { + "min": 1024, + "max": 2047 + }, + { + "min": 2048, + "max": 4095 + }, + { + "min": 4096, + "max": 8191 + }, + { + "min": 8192, + "max": 16383 + }, + { + "min": 16384, + "max": 32767 + }, + { + "min": 32768, + "max": 65535 + }, + { + "min": 65536, + "max": 131071 + }, + { + "min": 131072, + "max": 262143 + }, + { + "min": 262144, + "max": 524287 + }, + { + "min": 524288, + "max": 1048575 + }, + { + "min": 1048576, + "max": 2097151 + }, + { + "min": 2097152, + "max": 4194303 + }, + { + "min": 4194304, + "max": 8388607 + }, + { + "min": 8388608, + "max": 16777215 + }, + { + "min": 16777216, + "max": 33554431 + }, + { + "min": 33554432, + "max": 67108863 + }, + { + "min": 67108864, + "max": 134217727 + }, + { + "min": 134217728, + "max": 268435455 + }, + { + "min": 268435456, + "max": 536870911 + }, + { + "min": 536870912, + "max": 1073741823 + }, + { + "min": 1073741824, + "max": 2147483647 + }, + { + "min": 2147483648, + "max": 4294967295 + }, + { + "min": 4294967296, + "max": 8589934591 + }, + { + "min": 8589934592, + "max": 17179869183 + }, + { + "min": 17179869184, + "max": 34359738367 + }, + { + "min": 34359738368, + "max": 68719476735 + }, + { + "min": 68719476736, + "max": 137438953471 + }, + { + "min": 137438953472, + "max": 274877906943 + }, + { + "min": 274877906944 + } + ] + } + ], + "values": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + ] + } + }, + +This represents the 2d histogram, consisting of 9 history entrires and 32 value groups per each history entry. +"Ranges" element denote value bounds for each of value groups. "Buckets" denote amount of value groups ("buckets"), +"Min" is a minimum accepted valaue, "quant_size" is quantization unit and "scale_type" is either "log2" (logarhitmic +scale) or "linear" (linear scale). +You can use histogram_dump.py tool (see src/tools/histogram_dump.py) for quick visualisation of existing histogram +data. diff --git a/ceph/doc/dev/placement-group.rst b/ceph/doc/dev/placement-group.rst index a544e99d9..3c067ea3f 100644 --- a/ceph/doc/dev/placement-group.rst +++ b/ceph/doc/dev/placement-group.rst @@ -45,12 +45,11 @@ is the primary and the rest are replicas. Many PGs can map to one OSD. A PG represents nothing but a grouping of objects; you configure the -number of PGs you want (see -http://ceph.com/wiki/Changing_the_number_of_PGs ), number of -OSDs * 100 is a good starting point, and all of your stored objects -are pseudo-randomly evenly distributed to the PGs. So a PG explicitly -does NOT represent a fixed amount of storage; it represents 1/pg_num -'th of the storage you happen to have on your OSDs. +number of PGs you want, number of OSDs * 100 is a good starting point +, and all of your stored objects are pseudo-randomly evenly distributed +to the PGs. So a PG explicitly does NOT represent a fixed amount of +storage; it represents 1/pg_num'th of the storage you happen to have +on your OSDs. Ignoring the finer points of CRUSH and custom placement, it goes something like this in pseudocode:: diff --git a/ceph/doc/dev/quick_guide.rst b/ceph/doc/dev/quick_guide.rst index 437893428..e7cf350dd 100644 --- a/ceph/doc/dev/quick_guide.rst +++ b/ceph/doc/dev/quick_guide.rst @@ -106,12 +106,13 @@ you might do something like this: Running a RadosGW development environment ----------------------------------------- -Add the ``-r`` to vstart.sh to enable the RadosGW + +Set the ``RGW`` environment variable when running vstart.sh to enable the RadosGW. .. code:: $ cd build - $ ../src/vstart.sh -d -n -x -r + $ RGW=1 ../src/vstart.sh -d -n -x You can now use the swift python client to communicate with the RadosGW. diff --git a/ceph/doc/install/build-ceph.rst b/ceph/doc/install/build-ceph.rst index cc61e0a8e..9c834b987 100644 --- a/ceph/doc/install/build-ceph.rst +++ b/ceph/doc/install/build-ceph.rst @@ -28,9 +28,8 @@ Ceph is built using cmake. To build Ceph, navigate to your cloned Ceph repository and execute the following:: cd ceph - mkdir build + ./do_cmake.sh cd build - cmake .. make .. topic:: Hyperthreading diff --git a/ceph/doc/install/get-packages.rst b/ceph/doc/install/get-packages.rst index 4e96c2b3f..02a24cd14 100644 --- a/ceph/doc/install/get-packages.rst +++ b/ceph/doc/install/get-packages.rst @@ -107,9 +107,7 @@ You may find releases for CentOS/RHEL and others (installed with YUM) at:: https://download.ceph.com/rpm-{release-name} -The major releases of Ceph are summarized at: - - http://docs.ceph.com/docs/master/releases/ +The major releases of Ceph are summarized at: :doc:`/releases`. Every second major release is considered Long Term Stable (LTS). Critical bugfixes are backported to LTS releases until their retirement. Since retired diff --git a/ceph/doc/install/index.rst b/ceph/doc/install/index.rst index 033d59745..d9dde72cf 100644 --- a/ceph/doc/install/index.rst +++ b/ceph/doc/install/index.rst @@ -21,7 +21,7 @@ repository and build Ceph yourself. Get Tarballs Clone Source Build Ceph - Ceph Mirrors + Ceph Mirrors Install Software @@ -38,7 +38,7 @@ QEMU. :maxdepth: 1 Install ceph-deploy - Install Ceph Storage Cluster + Install Ceph Storage Cluster Install Ceph Object Gateway Install Virtualization for Block @@ -52,7 +52,8 @@ deployment scripts with Chef, Juju, Puppet, etc. .. toctree:: - Manual Deployment + Manual Deployment + Manual Deployment on FreeBSD Upgrade Software ================ diff --git a/ceph/doc/install/manual-deployment.rst b/ceph/doc/install/manual-deployment.rst index cf14d4b83..e60c6beab 100644 --- a/ceph/doc/install/manual-deployment.rst +++ b/ceph/doc/install/manual-deployment.rst @@ -58,7 +58,7 @@ a number of things: For example, when you run multiple clusters in a `federated architecture`_, the cluster name (e.g., ``us-west``, ``us-east``) identifies the cluster for the current CLI session. **Note:** To identify the cluster name on the - command line interface, specify the a Ceph configuration file with the + command line interface, specify the Ceph configuration file with the cluster name (e.g., ``ceph.conf``, ``us-west.conf``, ``us-east.conf``, etc.). Also see CLI usage (``ceph --cluster {cluster-name}``). @@ -290,6 +290,12 @@ The procedure is as follows: **Note:** Once you add OSDs and start them, the placement group health errors should disappear. See the next section for details. +Manager daemon configuration +============================ + +On each node where you run a ceph-mon daemon, you should also set up a ceph-mgr daemon. + +See `../mgr/administrator`_ Adding OSDs =========== diff --git a/ceph/doc/install/manual-freebsd-deployment.rst b/ceph/doc/install/manual-freebsd-deployment.rst new file mode 100644 index 000000000..5be1651e3 --- /dev/null +++ b/ceph/doc/install/manual-freebsd-deployment.rst @@ -0,0 +1,624 @@ +============================== + Manual Deployment on FreeBSD +============================== + +This a largely a copy of the regular Manual Deployment with FreeBSD specifics. +The difference lies in two parts: The underlying diskformat, and the way to use +the tools. + +All Ceph clusters require at least one monitor, and at least as many OSDs as +copies of an object stored on the cluster. Bootstrapping the initial monitor(s) +is the first step in deploying a Ceph Storage Cluster. Monitor deployment also +sets important criteria for the entire cluster, such as the number of replicas +for pools, the number of placement groups per OSD, the heartbeat intervals, +whether authentication is required, etc. Most of these values are set by +default, so it's useful to know about them when setting up your cluster for +production. + +Following the same configuration as `Installation (Quick)`_, we will set up a +cluster with ``node1`` as the monitor node, and ``node2`` and ``node3`` for +OSD nodes. + + + +.. ditaa:: + /------------------\ /----------------\ + | Admin Node | | node1 | + | +-------->+ | + | | | cCCC | + \---------+--------/ \----------------/ + | + | /----------------\ + | | node2 | + +----------------->+ | + | | cCCC | + | \----------------/ + | + | /----------------\ + | | node3 | + +----------------->| | + | cCCC | + \----------------/ + + + +Disklayout on FreeBSD +===================== + +Current implementation works on ZFS pools + +* All Ceph data is created in /var/lib/ceph +* Log files go into /var/log/ceph +* PID files go into /var/log/run +* One ZFS pool is allocated per OSD, like:: + + gpart create -s GPT ada1 + gpart add -t freebsd-zfs -l osd1 ada1 + zpool create -o mountpoint=/var/lib/ceph/osd/osd.1 osd + +* Some cache and log (ZIL) can be attached. + Please note that this is different from the Ceph journals. Cache and log are + totally transparent for Ceph, and help the filesystem to keep the system + consistant and help performance. + Assuming that ada2 is an SSD:: + + gpart create -s GPT ada2 + gpart add -t freebsd-zfs -l osd1-log -s 1G ada2 + zpool add osd1 log gpt/osd1-log + gpart add -t freebsd-zfs -l osd1-cache -s 10G ada2 + zpool add osd1 log gpt/osd1-cache + +* Note: *UFS2 does not allow large xattribs* + + +Configuration +------------- + +As per FreeBSD default parts of extra software go into ``/usr/local/``. Which +means that for ``/etc/ceph.conf`` the default location is +``/usr/local/etc/ceph/ceph.conf``. Smartest thing to do is to create a softlink +from ``/etc/ceph`` to ``/usr/local/etc/ceph``:: + + ln -s /usr/local/etc/ceph /etc/ceph + +A sample file is provided in ``/usr/local/share/doc/ceph/sample.ceph.conf`` +Note that ``/usr/local/etc/ceph/ceph.conf`` will be found by most tools, +linking it to ``/etc/ceph/ceph.conf`` will help with any scripts that are found +in extra tools, scripts, and/or discussionlists. + +Monitor Bootstrapping +===================== + +Bootstrapping a monitor (a Ceph Storage Cluster, in theory) requires +a number of things: + +- **Unique Identifier:** The ``fsid`` is a unique identifier for the cluster, + and stands for File System ID from the days when the Ceph Storage Cluster was + principally for the Ceph Filesystem. Ceph now supports native interfaces, + block devices, and object storage gateway interfaces too, so ``fsid`` is a + bit of a misnomer. + +- **Cluster Name:** Ceph clusters have a cluster name, which is a simple string + without spaces. The default cluster name is ``ceph``, but you may specify + a different cluster name. Overriding the default cluster name is + especially useful when you are working with multiple clusters and you need to + clearly understand which cluster your are working with. + + For example, when you run multiple clusters in a `federated architecture`_, + the cluster name (e.g., ``us-west``, ``us-east``) identifies the cluster for + the current CLI session. **Note:** To identify the cluster name on the + command line interface, specify the a Ceph configuration file with the + cluster name (e.g., ``ceph.conf``, ``us-west.conf``, ``us-east.conf``, etc.). + Also see CLI usage (``ceph --cluster {cluster-name}``). + +- **Monitor Name:** Each monitor instance within a cluster has a unique name. + In common practice, the Ceph Monitor name is the host name (we recommend one + Ceph Monitor per host, and no commingling of Ceph OSD Daemons with + Ceph Monitors). You may retrieve the short hostname with ``hostname -s``. + +- **Monitor Map:** Bootstrapping the initial monitor(s) requires you to + generate a monitor map. The monitor map requires the ``fsid``, the cluster + name (or uses the default), and at least one host name and its IP address. + +- **Monitor Keyring**: Monitors communicate with each other via a + secret key. You must generate a keyring with a monitor secret and provide + it when bootstrapping the initial monitor(s). + +- **Administrator Keyring**: To use the ``ceph`` CLI tools, you must have + a ``client.admin`` user. So you must generate the admin user and keyring, + and you must also add the ``client.admin`` user to the monitor keyring. + +The foregoing requirements do not imply the creation of a Ceph Configuration +file. However, as a best practice, we recommend creating a Ceph configuration +file and populating it with the ``fsid``, the ``mon initial members`` and the +``mon host`` settings. + +You can get and set all of the monitor settings at runtime as well. However, +a Ceph Configuration file may contain only those settings that override the +default values. When you add settings to a Ceph configuration file, these +settings override the default settings. Maintaining those settings in a +Ceph configuration file makes it easier to maintain your cluster. + +The procedure is as follows: + + +#. Log in to the initial monitor node(s):: + + ssh {hostname} + + For example:: + + ssh node1 + + +#. Ensure you have a directory for the Ceph configuration file. By default, + Ceph uses ``/etc/ceph``. When you install ``ceph``, the installer will + create the ``/etc/ceph`` directory automatically. :: + + ls /etc/ceph + + **Note:** Deployment tools may remove this directory when purging a + cluster (e.g., ``ceph-deploy purgedata {node-name}``, ``ceph-deploy purge + {node-name}``). + +#. Create a Ceph configuration file. By default, Ceph uses + ``ceph.conf``, where ``ceph`` reflects the cluster name. :: + + sudo vim /etc/ceph/ceph.conf + + +#. Generate a unique ID (i.e., ``fsid``) for your cluster. :: + + uuidgen + + +#. Add the unique ID to your Ceph configuration file. :: + + fsid = {UUID} + + For example:: + + fsid = a7f64266-0894-4f1e-a635-d0aeaca0e993 + + +#. Add the initial monitor(s) to your Ceph configuration file. :: + + mon initial members = {hostname}[,{hostname}] + + For example:: + + mon initial members = node1 + + +#. Add the IP address(es) of the initial monitor(s) to your Ceph configuration + file and save the file. :: + + mon host = {ip-address}[,{ip-address}] + + For example:: + + mon host = 192.168.0.1 + + **Note:** You may use IPv6 addresses instead of IPv4 addresses, but + you must set ``ms bind ipv6`` to ``true``. See `Network Configuration + Reference`_ for details about network configuration. + +#. Create a keyring for your cluster and generate a monitor secret key. :: + + ceph-authtool --create-keyring /tmp/ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *' + + +#. Generate an administrator keyring, generate a ``client.admin`` user and add + the user to the keyring. :: + + sudo ceph-authtool --create-keyring /etc/ceph/ceph.client.admin.keyring --gen-key -n client.admin --set-uid=0 --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow' + + +#. Add the ``client.admin`` key to the ``ceph.mon.keyring``. :: + + ceph-authtool /tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring + + +#. Generate a monitor map using the hostname(s), host IP address(es) and the FSID. + Save it as ``/tmp/monmap``:: + + monmaptool --create --add {hostname} {ip-address} --fsid {uuid} /tmp/monmap + + For example:: + + monmaptool --create --add node1 192.168.0.1 --fsid a7f64266-0894-4f1e-a635-d0aeaca0e993 /tmp/monmap + + +#. Create a default data directory (or directories) on the monitor host(s). :: + + sudo mkdir /var/lib/ceph/mon/{cluster-name}-{hostname} + + For example:: + + sudo mkdir /var/lib/ceph/mon/ceph-node1 + + See `Monitor Config Reference - Data`_ for details. + +#. Populate the monitor daemon(s) with the monitor map and keyring. :: + + sudo -u ceph ceph-mon [--cluster {cluster-name}] --mkfs -i {hostname} --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring + + For example:: + + sudo -u ceph ceph-mon --mkfs -i node1 --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring + + +#. Consider settings for a Ceph configuration file. Common settings include + the following:: + + [global] + fsid = {cluster-id} + mon initial members = {hostname}[, {hostname}] + mon host = {ip-address}[, {ip-address}] + public network = {network}[, {network}] + cluster network = {network}[, {network}] + auth cluster required = cephx + auth service required = cephx + auth client required = cephx + osd journal size = {n} + osd pool default size = {n} # Write an object n times. + osd pool default min size = {n} # Allow writing n copy in a degraded state. + osd pool default pg num = {n} + osd pool default pgp num = {n} + osd crush chooseleaf type = {n} + + In the foregoing example, the ``[global]`` section of the configuration might + look like this:: + + [global] + fsid = a7f64266-0894-4f1e-a635-d0aeaca0e993 + mon initial members = node1 + mon host = 192.168.0.1 + public network = 192.168.0.0/24 + auth cluster required = cephx + auth service required = cephx + auth client required = cephx + osd journal size = 1024 + osd pool default size = 2 + osd pool default min size = 1 + osd pool default pg num = 333 + osd pool default pgp num = 333 + osd crush chooseleaf type = 1 + +#. Touch the ``done`` file. + + Mark that the monitor is created and ready to be started:: + + sudo touch /var/lib/ceph/mon/ceph-node1/done + +#. And for FreeBSD an entry for every monitor needs to be added to the config + file. (The requirement will be removed in future releases). + + The entry should look like:: + + [mon] + [mon.node1] + host = node1 # this name can be resolve + + +#. Start the monitor(s). + + For Ubuntu, use Upstart:: + + sudo start ceph-mon id=node1 [cluster={cluster-name}] + + In this case, to allow the start of the daemon at each reboot you + must create two empty files like this:: + + sudo touch /var/lib/ceph/mon/{cluster-name}-{hostname}/upstart + + For example:: + + sudo touch /var/lib/ceph/mon/ceph-node1/upstart + + For Debian/CentOS/RHEL, use sysvinit:: + + sudo /etc/init.d/ceph start mon.node1 + + For FreeBSD we use the rc.d init scripts (called bsdrc in Ceph):: + + sudo service ceph start start mon.node1 + + For this to work /etc/rc.conf also needs the entry to enable ceph:: + cat 'ceph_enable="YES"' >> /etc/rc.conf + + +#. Verify that Ceph created the default pools. :: + + ceph osd lspools + + You should see output like this:: + + 0 data,1 metadata,2 rbd, + + +#. Verify that the monitor is running. :: + + ceph -s + + You should see output that the monitor you started is up and running, and + you should see a health error indicating that placement groups are stuck + inactive. It should look something like this:: + + cluster a7f64266-0894-4f1e-a635-d0aeaca0e993 + health HEALTH_ERR 192 pgs stuck inactive; 192 pgs stuck unclean; no osds + monmap e1: 1 mons at {node1=192.168.0.1:6789/0}, election epoch 1, quorum 0 node1 + osdmap e1: 0 osds: 0 up, 0 in + pgmap v2: 192 pgs, 3 pools, 0 bytes data, 0 objects + 0 kB used, 0 kB / 0 kB avail + 192 creating + + **Note:** Once you add OSDs and start them, the placement group health errors + should disappear. See the next section for details. + + +Adding OSDs +=========== + +Once you have your initial monitor(s) running, you should add OSDs. Your cluster +cannot reach an ``active + clean`` state until you have enough OSDs to handle the +number of copies of an object (e.g., ``osd pool default size = 2`` requires at +least two OSDs). After bootstrapping your monitor, your cluster has a default +CRUSH map; however, the CRUSH map doesn't have any Ceph OSD Daemons mapped to +a Ceph Node. + + +Short Form +---------- + +Ceph provides the ``ceph-disk`` utility, which can prepare a disk, partition or +directory for use with Ceph. The ``ceph-disk`` utility creates the OSD ID by +incrementing the index. Additionally, ``ceph-disk`` will add the new OSD to the +CRUSH map under the host for you. Execute ``ceph-disk -h`` for CLI details. +The ``ceph-disk`` utility automates the steps of the `Long Form`_ below. To +create the first two OSDs with the short form procedure, execute the following +on ``node2`` and ``node3``: + + +#. Prepare the OSD. :: + + On FreeBSD only existing directories can be use to create OSDs in:: + + + ssh {node-name} + sudo ceph-disk prepare --cluster {cluster-name} --cluster-uuid {uuid} {path-to-ceph-osd-directory} + + For example:: + + ssh node1 + sudo ceph-disk prepare --cluster ceph --cluster-uuid a7f64266-0894-4f1e-a635-d0aeaca0e993 /var/lib/ceph/osd/osd.1 + + +#. Activate the OSD:: + + sudo ceph-disk activate {data-path} [--activate-key {path}] + + For example:: + + sudo ceph-disk activate /var/lib/ceph/osd/osd.1 + + **Note:** Use the ``--activate-key`` argument if you do not have a copy + of ``/var/lib/ceph/bootstrap-osd/{cluster}.keyring`` on the Ceph Node. + + FreeBSD does not auto start the OSDs, but also requires a entry in + ``ceph.conf``. One for each OSD:: + + [osd] + [osd.1] + host = node1 # this name can be resolve + + +Long Form +--------- + +Without the benefit of any helper utilities, create an OSD and add it to the +cluster and CRUSH map with the following procedure. To create the first two +OSDs with the long form procedure, execute the following on ``node2`` and +``node3``: + +#. Connect to the OSD host. :: + + ssh {node-name} + +#. Generate a UUID for the OSD. :: + + uuidgen + + +#. Create the OSD. If no UUID is given, it will be set automatically when the + OSD starts up. The following command will output the OSD number, which you + will need for subsequent steps. :: + + ceph osd create [{uuid} [{id}]] + + +#. Create the default directory on your new OSD. :: + + ssh {new-osd-host} + sudo mkdir /var/lib/ceph/osd/{cluster-name}-{osd-number} + + Above are the ZFS instructions to do this for FreeBSD. + + +#. If the OSD is for a drive other than the OS drive, prepare it + for use with Ceph, and mount it to the directory you just created. + + +#. Initialize the OSD data directory. :: + + ssh {new-osd-host} + sudo ceph-osd -i {osd-num} --mkfs --mkkey --osd-uuid [{uuid}] + + The directory must be empty before you can run ``ceph-osd`` with the + ``--mkkey`` option. In addition, the ceph-osd tool requires specification + of custom cluster names with the ``--cluster`` option. + + +#. Register the OSD authentication key. The value of ``ceph`` for + ``ceph-{osd-num}`` in the path is the ``$cluster-$id``. If your + cluster name differs from ``ceph``, use your cluster name instead.:: + + sudo ceph auth add osd.{osd-num} osd 'allow *' mon 'allow profile osd' -i /var/lib/ceph/osd/{cluster-name}-{osd-num}/keyring + + +#. Add your Ceph Node to the CRUSH map. :: + + ceph [--cluster {cluster-name}] osd crush add-bucket {hostname} host + + For example:: + + ceph osd crush add-bucket node1 host + + +#. Place the Ceph Node under the root ``default``. :: + + ceph osd crush move node1 root=default + + +#. Add the OSD to the CRUSH map so that it can begin receiving data. You may + also decompile the CRUSH map, add the OSD to the device list, add the host as a + bucket (if it's not already in the CRUSH map), add the device as an item in the + host, assign it a weight, recompile it and set it. :: + + ceph [--cluster {cluster-name}] osd crush add {id-or-name} {weight} [{bucket-type}={bucket-name} ...] + + For example:: + + ceph osd crush add osd.0 1.0 host=node1 + + +#. After you add an OSD to Ceph, the OSD is in your configuration. However, + it is not yet running. The OSD is ``down`` and ``in``. You must start + your new OSD before it can begin receiving data. + + For Ubuntu, use Upstart:: + + sudo start ceph-osd id={osd-num} [cluster={cluster-name}] + + For example:: + + sudo start ceph-osd id=0 + sudo start ceph-osd id=1 + + For Debian/CentOS/RHEL, use sysvinit:: + + sudo /etc/init.d/ceph start osd.{osd-num} [--cluster {cluster-name}] + + For example:: + + sudo /etc/init.d/ceph start osd.0 + sudo /etc/init.d/ceph start osd.1 + + In this case, to allow the start of the daemon at each reboot you + must create an empty file like this:: + + sudo touch /var/lib/ceph/osd/{cluster-name}-{osd-num}/sysvinit + + For example:: + + sudo touch /var/lib/ceph/osd/ceph-0/sysvinit + sudo touch /var/lib/ceph/osd/ceph-1/sysvinit + + Once you start your OSD, it is ``up`` and ``in``. + + For FreeBSD using rc.d init:: + + After adding the OSD to ``ceph.conf`` + + sudo service ceph start osd.{osd-num} + + For example:: + + sudo service ceph start osd.0 + sudo service ceph start osd.1 + + In this case, to allow the start of the daemon at each reboot you + must create an empty file like this:: + + sudo touch /var/lib/ceph/osd/{cluster-name}-{osd-num}/bsdrc + + For example:: + + sudo touch /var/lib/ceph/osd/ceph-0/bsdrc + sudo touch /var/lib/ceph/osd/ceph-1/bsdrc + + Once you start your OSD, it is ``up`` and ``in``. + + + +Adding MDS +========== + +In the below instructions, ``{id}`` is an arbitrary name, such as the hostname of the machine. + +#. Create the mds data directory.:: + + mkdir -p /var/lib/ceph/mds/{cluster-name}-{id} + +#. Create a keyring.:: + + ceph-authtool --create-keyring /var/lib/ceph/mds/{cluster-name}-{id}/keyring --gen-key -n mds.{id} + +#. Import the keyring and set caps.:: + + ceph auth add mds.{id} osd "allow rwx" mds "allow" mon "allow profile mds" -i /var/lib/ceph/mds/{cluster}-{id}/keyring + +#. Add to ceph.conf.:: + + [mds.{id}] + host = {id} + +#. Start the daemon the manual way.:: + + ceph-mds --cluster {cluster-name} -i {id} -m {mon-hostname}:{mon-port} [-f] + +#. Start the daemon the right way (using ceph.conf entry).:: + + service ceph start + +#. If starting the daemon fails with this error:: + + mds.-1.0 ERROR: failed to authenticate: (22) Invalid argument + + Then make sure you do not have a keyring set in ceph.conf in the global section; move it to the client section; or add a keyring setting specific to this mds daemon. And verify that you see the same key in the mds data directory and ``ceph auth get mds.{id}`` output. + +#. Now you are ready to `create a Ceph filesystem`_. + + +Summary +======= + +Once you have your monitor and two OSDs up and running, you can watch the +placement groups peer by executing the following:: + + ceph -w + +To view the tree, execute the following:: + + ceph osd tree + +You should see output that looks something like this:: + + # id weight type name up/down reweight + -1 2 root default + -2 2 host node1 + 0 1 osd.0 up 1 + -3 1 host node2 + 1 1 osd.1 up 1 + +To add (or remove) additional monitors, see `Add/Remove Monitors`_. +To add (or remove) additional Ceph OSD Daemons, see `Add/Remove OSDs`_. + + +.. _federated architecture: ../../radosgw/federated-config +.. _Installation (Quick): ../../start +.. _Add/Remove Monitors: ../../rados/operations/add-or-rm-mons +.. _Add/Remove OSDs: ../../rados/operations/add-or-rm-osds +.. _Network Configuration Reference: ../../rados/configuration/network-config-ref +.. _Monitor Config Reference - Data: ../../rados/configuration/mon-config-ref#data +.. _create a Ceph filesystem: ../../cephfs/createfs diff --git a/ceph/doc/install/mirrors.rst b/ceph/doc/install/mirrors.rst index 5810571d5..49742d12a 100644 --- a/ceph/doc/install/mirrors.rst +++ b/ceph/doc/install/mirrors.rst @@ -24,6 +24,7 @@ These mirrors are available on the following locations: - **UK: UK**: http://uk.ceph.com - **US-East: US East Coast**: http://us-east.ceph.com/ - **US-West: US West Coast**: http://us-west.ceph.com/ +- **CN: China**: http://cn.ceph.com/ You can replace all download.ceph.com URLs with any of the mirrors, for example: diff --git a/ceph/doc/man/8/ceph-detect-init.rst b/ceph/doc/man/8/ceph-detect-init.rst index aeb3316e5..c409a949d 100644 --- a/ceph/doc/man/8/ceph-detect-init.rst +++ b/ceph/doc/man/8/ceph-detect-init.rst @@ -41,6 +41,17 @@ Options Display additional information for debugging. +Bugs +==== + +:program:`ceph-detect-init` is used by :program:`ceph-disk` to figure out the init system to manage the mount directory of an OSD. But only following combinations are fully tested: + +- `upstart` on `Ubuntu 14.04` +- `systemd` on `Ubuntu 15.04` and up +- `systemd` on `Debian 8` and up +- `systemd` on `RHEL/CentOS 7` and up +- `systemd` on `Fedora 22` and up + Availability ============ diff --git a/ceph/doc/man/8/ceph-disk.rst b/ceph/doc/man/8/ceph-disk.rst index ed938b8b5..4635937a4 100644 --- a/ceph/doc/man/8/ceph-disk.rst +++ b/ceph/doc/man/8/ceph-disk.rst @@ -78,6 +78,11 @@ the subcommands ``deactivate`` and ``destroy``. The documentation for each subcommand (prepare, activate, etc.) can be displayed with its ``--help`` option. For instance ``ceph-disk prepare --help``. +Bugs +==== + +See also the ``Bugs`` section in :doc:`ceph-detect-init `\(8). + Availability ============ @@ -87,5 +92,6 @@ the Ceph documentation at http://ceph.com/docs for more information. See also ======== +:doc:`ceph-detect-init `\(8) :doc:`ceph-osd `\(8), :doc:`ceph-deploy `\(8) diff --git a/ceph/doc/man/8/ceph-osd.rst b/ceph/doc/man/8/ceph-osd.rst index e8b2805b1..3b89740fc 100644 --- a/ceph/doc/man/8/ceph-osd.rst +++ b/ceph/doc/man/8/ceph-osd.rst @@ -10,7 +10,7 @@ Synopsis ======== | **ceph-osd** -i *osdnum* [ --osd-data *datapath* ] [ --osd-journal - *journal* ] [ --mkfs ] [ --mkjournal ] [ --mkkey ] + *journal* ] [ --mkfs ] [ --mkjournal ] [--flush-journal] [--check-allows-journal] [--check-wants-journal] [--check-needs-journal] [ --mkkey ] Description @@ -57,6 +57,18 @@ Options Journal updates to *journal*. +.. option:: --check-wants-journal + + Check whether a journal is desired. + +.. option:: --check-allows-journal + + Check whether a journal is allowed. + +.. option:: --check-needs-journal + + Check whether a journal is required. + .. option:: --mkfs Create an empty object repository. This also initializes the journal diff --git a/ceph/doc/man/8/ceph.rst b/ceph/doc/man/8/ceph.rst index ba3ccdfe2..fa3d126fb 100644 --- a/ceph/doc/man/8/ceph.rst +++ b/ceph/doc/man/8/ceph.rst @@ -39,7 +39,7 @@ Synopsis | **ceph** **mon_status** -| **ceph** **osd** [ *blacklist* \| *blocked-by* \| *create* \| *deep-scrub* \| *df* \| *down* \| *dump* \| *erasure-code-profile* \| *find* \| *getcrushmap* \| *getmap* \| *getmaxosd* \| *in* \| *lspools* \| *map* \| *metadata* \| *out* \| *pause* \| *perf* \| *pg-temp* \| *primary-affinity* \| *primary-temp* \| *repair* \| *reweight* \| *reweight-by-pg* \| *rm* \| *scrub* \| *set* \| *setcrushmap* \| *setmaxosd* \| *stat* \| *tree* \| *unpause* \| *unset* ] ... +| **ceph** **osd** [ *blacklist* \| *blocked-by* \| *create* \| *new* \| *deep-scrub* \| *df* \| *down* \| *dump* \| *erasure-code-profile* \| *find* \| *getcrushmap* \| *getmap* \| *getmaxosd* \| *in* \| *lspools* \| *map* \| *metadata* \| *out* \| *pause* \| *perf* \| *pg-temp* \| *primary-affinity* \| *primary-temp* \| *repair* \| *reweight* \| *reweight-by-pg* \| *rm* \| *destroy* \| *purge* \| *scrub* \| *set* \| *setcrushmap* \| *setmaxosd* \| *stat* \| *tree* \| *unpause* \| *unset* ] ... | **ceph** **osd** **crush** [ *add* \| *add-bucket* \| *create-or-move* \| *dump* \| *get-tunable* \| *link* \| *move* \| *remove* \| *rename-bucket* \| *reweight* \| *reweight-all* \| *reweight-subtree* \| *rm* \| *rule* \| *set* \| *set-tunable* \| *show-tunables* \| *tunables* \| *unlink* ] ... @@ -478,10 +478,40 @@ Usage:: Subcommand ``create`` creates new osd (with optional UUID and ID). +This command is DEPRECATED as of the Luminous release, and will be removed in +a future release. + +Subcommand ``new`` should instead be used. + Usage:: ceph osd create {} {} +Subcommand ``new`` reuses a previously destroyed OSD *id*. The new OSD will +have the specified *uuid*, and the command expects a JSON file containing +the base64 cephx key for auth entity *client.osd.*, as well as optional +base64 cepx key for dm-crypt lockbox access and a dm-crypt key. Specifying +a dm-crypt requires specifying the accompanying lockbox cephx key. + +Usage:: + + ceph osd new {} {} -i {} + +The secrets JSON file is expected to maintain a form of the following format:: + + { + "cephx_secret": "AQBWtwhZdBO5ExAAIDyjK2Bh16ZXylmzgYYEjg==" + } + +Or:: + + { + "cephx_secret": "AQBWtwhZdBO5ExAAIDyjK2Bh16ZXylmzgYYEjg==", + "cephx_lockbox_secret": "AQDNCglZuaeVCRAAYr76PzR1Anh7A0jswkODIQ==", + "dmcrypt_key": "" + } + + Subcommand ``crush`` is used for CRUSH management. It uses some additional subcommands. @@ -938,6 +968,29 @@ Usage:: ceph osd rm [...] +Subcommand ``destroy`` marks OSD *id* as *destroyed*, removing its cephx +entity's keys and all of its dm-crypt and daemon-private config key +entries. + +This command will not remove the OSD from crush, nor will it remove the +OSD from the OSD map. Instead, once the command successfully completes, +the OSD will show marked as *destroyed*. + +In order to mark an OSD as destroyed, the OSD must first be marked as +**lost**. + +Usage:: + + ceph osd destroy {--yes-i-really-mean-it} + + +Subcommand ``purge`` performs a combination of ``osd destroy``, +``osd rm`` and ``osd crush remove``. + +Usage:: + + ceph osd purge {--yes-i-really-mean-it} + Subcommand ``scrub`` initiates scrub on specified osd. Usage:: @@ -1265,6 +1318,13 @@ Usage:: ceph tell [...] + +List all available commands. + +Usage:: + + ceph tell help + version ------- diff --git a/ceph/doc/man/8/rados.rst b/ceph/doc/man/8/rados.rst index e6aaf7356..90668706c 100644 --- a/ceph/doc/man/8/rados.rst +++ b/ceph/doc/man/8/rados.rst @@ -138,6 +138,18 @@ Pool specific commands :command:`cleanup` +:command:`listxattr` *name* + List all extended attributes of an object. + +:command:`getxattr` *name* *attr* + Dump the extended attribute value of *attr* of an object. + +:command:`setxattr` *name* *attr* *value* + Set the value of *attr* in the extended attributes of an object. + +:command:`rmxattr` *name* *attr* + Remove *attr* from the extended attributes of an object. + :command:`listomapkeys` *name* List all the keys stored in the object map of object name. diff --git a/ceph/doc/mgr/administrator.rst b/ceph/doc/mgr/administrator.rst index 8db733c1c..e636c80ed 100644 --- a/ceph/doc/mgr/administrator.rst +++ b/ceph/doc/mgr/administrator.rst @@ -2,12 +2,16 @@ ceph-mgr administrator's guide ============================== -Setup ------ +Manual setup +------------ -Create an authentication key for your daemon:: +Usually, you would set up a ceph-mgr daemon using a tool such +as ceph-ansible. These instructions describe how to set up +a ceph-mgr daemon manually. - ceph auth get-or-create mgr.$name mon 'allow *' +First, create an authentication key for your daemon:: + + ceph auth get-or-create mgr.$name mon 'allow profile mgr' osd 'allow *' mds 'allow *' Place that key into ``mgr data`` path, which for a cluster "ceph" and mgr $name "foo" would be ``/var/lib/ceph/mgr/ceph-foo``. @@ -21,6 +25,15 @@ of ``ceph status``, which should now include a mgr status line:: mgr active: $name +Client authentication +--------------------- +The manager is a new daemon which requires new CephX capabilities. If you upgrade +a cluster from an old version of Ceph, or use the default install/deploy tools, +your admin client should get this capability automatically. If you use tooling from +elsewhere, you may get EACCES errors when invoking certain ceph cluster commands. +To fix that, add a "mgr allow *" stanza to your client's cephx capabilities by +`Modifying User Capabilities`_. + High availability ----------------- @@ -75,9 +88,10 @@ OPTION(mgr_module_path, OPT_STR, CEPH_PKGLIBDIR "/mgr") // where to load python :Type: String :Default: ``"/var/lib/ceph/mgr/$cluster-$id"`` -``mgr beacon period`` +``mgr tick period`` -:Description: How many seconds between mgr beacons to monitors +:Description: How many seconds between mgr beacons to monitors, and other + periodic checks. :Type: Integer :Default: ``5`` @@ -87,3 +101,4 @@ OPTION(mgr_module_path, OPT_STR, CEPH_PKGLIBDIR "/mgr") // where to load python :Type: Integer :Default: ``30`` +.. _Modifying User Capabilities: ../rados/operations/user-management#modify-user-capabilities diff --git a/ceph/doc/mgr/dashboard.rst b/ceph/doc/mgr/dashboard.rst new file mode 100644 index 000000000..7f837f26d --- /dev/null +++ b/ceph/doc/mgr/dashboard.rst @@ -0,0 +1,15 @@ +dashboard plugin +================ + +Dashboard plugin visualizes the statistics of the cluster using a web server +hosted by ``ceph-mgr``. Like most web applications, dashboard binds to a host +name and port. Since each ``ceph-mgr`` hosts its own instance of dashboard, we +need to configure them separately. The hostname and port are stored using the +configuration key facility. So we can configure them like:: + + ceph config-key put mgr/dashboard/$name/server_addr $IP + ceph config-key put mgr/dashboard/$name/server_port $PORT + +where ``$name`` is the ID of the ceph-mgr who is hosting this dashboard web app. +If they are not configured, the web app will be bound to ``127.0.0.1:7000``. + diff --git a/ceph/doc/mgr/index.rst b/ceph/doc/mgr/index.rst index 965a8b020..38bdec153 100644 --- a/ceph/doc/mgr/index.rst +++ b/ceph/doc/mgr/index.rst @@ -8,9 +8,25 @@ The :term:`Ceph Manager` daemon (ceph-mgr) runs alongside monitor daemons, to provide additional monitoring and interfaces to external monitoring and management systems. +Since the 12.x (*luminous*) Ceph release, the ceph-mgr daemon is required for +normal operations. The ceph-mgr daemon is an optional component in +the 11.x (*kraken*) Ceph release. + +By default, the manager daemon requires no additional configuration, beyond +ensuring it is running. If there is no mgr daemon running, you will +see a health warning to that effect, and some of the other information +in the output of `ceph status` will be missing or stale until a mgr is started. + +Use your normal deployment tools, such as ceph-ansible or ceph-deploy, to +set up ceph-mgr daemons on each of your mon nodes. It is not mandatory +to place mgr daemons on the same nodes as mons, but it is almost always +sensible. + .. toctree:: :maxdepth: 1 Installation and Configuration + Dashboard + RESTful Writing plugins diff --git a/ceph/doc/mgr/restful.rst b/ceph/doc/mgr/restful.rst new file mode 100644 index 000000000..846c98840 --- /dev/null +++ b/ceph/doc/mgr/restful.rst @@ -0,0 +1,25 @@ +restful plugin +============== + +RESTful plugin offers the REST API access to the status of the cluster. RESTful +plugin enables you to secure the API endpoints via SSL. If you don't have a +security certificate and key already, you need to create them first:: + + openssl req -new -nodes -x509 \ + -subj "/O=IT/CN=ceph-mgr-restful" \ + -days 3650 -keyout $PKEY -out $CERT -extensions v3_ca + +where ``$PKEY`` and ``$CERT`` are the paths to the private key and the +certificate. And then you need to import the keystore to the cluster using the +configuration key facility, so RESTful plugin can read them at startup:: + + ceph config-key put mgr/restful/$name/crt -i $CERT + ceph config-key put mgr/restful/$name/key -i $PKEY + +Also, like other web applications, RESTful plugin is bound to the a hostname and +a port:: + + ceph config-key put mgr/restful/$name/server_addr $IP + ceph config-key put mgr/restful/$name/server_port $PORT + +If not specified, the plugin uses ``127.0.0.1:8003`` by default. diff --git a/ceph/doc/rados/configuration/filestore-config-ref.rst b/ceph/doc/rados/configuration/filestore-config-ref.rst index 16ac7c05d..6b351f0bf 100644 --- a/ceph/doc/rados/configuration/filestore-config-ref.rst +++ b/ceph/doc/rados/configuration/filestore-config-ref.rst @@ -192,7 +192,7 @@ The following settings provide limits on the size of filestore queue. :Description: Defines the maximum number of in progress operations the file store accepts before blocking on queuing new operations. :Type: Integer :Required: No. Minimal impact on performance. -:Default: ``500`` +:Default: ``50`` ``filestore queue max bytes`` @@ -203,20 +203,6 @@ The following settings provide limits on the size of filestore queue. :Default: ``100 << 20`` -``filestore queue committing max ops`` - -:Description: The maximum number of operations the filestore can commit. -:Type: Integer -:Required: No -:Default: ``500`` - - -``filestore queue committing max bytes`` - -:Description: The maximum number of bytes the filestore can commit. -:Type: Integer -:Required: No -:Default: ``100 << 20`` .. index:: filestore; timeouts diff --git a/ceph/doc/rados/configuration/mon-config-ref.rst b/ceph/doc/rados/configuration/mon-config-ref.rst index b19461f7a..984354791 100644 --- a/ceph/doc/rados/configuration/mon-config-ref.rst +++ b/ceph/doc/rados/configuration/mon-config-ref.rst @@ -106,6 +106,11 @@ A consensus requires a majority of monitors running to establish a quorum for consensus about the cluster map (e.g., 1; 2 out of 3; 3 out of 5; 4 out of 6; etc.). +``mon force quorum join`` + +:Description: Force monitor to join quorum even if it has been previously removed from the map +:Type: Boolean +:Default: ``False`` .. index:: Ceph Monitor; consistency @@ -314,6 +319,126 @@ by setting it in the ``[mon]`` section of the configuration file. :Default: ``/var/lib/ceph/mon/$cluster-$id`` +``mon data size warn`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log when the monitor's data + store goes over 15GB. +:Type: Integer +:Default: 15*1024*1024*1024* + + +``mon data avail warn`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log when the available disk + space of monitor's data store is lower or equal to this + percentage. +:Type: Integer +:Default: 30 + + +``mon data avail crit`` + +:Description: Issue a ``HEALTH_ERR`` in cluster log when the available disk + space of monitor's data store is lower or equal to this + percentage. +:Type: Integer +:Default: 5 + + +``mon warn on cache pools without hit sets`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if a cache pool does not + have the hitset type set set. + See `hit set type <../operations/pools#hit-set-type>`_ for more + details. +:Type: Boolean +:Default: True + + +``mon warn on crush straw calc version zero`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if the CRUSH's + ``straw_calc_version`` is zero. See + `CRUSH map tunables <../operations/crush-map#tunables>`_ for + details. +:Type: Boolean +:Default: True + + +``mon warn on legacy crush tunables`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if + CRUSH tunables are too old (older than ``mon_min_crush_required_version``) +:Type: Boolean +:Default: True + + +``mon crush min required version`` + +:Description: The minimum tunable profile version required by the cluster. + See + `CRUSH map tunables <../operations/crush-map#tunables>`_ for + details. +:Type: String +:Default: ``firefly`` + + +``mon warn on osd down out interval zero`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if + ``mon osd down out interval`` is zero. Having this option set to + zero on the leader acts much like the ``noout`` flag. It's hard + to figure out what's going wrong with clusters witout the + ``noout`` flag set but acting like that just the same, so we + report a warning in this case. +:Type: Boolean +:Default: True + + +``mon cache target full warn ratio`` + +:Description: Position between pool's ``cache_target_full`` and + ``target_max_object`` where we start warning +:Type: Float +:Default: ``0.66`` + + +``mon health data update interval`` + +:Description: How often (in seconds) the monitor in quorum shares its health + status with its peers. (negative number disables it) +:Type: Float +:Default: ``60`` + + +``mon health to clog`` + +:Description: Enable sending health summary to cluster log periodically. +:Type: Boolean +:Default: True + + +``mon health to clog tick interval`` + +:Description: How often (in seconds) the monitor send health summary to cluster + log (a non-positive number disables it). If current health summary + is empty or identical to the last time, monitor will not send it + to cluster log. +:Type: Integer +:Default: 3600 + + +``mon health to clog interval`` + +:Description: How often (in seconds) the monitor send health summary to cluster + log (a non-positive number disables it). Monitor will always + send the summary to cluster log no matter if the summary changes + or not. +:Type: Integer +:Default: 60 + + + .. index:: Ceph Storage Cluster; capacity planning, Ceph Monitor; capacity planning Storage Capacity @@ -546,7 +671,9 @@ Trimming requires that the placement groups are ``active + clean``. ``mon sync timeout`` -:Description: +:Description: Number of seconds the monitor will wait for the next update + message from its sync provider before it gives up and bootstrap + again. :Type: Double :Default: ``30.0`` @@ -560,39 +687,123 @@ Trimming requires that the placement groups are ``active + clean``. ``mon sync max payload size`` -:Description: The maximum size for a sync payload. +:Description: The maximum size for a sync payload (in bytes). :Type: 32-bit Integer :Default: ``1045676`` -``mon accept timeout`` +``paxos max join drift`` -:Description: Number of seconds the Leader will wait for the Requester(s) to - accept a Paxos update. It is also used during the Paxos recovery - phase for similar purposes. +:Description: The maximum Paxos iterations before we must first sync the + monitor data stores. When a monitor finds that its peer is too + far ahead of it, it will first sync with data stores before moving + on. +:Type: Integer +:Default: ``10`` -:Type: Float -:Default: ``10.0`` +``paxos stash full interval`` +:Description: How often (in commits) to stash a full copy of the PaxosService state. + Current this setting only affects ``mds``, ``mon``, ``auth`` and ``mgr`` + PaxosServices. +:Type: Integer +:Default: 25 ``paxos propose interval`` :Description: Gather updates for this time interval before proposing - a map update. - + a map update. :Type: Double :Default: ``1.0`` +``paxos min`` + +:Description: The minimum number of paxos states to keep around +:Type: Integer +:Default: 500 + + ``paxos min wait`` :Description: The minimum amount of time to gather updates after a period of inactivity. - :Type: Double :Default: ``0.05`` +``paxos trim min`` + +:Description: Number of extra proposals tolerated before trimming +:Type: Integer +:Default: 250 + + +``paxos trim max`` + +:Description: The maximum number of extra proposals to trim at a time +:Type: Integer +:Default: 500 + + +``paxos service trim min`` + +:Description: The minimum amount of versions to trigger a trim (0 disables it) +:Type: Integer +:Default: 250 + + +``paxos service trim max`` + +:Description: The maximum amount of versions to trim during a single proposal (0 disables it) +:Type: Integer +:Default: 500 + + +``mon max log epochs`` + +:Description: The maximum amount of log epochs to trim during a single proposal +:Type: Integer +:Default: 500 + + +``mon max pgmap epochs`` + +:Description: The maximum amount of pgmap epochs to trim during a single proposal +:Type: Integer +:Default: 500 + + +``mon mds force trim to`` + +:Description: Force monitor to trim mdsmaps to this point (0 disables it. + dangerous, use with care) +:Type: Integer +:Default: 0 + + +``mon osd force trim to`` + +:Description: Force monitor to trim osdmaps to this point, even if there is + PGs not clean at the specified epoch (0 disables it. dangerous, + use with care) +:Type: Integer +:Default: 0 + +``mon osd cache size`` + +:Description: The size of osdmaps cache, not to rely on underlying store's cache +:Type: Integer +:Default: 10 + + +``mon election timeout`` + +:Description: On election proposer, maximum waiting time for all ACKs in seconds. +:Type: Float +:Default: ``5`` + + ``mon lease`` :Description: The length (in seconds) of the lease on the monitor's versions. @@ -600,22 +811,30 @@ Trimming requires that the placement groups are ``active + clean``. :Default: ``5`` -``mon lease renew interval`` +``mon lease renew interval factor`` -:Description: The interval (in seconds) for the Leader to renew the other - monitor's leases. - +:Description: ``mon lease`` \* ``mon lease renew interval factor`` will be the + interval for the Leader to renew the other monitor's leases. The + factor should be less than ``1.0``. :Type: Float -:Default: ``3`` +:Default: ``0.6`` -``mon lease ack timeout`` +``mon lease ack timeout factor`` -:Description: The number of seconds the Leader will wait for the Providers to - acknowledge the lease extension. - +:Description: The Leader will wait ``mon lease`` \* ``mon lease ack timeout factor`` + for the Providers to acknowledge the lease extension. :Type: Float -:Default: ``10.0`` +:Default: ``2.0`` + + +``mon accept timeout factor`` + +:Description: The Leader will wait ``mon lease`` \* ``mon accept timeout factor`` + for the Requester(s) to accept a Paxos update. It is also used + during the Paxos recovery phase for similar purposes. +:Type: Float +:Default: ``2.0`` ``mon min osdmap epochs`` @@ -640,42 +859,6 @@ Trimming requires that the placement groups are ``active + clean``. - -Slurp ------ - -In Ceph version 0.58 and earlier, when a Paxos service drifts beyond a given -number of versions, Ceph triggers the `slurp` mechanism, which establishes a -connection with the quorum Leader and obtains every single version the Leader -has for every service that has drifted. In Ceph versions 0.59 and later, slurp -will not work, because there is a single Paxos instance for all services. - -.. deprecated:: 0.58 - -``paxos max join drift`` - -:Description: The maximum Paxos iterations before we must first sync the - monitor data stores. -:Type: Integer -:Default: ``10`` - - -``mon slurp timeout`` - -:Description: The number of seconds the monitor has to recover using slurp - before the process is aborted and the monitor bootstraps. - -:Type: Double -:Default: ``10.0`` - - -``mon slurp bytes`` - -:Description: Limits the slurp messages to the specified number of bytes. -:Type: 32-bit Integer -:Default: ``256 * 1024`` - - .. index:: Ceph Monitor; clock Clock @@ -688,7 +871,7 @@ are not synchronized, it can lead to a number of anomalies. For example: - Daemons ignoring received messages (e.g., timestamps outdated) - Timeouts triggered too soon/late when a message wasn't received in time. -See `Monitor Store Synchronization`_ and `Slurp`_ for details. +See `Monitor Store Synchronization`_ for details. .. tip:: You SHOULD install NTP on your Ceph monitor hosts to @@ -739,12 +922,19 @@ acceptable values. ``mon timecheck interval`` :Description: The time check interval (clock drift check) in seconds - for the leader. + for the Leader. :Type: Float :Default: ``300.0`` +``mon timecheck skew interval`` + +:Description: The time check interval (clock drift check) in seconds when in + presence of a skew in seconds for the Leader. +:Type: Float +:Default: ``30.0`` + Client ------ @@ -835,12 +1025,6 @@ Miscellaneous :Type: 32-bit Integer :Default: ``100`` -``mon sync fs threshold`` - -:Description: Synchronize with the filesystem when writing the specified number of objects. Set it to ``0`` to disable it. -:Type: 32-bit Integer -:Default: ``5`` - ``mon subscribe interval`` :Description: The refresh interval (in seconds) for subscriptions. The @@ -897,6 +1081,129 @@ Miscellaneous :Default: ``0.5`` +``mon osd prime pg temp max time estimate`` + +:Description: Maximum estimate of time spent on each PG before we prime all PGs + in parallel. +:Type: Float +:Default: ``0.25`` + + +``mon osd allow primary affinity`` + +:Description: allow ``primary_affinity`` to be set in the osdmap. +:Type: Boolean +:Default: False + + +``mon osd pool ec fast read`` + +:Description: Whether turn on fast read on the pool or not. It will be used as + the default setting of newly created erasure pools if ``fast_read`` + is not specified at create time. +:Type: Boolean +:Default: False + + +``mon mds skip sanity`` + +:Description: Skip safety assertions on FSMap (in case of bugs where we want to + continue anyway). Monitor terminates if the FSMap sanity check + fails, but we can disable it by enabling this option. +:Type: Boolean +:Default: False + + +``mon max mdsmap epochs`` + +:Description: The maximum amount of mdsmap epochs to trim during a single proposal. +:Type: Integer +:Default: 500 + + +``mon config key max entry size`` + +:Description: The maximum size of config-key entry (in bytes) +:Type: Integer +:Default: 4096 + + +``mon scrub interval`` + +:Description: How often (in seconds) the monitor scrub its store by comparing + the stored checksums with the computed ones of all the stored + keys. +:Type: Integer +:Default: 3600*24 + + +``mon scrub max keys`` + +:Description: The maximum number of keys to scrub each time. +:Type: Integer +:Default: 100 + + +``mon compact on start`` + +:Description: Compact the database used as Ceph Monitor store on + ``ceph-mon`` start. A manual compaction helps to shrink the + monitor database and improve the performance of it if the regular + compaction fails to work. +:Type: Boolean +:Default: False + + +``mon compact on bootstrap`` + +:Description: Compact the database used as Ceph Monitor store on + on bootstrap. Monitor starts probing each other for creating + a quorum after bootstrap. If it times out before joining the + quorum, it will start over and bootstrap itself again. +:Type: Boolean +:Default: False + + +``mon compact on trim`` + +:Description: Compact a certain prefix (including paxos) when we trim its old states. +:Type: Boolean +:Default: True + + +``mon cpu threads`` + +:Description: Number of threads for performing CPU intensive work on monitor. +:Type: Boolean +:Default: True + + +``mon osd mapping pgs per chunk`` + +:Description: We calculate the mapping from placement group to OSDs in chunks. + This option specifies the number of placement groups per chunk. +:Type: Integer +:Default: 4096 + + +``mon osd max split count`` + +:Description: Largest number of PGs per "involved" OSD to let split create. + When we increase the ``pg_num`` of a pool, the placement groups + will be splitted on all OSDs serving that pool. We want to avoid + extreme multipliers on PG splits. +:Type: Integer +:Default: 300 + + +``mon session timeout`` + +:Description: Monitor will terminate inactive sessions stay idle over this + time limit. +:Type: Integer +:Default: 300 + + .. _Paxos: http://en.wikipedia.org/wiki/Paxos_(computer_science) .. _Monitor Keyrings: ../../../dev/mon-bootstrap#secret-keys diff --git a/ceph/doc/rados/configuration/mon-lookup-dns.rst b/ceph/doc/rados/configuration/mon-lookup-dns.rst index 0b0cb5699..9aa1d3739 100644 --- a/ceph/doc/rados/configuration/mon-lookup-dns.rst +++ b/ceph/doc/rados/configuration/mon-lookup-dns.rst @@ -12,6 +12,13 @@ This allows for less configuration on clients and monitors. Using a DNS update c By default clients and daemons will look for the TCP service called *ceph-mon* which is configured by the *mon_dns_srv_name* configuration directive. + +``mon dns srv name`` + +:Description: the service name used querying the DNS for the monitor hosts/addresses +:Type: String +:Default: ``ceph-mon`` + Example ------- When the DNS search domain is set to *example.com* a DNS zone file might contain the following elements. diff --git a/ceph/doc/rados/configuration/mon-osd-interaction.rst b/ceph/doc/rados/configuration/mon-osd-interaction.rst index c71b400ed..ab57cb069 100644 --- a/ceph/doc/rados/configuration/mon-osd-interaction.rst +++ b/ceph/doc/rados/configuration/mon-osd-interaction.rst @@ -66,39 +66,46 @@ or by setting the value at runtime. |----+ Mark | | | OSD 2 | |<---+ Down | - + .. index:: OSD down report OSDs Report Down OSDs ===================== -By default, a Ceph OSD Daemon must report to the Ceph Monitors that another Ceph -OSD Daemon is ``down`` three times before the Ceph Monitors acknowledge that the -reported Ceph OSD Daemon is ``down``. By default, only one -Ceph OSD Daemon is required to report another Ceph OSD Daemon ``down``. You can -change the number of Ceph OSD Daemones required to report a Ceph OSD Daemon -``down`` to a Ceph Monitor by adding an ``mon osd min down reporters`` setting -(``osd min down reporters`` prior to v0.62) under the ``[mon]`` section of your -Ceph configuration file, or by setting the value at runtime. - - -.. ditaa:: +---------+ +---------+ - | OSD 1 | | Monitor | - +---------+ +---------+ - | | - | OSD 2 Is Down | - |-------------->| - | | - | OSD 2 Is Down | - |-------------->| - | | - | OSD 2 Is Down | - |-------------->| - | | - | |----------+ Mark - | | | OSD 2 - | |<---------+ Down +By default, two Ceph OSD Daemons from different hosts must report to the Ceph +Monitors that another Ceph OSD Daemon is ``down`` before the Ceph Monitors +acknowledge that the reported Ceph OSD Daemon is ``down``. But there is chance +that all the OSDs reporting the failure are hosted in a rack with a bad switch +which has trouble connecting to another OSD. To avoid this sort of false alarm, +we consider the peers reporting a failure a proxy for a potential "subcluster" +over the overall cluster that is similarly laggy. This is clearly not true in +all cases, but will sometimes help us localize the grace correction to a subset +of the system that is unhappy. ``mon osd reporter subtree level`` is used to +group the peers into the "subcluster" by their common ancestor type in CRUSH +map. By default, only two reports from different subtree are required to report +another Ceph OSD Daemon ``down``. You can change the number of reporters from +unique subtrees and the common ancestor type required to report a Ceph OSD +Daemon ``down`` to a Ceph Monitor by adding an ``mon osd min down reporters`` +and ``mon osd reporter subtree level`` settings under the ``[mon]`` section of +your Ceph configuration file, or by setting the value at runtime. + + +.. ditaa:: +---------+ +---------+ +---------+ + | OSD 1 | | OSD 2 | | Monitor | + +---------+ +---------+ +---------+ + | | | + | OSD 3 Is Down | | + |---------------+--------------->| + | | | + | | | + | | OSD 3 Is Down | + | |--------------->| + | | | + | | | + | | |---------+ Mark + | | | | OSD 3 + | | |<--------+ Down .. index:: peering failure @@ -118,13 +125,13 @@ setting the value at runtime. +---------+ +---------+ +-------+ +---------+ | | | | | Request To | | | - | Peer | | | + | Peer | | | |-------------->| | | |<--------------| | | | Peering | | | | | | Request To | | - | Peer | | + | Peer | | |----------------------------->| | | | |----+ OSD Monitor | @@ -135,7 +142,7 @@ setting the value at runtime. |-------------------------------------------->| |<--------------------------------------------| | Receive New Cluster Map | - + .. index:: OSD status @@ -149,10 +156,10 @@ event such as a failure, a change in placement group stats, a change in ``up_thru`` or when it boots within 5 seconds. You can change the Ceph OSD Daemon minimum report interval by adding an ``osd mon report interval min`` setting under the ``[osd]`` section of your Ceph configuration file, or by -setting the value at runtime. A Ceph OSD Daemon sends a report to a Ceph -Monitor every 120 seconds irrespective of whether any notable changes occur. -You can change the Ceph Monitor report interval by adding an ``osd mon report -interval max`` setting under the ``[osd]`` section of your Ceph configuration +setting the value at runtime. A Ceph OSD Daemon sends a report to a Ceph +Monitor every 120 seconds irrespective of whether any notable changes occur. +You can change the Ceph Monitor report interval by adding an ``osd mon report +interval max`` setting under the ``[osd]`` section of your Ceph configuration file, or by setting the value at runtime. @@ -207,18 +214,18 @@ Monitor Settings ``mon osd min up ratio`` -:Description: The minimum ratio of ``up`` Ceph OSD Daemons before Ceph will +:Description: The minimum ratio of ``up`` Ceph OSD Daemons before Ceph will mark Ceph OSD Daemons ``down``. - + :Type: Double :Default: ``.3`` ``mon osd min in ratio`` -:Description: The minimum ratio of ``in`` Ceph OSD Daemons before Ceph will +:Description: The minimum ratio of ``in`` Ceph OSD Daemons before Ceph will mark Ceph OSD Daemons ``out``. - + :Type: Double :Default: ``.75`` @@ -237,6 +244,15 @@ Monitor Settings :Default: ``0.3`` + +``mon osd laggy max interval`` +:Description: Maximum value of ``laggy_interval`` in laggy estimations (in seconds). + Monitor uses an adaptive approach to evaluate the ``laggy_interval`` of + a certain OSD. This value will be used to calculate the grace time for + that OSD. +:Type: Integer +:Default: 300 + ``mon osd adjust heartbeat grace`` :Description: If set to ``true``, Ceph will scale based on laggy estimations. @@ -251,38 +267,38 @@ Monitor Settings :Default: ``true`` -``mon osd auto mark in`` +``mon osd auto mark in`` -:Description: Ceph will mark any booting Ceph OSD Daemons as ``in`` +:Description: Ceph will mark any booting Ceph OSD Daemons as ``in`` the Ceph Storage Cluster. :Type: Boolean :Default: ``false`` -``mon osd auto mark auto out in`` +``mon osd auto mark auto out in`` -:Description: Ceph will mark booting Ceph OSD Daemons auto marked ``out`` +:Description: Ceph will mark booting Ceph OSD Daemons auto marked ``out`` of the Ceph Storage Cluster as ``in`` the cluster. - + :Type: Boolean -:Default: ``true`` +:Default: ``true`` -``mon osd auto mark new in`` +``mon osd auto mark new in`` -:Description: Ceph will mark booting new Ceph OSD Daemons as ``in`` the +:Description: Ceph will mark booting new Ceph OSD Daemons as ``in`` the Ceph Storage Cluster. - + :Type: Boolean -:Default: ``true`` +:Default: ``true`` -``mon osd down out interval`` +``mon osd down out interval`` :Description: The number of seconds Ceph waits before marking a Ceph OSD Daemon ``down`` and ``out`` if it doesn't respond. - + :Type: 32-bit Integer :Default: ``600`` @@ -298,21 +314,30 @@ Monitor Settings :Default: ``rack`` -``mon osd report timeout`` +``mon osd report timeout`` -:Description: The grace period in seconds before declaring +:Description: The grace period in seconds before declaring unresponsive Ceph OSD Daemons ``down``. :Type: 32-bit Integer :Default: ``900`` -``mon osd min down reporters`` +``mon osd min down reporters`` -:Description: The minimum number of Ceph OSD Daemons required to report a +:Description: The minimum number of Ceph OSD Daemons required to report a ``down`` Ceph OSD Daemon. :Type: 32-bit Integer -:Default: ``1`` +:Default: ``2`` + + +``mon osd reporter subtree level`` + +:Description: In which level of parent bucket the reporters are counted. The OSDs + send failure reports to monitor if they find its peer is not responsive. + And monitor mark the reported OSD out and then down after a grace period. +:Type: String +:Default: ``host`` .. index:: OSD hearbeat @@ -322,63 +347,61 @@ OSD Settings ``osd heartbeat address`` -:Description: An Ceph OSD Daemon's network address for heartbeats. +:Description: An Ceph OSD Daemon's network address for heartbeats. :Type: Address :Default: The host address. -``osd heartbeat interval`` +``osd heartbeat interval`` :Description: How often an Ceph OSD Daemon pings its peers (in seconds). :Type: 32-bit Integer :Default: ``6`` -``osd heartbeat grace`` +``osd heartbeat grace`` :Description: The elapsed time when a Ceph OSD Daemon hasn't shown a heartbeat that the Ceph Storage Cluster considers it ``down``. This setting has to be set in both the [mon] and [osd] or [global] section so that it is read by both the MON and OSD daemons. - :Type: 32-bit Integer :Default: ``20`` -``osd mon heartbeat interval`` +``osd mon heartbeat interval`` -:Description: How often the Ceph OSD Daemon pings a Ceph Monitor if it has no +:Description: How often the Ceph OSD Daemon pings a Ceph Monitor if it has no Ceph OSD Daemon peers. :Type: 32-bit Integer -:Default: ``30`` +:Default: ``30`` -``osd mon report interval max`` +``osd mon report interval max`` :Description: The maximum time in seconds that a Ceph OSD Daemon can wait before it must report to a Ceph Monitor. :Type: 32-bit Integer -:Default: ``120`` +:Default: ``120`` -``osd mon report interval min`` +``osd mon report interval min`` :Description: The minimum number of seconds a Ceph OSD Daemon may wait - from startup or another reportable event before reporting + from startup or another reportable event before reporting to a Ceph Monitor. :Type: 32-bit Integer :Default: ``5`` -:Valid Range: Should be less than ``osd mon report interval max`` +:Valid Range: Should be less than ``osd mon report interval max`` -``osd mon ack timeout`` +``osd mon ack timeout`` -:Description: The number of seconds to wait for a Ceph Monitor to acknowledge a +:Description: The number of seconds to wait for a Ceph Monitor to acknowledge a request for statistics. :Type: 32-bit Integer -:Default: ``30`` - +:Default: ``30`` diff --git a/ceph/doc/rados/configuration/osd-config-ref.rst b/ceph/doc/rados/configuration/osd-config-ref.rst index 5679c0cae..801363930 100644 --- a/ceph/doc/rados/configuration/osd-config-ref.rst +++ b/ceph/doc/rados/configuration/osd-config-ref.rst @@ -420,7 +420,7 @@ recovery operations to ensure optimal performance during recovery. ``osd client op priority``. :Type: 32-bit Integer -:Default: ``10`` +:Default: ``3`` :Valid Range: 1-63 @@ -654,7 +654,7 @@ perform well in a degraded state. increased load on the cluster. :Type: 32-bit Integer -:Default: ``15`` +:Default: ``3`` ``osd recovery max chunk`` @@ -664,6 +664,14 @@ perform well in a degraded state. :Default: ``8 << 20`` +``osd recovery max single start`` + +:Description: The maximum number of recovery operations per OSD that will be + newly started when an OSD is recovering. +:Type: 64-bit Integer Unsigned +:Default: ``1`` + + ``osd recovery thread timeout`` :Description: The maximum time in seconds before timing out a recovery thread. @@ -679,6 +687,16 @@ perform well in a degraded state. :Type: Boolean :Default: ``true`` + +``osd recovery sleep`` + +:Description: Time to sleep before next recovery. Increasing this value will + slow down recovery operation while client operations will be + less impacted. + +:Type: Float +:Default: ``0.01`` + Tiering ======= diff --git a/ceph/doc/rados/configuration/pool-pg-config-ref.rst b/ceph/doc/rados/configuration/pool-pg-config-ref.rst index 9cb2c8f54..dd416edfa 100644 --- a/ceph/doc/rados/configuration/pool-pg-config-ref.rst +++ b/ceph/doc/rados/configuration/pool-pg-config-ref.rst @@ -42,15 +42,95 @@ Ceph configuration file. :Type: 32-bit Integer :Default: ``300`` +``mon pg min inactive`` -``osd pg bits`` +:Description: Issue a ``HEALTH_ERR`` in cluster log if the number of PGs stay + inactive longer than ``mon_pg_stuck_threshold`` exceeds this + setting. A non-positive number means disabled, never go into ERR. +:Type: Integer +:Default: ``1`` + + +``mon pg warn min per osd`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if the average number + of PGs per (in) OSD is under this number. (a non-positive number + disables this) +:Type: Integer +:Default: ``30`` + + +``mon pg warn max per osd`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if the average number + of PGs per (in) OSD is above this number. (a non-positive number + disables this) +:Type: Integer +:Default: ``300`` + + +``mon pg warn min objects`` + +:Description: Do not warn if the total number of objects in cluster is below + this number +:Type: Integer +:Default: ``1000`` + + +``mon pg warn min pool objects`` + +:Description: Do not warn on pools whose object number is below this number +:Type: Integer +:Default: ``1000`` + + +``mon pg check down all threshold`` + +:Description: Threshold of down OSDs percentage after which we check all PGs + for stale ones. +:Type: Float +:Default: ``0.5`` + + +``mon pg warn max object skew`` + +:Description: Issue a ``HEALTH_WARN`` in cluster log if the average object number + of a certain pool is greater than ``mon pg warn max object skew`` times + the average object number of the whole pool. (a non-positive number + disables this) +:Type: Float +:Default: ``10`` + + +``mon delta reset interval`` + +:Description: Seconds of inactivity before we reset the pg delta to 0. We keep + track of the delta of the used space of each pool, so, for + example, it would be easier for us to understand the progress of + recovery or the performance of cache tier. But if there's no + activity reported for a certain pool, we just reset the history of + deltas of that pool. +:Type: Integer +:Default: ``10`` + + +``mon osd max op age`` + +:Description: Maximum op age before we get concerned (make it a power of 2). + A ``HEALTH_WARN`` will be issued if a request has been blocked longer + than this limit. +:Type: Float +:Default: ``32.0`` + + +``osd pg bits`` :Description: Placement group bits per Ceph OSD Daemon. :Type: 32-bit Integer :Default: ``6`` -``osd pgp bits`` +``osd pgp bits`` :Description: The number of bits per Ceph OSD Daemon for PGPs. :Type: 32-bit Integer diff --git a/ceph/doc/rados/operations/crush-map.rst b/ceph/doc/rados/operations/crush-map.rst index e28627b11..c75887ca8 100644 --- a/ceph/doc/rados/operations/crush-map.rst +++ b/ceph/doc/rados/operations/crush-map.rst @@ -1257,4 +1257,4 @@ Further, as noted above, be careful running old versions of the ``ceph-osd`` daemon after reverting to legacy values as the feature bit is not perfectly enforced. -.. _CRUSH - Controlled, Scalable, Decentralized Placement of Replicated Data: http://ceph.com/papers/weil-crush-sc06.pdf +.. _CRUSH - Controlled, Scalable, Decentralized Placement of Replicated Data: https://ceph.com/wp-content/uploads/2016/08/weil-crush-sc06.pdf diff --git a/ceph/doc/rados/operations/erasure-code-jerasure.rst b/ceph/doc/rados/operations/erasure-code-jerasure.rst index bd2917ed1..b0e6020cd 100644 --- a/ceph/doc/rados/operations/erasure-code-jerasure.rst +++ b/ceph/doc/rados/operations/erasure-code-jerasure.rst @@ -6,7 +6,7 @@ The *jerasure* plugin is the most generic and flexible plugin, it is also the default for Ceph erasure coded pools. The *jerasure* plugin encapsulates the `Jerasure -`_ library. It is +`_ library. It is recommended to read the *jerasure* documentation to get a better understanding of the parameters. diff --git a/ceph/doc/rados/operations/erasure-code.rst b/ceph/doc/rados/operations/erasure-code.rst index 6878777ac..568f26aec 100644 --- a/ceph/doc/rados/operations/erasure-code.rst +++ b/ceph/doc/rados/operations/erasure-code.rst @@ -139,7 +139,7 @@ erasure coded pool as the ``--data-pool`` during image creation:: rbd create --size 1G --data-pool ec_pool replicated_pool/image_name For Cephfs, using an erasure coded pool means setting that pool in -a `file layout<../../cephfs/file-layouts>`_. +a `file layout <../../../cephfs/file-layouts>`_. Erasure coded pool and cache tiering diff --git a/ceph/doc/rados/operations/user-management.rst b/ceph/doc/rados/operations/user-management.rst index ccdb09787..2e47f37ff 100644 --- a/ceph/doc/rados/operations/user-management.rst +++ b/ceph/doc/rados/operations/user-management.rst @@ -360,6 +360,7 @@ are often restricted to accessing a particular pool. :: pools in the cluster! +.. _modify-user-capabilities: Modify User Capabilities ------------------------ diff --git a/ceph/doc/rados/troubleshooting/memory-profiling.rst b/ceph/doc/rados/troubleshooting/memory-profiling.rst index 5322e7b22..e2396e2fd 100644 --- a/ceph/doc/rados/troubleshooting/memory-profiling.rst +++ b/ceph/doc/rados/troubleshooting/memory-profiling.rst @@ -139,4 +139,4 @@ For example:: ceph tell osd.0 heap stop_profiler .. _Logging and Debugging: ../log-and-debug -.. _Google Heap Profiler: http://google-perftools.googlecode.com/svn/trunk/doc/heapprofile.html +.. _Google Heap Profiler: http://goog-perftools.sourceforge.net/doc/heap_profiler.html diff --git a/ceph/doc/rados/troubleshooting/troubleshooting-osd.rst b/ceph/doc/rados/troubleshooting/troubleshooting-osd.rst index fe29f4767..f72c6a4ad 100644 --- a/ceph/doc/rados/troubleshooting/troubleshooting-osd.rst +++ b/ceph/doc/rados/troubleshooting/troubleshooting-osd.rst @@ -417,7 +417,57 @@ Possible solutions - Upgrade Ceph - Restart OSDs - +Debugging Slow Requests +----------------------- + +If you run "ceph daemon osd. dump_historic_ops" or "dump_ops_in_flight", +you will see a set of operations and a list of events each operation went +through. These are briefly described below. + +Events from the Messenger layer: + +- header_read: when the messenger first started reading the message off the wire +- throttled: when the messenger tried to acquire memory throttle space to read + the message into memory +- all_read: when the messenger finished reading the message off the wire +- dispatched: when the messenger gave the message to the OSD +- Initiated: : the primary marks this when it + hears about the above, but for a particular replica +- commit_sent: we sent a reply back to the client (or primary OSD, for sub ops) + +Many of these events are seemingly redundant, but cross important boundaries in +the internal code (such as passing data across locks into new threads). Flapping OSDs ============= diff --git a/ceph/doc/radosgw/admin.rst b/ceph/doc/radosgw/admin.rst index f1916481b..c1f1904f7 100644 --- a/ceph/doc/radosgw/admin.rst +++ b/ceph/doc/radosgw/admin.rst @@ -438,6 +438,20 @@ new user, and that quota is enabled. See ``rgw bucket default quota max objects ``rgw bucket default quota max size``, ``rgw user default quota max objects``, and ``rgw user default quota max size`` in `Ceph Object Gateway Config Reference`_ +Quota Cache +----------- + +Quota statistics are cached on each RGW instance. If there are multiple +instances, then the cache can keep quotas from being perfectly enforced, as +each instance will have a different view of quotas. The options that control +this are ``rgw bucket quota ttl``, ``rgw user quota bucket sync interval`` and +``rgw user quota sync interval``. The higher these values are, the more +efficient quota operations are, but the more out-of-sync multiple instances +will be. The lower these values are, the closer to perfect enforcement +multiple instances will achieve. If all three are 0, then quota caching is +effectively disabled, and multiple instances will have perfect quota +enforcement. See `Ceph Object Gateway Config Reference`_ + Reading / Writing Global Quotas ------------------------------- diff --git a/ceph/doc/radosgw/adminops.rst b/ceph/doc/radosgw/adminops.rst index 241c43d10..28c02164b 100644 --- a/ceph/doc/radosgw/adminops.rst +++ b/ceph/doc/radosgw/adminops.rst @@ -1818,11 +1818,6 @@ Special Error Responses :Description: User does not possess specified capability. :Code: 404 Not Found -Special Error Responses -~~~~~~~~~~~~~~~~~~~~~~~ - -None. - Quotas ====== diff --git a/ceph/doc/radosgw/barbican.rst b/ceph/doc/radosgw/barbican.rst index 557c95604..3a7fe6e5c 100644 --- a/ceph/doc/radosgw/barbican.rst +++ b/ceph/doc/radosgw/barbican.rst @@ -67,7 +67,8 @@ In the response, ``d1e7ef3b-f841-4b7c-90b2-b7d90ca2d723`` is the key id that can be used in any `SSE-KMS`_ request. This newly created key is not accessible by user ``rgwcrypt-user``. This -privilege must be added with an ACL. +privilege must be added with an ACL. See `How to Set/Replace ACL`_ for more +details. Example request (assuming that the Keystone id of ``rgwcrypt-user`` is ``906aa90bd8a946c89cdff80d0869460f``):: diff --git a/ceph/doc/radosgw/bucketpolicy.rst b/ceph/doc/radosgw/bucketpolicy.rst new file mode 100644 index 000000000..85e705561 --- /dev/null +++ b/ceph/doc/radosgw/bucketpolicy.rst @@ -0,0 +1,133 @@ +=============== +Bucket Policies +=============== + +.. versionadded:: Luminous + +The Ceph Object Gateway supports a subset of the Amazon S3 policy +language applied to buckets. + + +Creation and Removal +==================== + +Bucket policies are managed through standard S3 operations rather than +radosgw-admin. + +For example, one may use s3cmd to set or delete a policy thus:: + + $ cat > examplepol + { + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Principal": {"AWS": ["arn:aws:iam::usfolks:user/fred"]}, + "Action": "s3PutObjectAcl", + "Resource": [ + "arn:aws:s3:::happybucket/*" + ] + }] + } + + $ s3cmd setpolicy examplepol s3://happybucket + $ s3cmd delpolicy s3://happybucket + + +Limitations +=========== + +Currently, we support only the following actions: + +- s3:AbortMultipartUpload +- s3:CreateBucket +- s3:DeleteBucketPolicy +- s3:DeleteBucket +- s3:DeleteBucketWebsite +- s3:DeleteObject +- s3:DeleteObjectVersion +- s3:DeleteReplicationConfiguration +- s3:GetAccelerateConfiguration +- s3:GetBucketAcl +- s3:GetBucketCORS +- s3:GetBucketLocation +- s3:GetBucketLogging +- s3:GetBucketNotification +- s3:GetBucketPolicy +- s3:GetBucketRequestPayment +- s3:GetBucketTagging +- s3:GetBucketVersioning +- s3:GetBucketWebsite +- s3:GetLifecycleConfiguration +- s3:GetObjectAcl +- s3:GetObject +- s3:GetObjectTorrent +- s3:GetObjectVersionAcl +- s3:GetObjectVersion +- s3:GetObjectVersionTorrent +- s3:GetReplicationConfiguration +- s3:ListAllMyBuckets +- s3:ListBucketMultiPartUploads +- s3:ListBucket +- s3:ListBucketVersions +- s3:ListMultipartUploadParts +- s3:PutAccelerateConfiguration +- s3:PutBucketAcl +- s3:PutBucketCORS +- s3:PutBucketLogging +- s3:PutBucketNotification +- s3:PutBucketPolicy +- s3:PutBucketRequestPayment +- s3:PutBucketTagging +- s3:PutBucketVersioning +- s3:PutBucketWebsite +- s3:PutLifecycleConfiguration +- s3:PutObjectAcl +- s3:PutObject +- s3:PutObjectVersionAcl +- s3:PutReplicationConfiguration +- s3:RestoreObject + +We do not yet support setting policies on users, groups, or roles. + +We use the RGW ‘tenant’ identifier in place of the Amazon twelve-digit +account ID. In the future we may allow you to assign an account ID to +a tenant, but for now if you want to use policies between AWS S3 and +RGW S3 you will have to use the Amazon account ID as the tenant ID when +creating users. + +Under AWS, all tenants share a single namespace. RGW gives every +tenant its own namespace of buckets. There may be an option to enable +an AWS-like 'flat' bucket namespace in future versions. At present, to +access a bucket belonging to another tenant, address it as +"tenant:bucket" in the S3 request. + +In AWS, a bucket policy can grant access to another account, and that +account owner can then grant access to individual users with user +permissions. Since we do not yet support user, role, and group +permissions, account owners will currently need to grant access +directly to individual users, and granting an entire account access to +a bucket grants access to all users in that account. + +Bucket policies do not yet support string interpolation. + +Currently, the only condition keys we support are: +- aws:CurrentTime +- aws:EpochTime +- aws:PrincipalType +- aws:Referer +- aws:SecureTransport +- aws:SourceIp +- aws:UserAgent +- aws:username + +More may be supported soon as we integrate with the recently rewritten +Authentication/Authorization subsystem. + +Swift +===== + +There is no way to set bucket policies under Swift, but bucket +policies that have been set govern Swift as well as S3 operations. + +Swift credentials are matched against Principals specified in a policy +in a way specific to whatever backend is being used. diff --git a/ceph/doc/radosgw/config-fcgi.rst b/ceph/doc/radosgw/config-fcgi.rst deleted file mode 100644 index a0b19460f..000000000 --- a/ceph/doc/radosgw/config-fcgi.rst +++ /dev/null @@ -1,595 +0,0 @@ -===================================================== - Configuring Ceph Object Gateway with Apache/FastCGI -===================================================== - -Configuring a Ceph Object Gateway requires a running Ceph Storage Cluster. -Since it contains an embedded webserver (civetweb), the Ceph Object Gateway -does not require an external web server, but it can be configured to use -Apache with the FastCGI module. - -.. note:: CGI can pose a security risk. - -The Ceph Object Gateway is a client of the Ceph Storage Cluster. As a -Ceph Storage Cluster client, it requires: - -- A name for the gateway instance. We use ``gateway`` in this guide. -- A storage cluster user name with appropriate permissions in a keyring. -- Pools to store its data. -- A data directory for the gateway instance. -- An instance entry in the Ceph Configuration file. -- A configuration file for the web server to interact with FastCGI. - - -Create a User and Keyring -========================= - -Each instance must have a user name and key to communicate with a Ceph Storage -Cluster. In the following steps, we use an admin node to create a keyring. -Then, we create a client user name and key. Next, we add the -key to the Ceph Storage Cluster. Finally, we distribute the key ring to -the node containing the gateway instance. - -.. topic:: Monitor Key CAPS - - When you provide CAPS to the key, you MUST provide read capability. - However, you have the option of providing write capability for the monitor. - This is an important choice. If you provide write capability to the key, - the Ceph Object Gateway will have the ability to create pools automatically; - however, it will create pools with either the default number of placement - groups (not ideal) or the number of placement groups you specified in your - Ceph configuration file. If you allow the Ceph Object Gateway to create - pools automatically, ensure that you have reasonable defaults for the number - of placement groups first. See `Pool Configuration`_ for details. - - -See `User Management`_ for additional details on Ceph authentication. - -#. Generate a Ceph Object Gateway user name and key for each instance. For - exemplary purposes, we will use the name ``gateway`` after ``client.radosgw``:: - - sudo ceph auth get-or-create client.radosgw.gateway osd 'allow rwx' mon 'allow rwx' -o /etc/ceph/ceph.client.radosgw.keyring - -#. Distribute the keyring to the node with the gateway instance. :: - - sudo scp /etc/ceph/ceph.client.radosgw.keyring ceph@{hostname}:/home/ceph - ssh {hostname} - sudo mv ceph.client.radosgw.keyring /etc/ceph/ceph.client.radosgw.keyring - - - .. note:: The 2nd step is optional if ``admin node`` is the ``gateway host``. - -Create Pools -============ - -Ceph Object Gateways require Ceph Storage Cluster pools to store specific -gateway data. If the user you created has permissions, the gateway -will create the pools automatically. However, you should ensure that you have -set an appropriate default number of placement groups per pool into your Ceph -configuration file. - -.. note:: Ceph Object Gateways have multiple pools, so don't make the number of - PGs too high considering all of the pools assigned to the same CRUSH - hierarchy, or performance may suffer. - -When configuring a gateway with the default region and zone, the naming -convention for pools typically omits region and zone naming, but you can use any -naming convention you prefer. For example: - - -- ``.rgw.root`` -- ``.rgw.control`` -- ``.rgw.gc`` -- ``.rgw.buckets`` -- ``.rgw.buckets.index`` -- ``.rgw.buckets.extra`` -- ``.log`` -- ``.intent-log`` -- ``.usage`` -- ``.users`` -- ``.users.email`` -- ``.users.swift`` -- ``.users.uid`` - - -See `Configuration Reference - Pools`_ for details on the default pools for -gateways. See `Pools`_ for details on creating pools. As already said, if -write permission is given, Ceph Object Gateway will create pools automatically. -To create a pool manually, execute the following:: - - ceph osd pool create {poolname} {pg-num} {pgp-num} {replicated | erasure} [{erasure-code-profile}] {ruleset-name} {ruleset-number} - - -.. tip:: Ceph supports multiple CRUSH hierarchies and CRUSH rulesets, enabling - great flexibility in the way you configure your gateway. Pools such as - ``rgw.buckets.index`` may benefit from a pool of SSDs for fast performance. - Backing storage may benefit from the increased economy of erasure-coded - storage, and/or the improved performance from cache tiering. - -When you have completed this step, execute the following to ensure that -you have created all of the foregoing pools:: - - rados lspools - - -Add a Gateway Configuration to Ceph -=================================== - -Add the Ceph Object Gateway configuration to your Ceph Configuration file in -``admin node``. The Ceph Object Gateway configuration requires you to -identify the Ceph Object Gateway instance. Then, you must specify the host name -where you installed the Ceph Object Gateway daemon, a keyring (for use with -cephx), the socket path for FastCGI and a log file. - -For distros with Apache 2.2 and early versions of Apache 2.4 (RHEL 6, Ubuntu -12.04, 14.04 etc), append the following configuration to ``/etc/ceph/ceph.conf`` -in your ``admin node``:: - - [client.radosgw.gateway] - host = {hostname} - keyring = /etc/ceph/ceph.client.radosgw.keyring - rgw socket path = "" - log file = /var/log/radosgw/client.radosgw.gateway.log - rgw frontends = fastcgi socket_port=9000 socket_host=0.0.0.0 - rgw print continue = false - - -.. note:: Apache 2.2 and early versions of Apache 2.4 do not use Unix Domain - Sockets but use localhost TCP. - -For distros with Apache 2.4.9 or later (RHEL 7, CentOS 7 etc), append the -following configuration to ``/etc/ceph/ceph.conf`` in your ``admin node``:: - - [client.radosgw.gateway] - host = {hostname} - keyring = /etc/ceph/ceph.client.radosgw.keyring - rgw socket path = /var/run/ceph/ceph.radosgw.gateway.fastcgi.sock - log file = /var/log/radosgw/client.radosgw.gateway.log - rgw print continue = false - - -.. note:: ``Apache 2.4.9`` supports Unix Domain Socket (UDS) but as - ``Ubuntu 14.04`` ships with ``Apache 2.4.7`` it doesn't have UDS support and - has to be configured for use with localhost TCP. A bug has been filed for - backporting UDS support in ``Apache 2.4.7`` for ``Ubuntu 14.04``. - See: `Backport support for UDS in Ubuntu Trusty`_ - -Here, ``{hostname}`` is the short hostname (output of command ``hostname -s``) -of the node that is going to provide the gateway service i.e., the -``gateway host``. - -The ``[client.radosgw.gateway]`` portion of the gateway instance identifies this -portion of the Ceph configuration file as configuring a Ceph Storage Cluster -client where the client type is a Ceph Object Gateway (i.e., ``radosgw``). - - -.. note:: The last line in the configuration i.e., ``rgw print continue = false`` - is added to avoid issues with ``PUT`` operations. - -Once you finish the setup procedure, if you encounter issues with your -configuration, you can add debugging to the ``[global]`` section of your Ceph -configuration file and restart the gateway to help troubleshoot any -configuration issues. For example:: - - [global] - #append the following in the global section. - debug ms = 1 - debug rgw = 20 - - -Distribute updated Ceph configuration file -========================================== - -The updated Ceph configuration file needs to be distributed to all Ceph cluster -nodes from the ``admin node``. - -It involves the following steps: - -#. Pull the updated ``ceph.conf`` from ``/etc/ceph/`` to the root directory of - the cluster in admin node (e.g. ``my-cluster`` directory). The contents of - ``ceph.conf`` in ``my-cluster`` will get overwritten. To do so, execute the - following:: - - ceph-deploy --overwrite-conf config pull {hostname} - - Here, ``{hostname}`` is the short hostname of the Ceph admin node. - -#. Push the updated ``ceph.conf`` file from the admin node to all other nodes in - the cluster including the ``gateway host``:: - - ceph-deploy --overwrite-conf config push [HOST] [HOST...] - - Give the hostnames of the other Ceph nodes in place of ``[HOST] [HOST...]``. - - -Copy ceph.client.admin.keyring from admin node to gateway host -============================================================== - -As the ``gateway host`` can be a different node that is not part of the cluster, -the ``ceph.client.admin.keyring`` needs to be copied from the ``admin node`` to -the ``gateway host``. To do so, execute the following on ``admin node``:: - - sudo scp /etc/ceph/ceph.client.admin.keyring ceph@{hostname}:/home/ceph - ssh {hostname} - sudo mv ceph.client.admin.keyring /etc/ceph/ceph.client.admin.keyring - - -.. note:: The above step need not be executed if ``admin node`` is the - ``gateway host``. - - -Create Data Directory -===================== - -Deployment scripts may not create the default Ceph Object Gateway data -directory. Create data directories for each instance of a ``radosgw`` -daemon (if you haven't done so already). The ``host`` variables in the -Ceph configuration file determine which host runs each instance of a -``radosgw`` daemon. The typical form specifies the ``radosgw`` daemon, -the cluster name and the daemon ID. - -To create the directory on the ``gateway host``, execute the following:: - - sudo mkdir -p /var/lib/ceph/radosgw/ceph-radosgw.gateway - - -Adjust Socket Directory Permissions -=================================== - -On some distros, the ``radosgw`` daemon runs as the unprivileged ``apache`` -UID, and this UID must have write access to the location where it will write -its socket file. - -To grant permissions to the default socket location, execute the following on -the ``gateway host``:: - - sudo chown apache:apache /var/run/ceph - - -Change Log File Owner -===================== - -On some distros, the ``radosgw`` daemon runs as the unprivileged ``apache`` UID, -but the ``root`` user owns the log file by default. You must change it to the -``apache`` user so that Apache can populate the log file. To do so, execute -the following:: - - sudo chown apache:apache /var/log/radosgw/client.radosgw.gateway.log - - -Start radosgw service -===================== - -The Ceph Object gateway daemon needs to be started. To do so, execute the -following on the ``gateway host``: - -On Debian-based distros:: - - sudo /etc/init.d/radosgw start - -On RPM-based distros:: - - sudo /etc/init.d/ceph-radosgw start - - -Create a Gateway Configuration file -=================================== - -On the host where you installed the Ceph Object Gateway i.e., ``gateway host``, -create an ``rgw.conf`` file. Place the file in ``/etc/apache2/conf-available`` -directory for ``Debian-based`` distros and in ``/etc/httpd/conf.d`` directory -for ``RPM-based`` distros. It is a Apache configuration file which is needed -for the ``radosgw`` service. This file must be readable by the web server. - -Execute the following steps: - -#. Create the file: - - For Debian-based distros, execute:: - - sudo vi /etc/apache2/conf-available/rgw.conf - - For RPM-based distros, execute:: - - sudo vi /etc/httpd/conf.d/rgw.conf - -#. For distros with Apache 2.2 and early versions of Apache 2.4 that use - localhost TCP and do not support Unix Domain Socket, add the following - contents to the file:: - - - ServerName localhost - DocumentRoot /var/www/html - - ErrorLog /var/log/httpd/rgw_error.log - CustomLog /var/log/httpd/rgw_access.log combined - - # LogLevel debug - - RewriteEngine On - - RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] - - SetEnv proxy-nokeepalive 1 - - ProxyPass / fcgi://localhost:9000/ - - - - .. note:: For Debian-based distros replace ``/var/log/httpd/`` - with ``/var/log/apache2``. - -#. For distros with Apache 2.4.9 or later that support Unix Domain Socket, - add the following contents to the file:: - - - ServerName localhost - DocumentRoot /var/www/html - - ErrorLog /var/log/httpd/rgw_error.log - CustomLog /var/log/httpd/rgw_access.log combined - - # LogLevel debug - - RewriteEngine On - - RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] - - SetEnv proxy-nokeepalive 1 - - ProxyPass / unix:///var/run/ceph/ceph.radosgw.gateway.fastcgi.sock|fcgi://localhost:9000/ - - - - -Restart Apache -============== - -The Apache service needs to be restarted to accept the new configuration. - -For Debian-based distros, run:: - - sudo service apache2 restart - -For RPM-based distros, run:: - - sudo service httpd restart - -Or:: - - sudo systemctl restart httpd - - -Using The Gateway -================= - -To use the REST interfaces, first create an initial Ceph Object Gateway -user for the S3 interface. Then, create a subuser for the Swift interface. -See the `Admin Guide`_ for more details on user management. - -Create a radosgw user for S3 access ------------------------------------- - -A ``radosgw`` user needs to be created and granted access. The command -``man radosgw-admin`` will provide information on additional command options. - -To create the user, execute the following on the ``gateway host``:: - - sudo radosgw-admin user create --uid="testuser" --display-name="First User" - -The output of the command will be something like the following:: - - {"user_id": "testuser", - "display_name": "First User", - "email": "", - "suspended": 0, - "max_buckets": 1000, - "auid": 0, - "subusers": [], - "keys": [ - { "user": "testuser", - "access_key": "I0PJDPCIYZ665MW88W9R", - "secret_key": "dxaXZ8U90SXydYzyS5ivamEP20hkLSUViiaR+ZDA"}], - "swift_keys": [], - "caps": [], - "op_mask": "read, write, delete", - "default_placement": "", - "placement_tags": [], - "bucket_quota": { "enabled": false, - "max_size_kb": -1, - "max_objects": -1}, - "user_quota": { "enabled": false, - "max_size_kb": -1, - "max_objects": -1}, - "temp_url_keys": []} - - -.. note:: The values of ``keys->access_key`` and ``keys->secret_key`` are - needed for access validation. - -Create a Swift user -------------------- - -A Swift subuser needs to be created if this kind of access is needed. Creating -a Swift user is a two step process. The first step is to create the user. -The second is to create the secret key. - -Execute the following steps on the ``gateway host``: - -Create the Swift user:: - - sudo radosgw-admin subuser create --uid=testuser --subuser=testuser:swift --access=full - -The output will be something like the following:: - - { "user_id": "testuser", - "display_name": "First User", - "email": "", - "suspended": 0, - "max_buckets": 1000, - "auid": 0, - "subusers": [ - { "id": "testuser:swift", - "permissions": "full-control"}], - "keys": [ - { "user": "testuser:swift", - "access_key": "3Y1LNW4Q6X0Y53A52DET", - "secret_key": ""}, - { "user": "testuser", - "access_key": "I0PJDPCIYZ665MW88W9R", - "secret_key": "dxaXZ8U90SXydYzyS5ivamEP20hkLSUViiaR+ZDA"}], - "swift_keys": [], - "caps": [], - "op_mask": "read, write, delete", - "default_placement": "", - "placement_tags": [], - "bucket_quota": { "enabled": false, - "max_size_kb": -1, - "max_objects": -1}, - "user_quota": { "enabled": false, - "max_size_kb": -1, - "max_objects": -1}, - "temp_url_keys": []} - -Create the secret key:: - - sudo radosgw-admin key create --subuser=testuser:swift --key-type=swift --gen-secret - -The output will be something like the following:: - - { "user_id": "testuser", - "display_name": "First User", - "email": "", - "suspended": 0, - "max_buckets": 1000, - "auid": 0, - "subusers": [ - { "id": "testuser:swift", - "permissions": "full-control"}], - "keys": [ - { "user": "testuser:swift", - "access_key": "3Y1LNW4Q6X0Y53A52DET", - "secret_key": ""}, - { "user": "testuser", - "access_key": "I0PJDPCIYZ665MW88W9R", - "secret_key": "dxaXZ8U90SXydYzyS5ivamEP20hkLSUViiaR+ZDA"}], - "swift_keys": [ - { "user": "testuser:swift", - "secret_key": "244+fz2gSqoHwR3lYtSbIyomyPHf3i7rgSJrF\/IA"}], - "caps": [], - "op_mask": "read, write, delete", - "default_placement": "", - "placement_tags": [], - "bucket_quota": { "enabled": false, - "max_size_kb": -1, - "max_objects": -1}, - "user_quota": { "enabled": false, - "max_size_kb": -1, - "max_objects": -1}, - "temp_url_keys": []} - -Access Verification -=================== - -You then need to verify if the created users are able to access the gateway. - -Test S3 access --------------- - -You need to write and run a Python test script for verifying S3 access. The S3 -access test script will connect to the ``radosgw``, create a new bucket and list -all buckets. The values for ``aws_access_key_id`` and ``aws_secret_access_key`` -are taken from the values of ``access_key`` and ``secret_key`` returned by the -``radosgw_admin`` command. - -Execute the following steps: - -#. You will need to install the ``python-boto`` package. - - For Debian-based distros, run:: - - sudo apt-get install python-boto - - For RPM-based distros, run:: - - sudo yum install python-boto - -#. Create the Python script:: - - vi s3test.py - -#. Add the following contents to the file:: - - import boto - import boto.s3.connection - access_key = 'I0PJDPCIYZ665MW88W9R' - secret_key = 'dxaXZ8U90SXydYzyS5ivamEP20hkLSUViiaR+ZDA' - conn = boto.connect_s3( - aws_access_key_id = access_key, - aws_secret_access_key = secret_key, - host = '{hostname}', - is_secure=False, - calling_format = boto.s3.connection.OrdinaryCallingFormat(), - ) - bucket = conn.create_bucket('my-new-bucket') - for bucket in conn.get_all_buckets(): - print "{name}\t{created}".format( - name = bucket.name, - created = bucket.creation_date, - ) - - Replace ``{hostname}`` with the hostname of the host where you have - configured the gateway service i.e., the ``gateway host``. - -#. Run the script:: - - python s3test.py - - The output will be something like the following:: - - my-new-bucket 2015-02-16T17:09:10.000Z - -Test swift access ------------------ - -Swift access can be verified via the ``swift`` command line client. The command -``man swift`` will provide more information on available command line options. - -To install ``swift`` client, execute the following: - - For Debian-based distros:: - - sudo apt-get install python-setuptools - sudo easy_install pip - sudo pip install --upgrade setuptools - sudo pip install --upgrade python-swiftclient - - For RPM-based distros:: - - sudo yum install python-setuptools - sudo easy_install pip - sudo pip install --upgrade setuptools - sudo pip install --upgrade python-swiftclient - -To test swift access, execute the following:: - - swift -A http://{IP ADDRESS}/auth/1.0 -U testuser:swift -K ‘{swift_secret_key}’ list - -Replace ``{IP ADDRESS}`` with the public IP address of the gateway server and -``{swift_secret_key}`` with its value from the output of -``radosgw-admin key create`` command executed for the ``swift`` user. - -For example:: - - swift -A http://10.19.143.116/auth/1.0 -U testuser:swift -K ‘244+fz2gSqoHwR3lYtSbIyomyPHf3i7rgSJrF/IA’ list - -The output should be:: - - my-new-bucket - - -.. _Configuration Reference - Pools: ../config-ref#pools -.. _Pool Configuration: ../../rados/configuration/pool-pg-config-ref/ -.. _Pools: ../../rados/operations/pools -.. _User Management: ../../rados/operations/user-management -.. _Backport support for UDS in Ubuntu Trusty: https://bugs.launchpad.net/ubuntu/+source/apache2/+bug/1411030 -.. _Admin Guide: ../admin diff --git a/ceph/doc/radosgw/config-ref.rst b/ceph/doc/radosgw/config-ref.rst index 8a9c39e85..ac96193cc 100644 --- a/ceph/doc/radosgw/config-ref.rst +++ b/ceph/doc/radosgw/config-ref.rst @@ -7,6 +7,11 @@ The following settings may added to the Ceph configuration file (i.e., usually settings may contain default values. If you do not specify each setting in the Ceph configuration file, the default value will be set automatically. +Configuration variables set under the ``[client.radosgw.{instance-name}]`` +section will not apply to rgw or radosgw-admin commands without an instance-name +specified in the command. Thus variables meant to be applied to all RGW +instances or all radosgw-admin commands can be put into the ``[global]`` or the +``[client]`` section to avoid specifying instance-name. ``rgw data`` @@ -294,29 +299,13 @@ Ceph configuration file, the default value will be set automatically. a value of zero indicates there is no sharding. It is not recommended to set a value too large (e.g. thousand) as it increases the cost for bucket listing. + This variable should be set in the client or global sections + so that it is automatically applied to radosgw-admin commands. :Type: Integer :Default: ``0`` -``rgw num zone opstate shards`` - -:Description: The maximum number of shards for keeping inter-region copy - progress information. - -:Type: Integer -:Default: ``128`` - - -``rgw opstate ratelimit sec`` - -:Description: The minimum time between opstate updates on a single upload. - ``0`` disables the ratelimit. - -:Type: Integer -:Default: ``30`` - - ``rgw curl wait timeout ms`` :Description: The timeout in milliseconds for certain ``curl`` calls. @@ -352,10 +341,41 @@ Ceph configuration file, the default value will be set automatically. :Default: ``false`` +``rgw bucket quota ttl`` + +:Description: The amount of time in seconds cached quota information is + trusted. After this timeout, the quota information will be + re-fetched from the cluster. +:Type: Integer +:Default: ``600`` + + +``rgw user quota bucket sync interval`` + +:Description: The amount of time in seconds bucket quota information is + accumulated before syncing to the cluster. During this time, + other RGW instances will not see the changes in bucket quota + stats from operations on this instance. +:Type: Integer +:Default: ``180`` + + +``rgw user quota sync interval`` + +:Description: The amount of time in seconds user quota information is + accumulated before syncing to the cluster. During this time, + other RGW instances will not see the changes in user quota stats + from operations on this instance. +:Type: Integer +:Default: ``180`` + + ``rgw bucket default quota max objects`` :Description: Default max number of objects per bucket. Set on new users, if no other quota is specified. Has no effect on existing users. + This variable should be set in the client or global sections + so that it is automatically applied to radosgw-admin commands. :Type: Integer :Default: ``-1`` @@ -385,389 +405,96 @@ Ceph configuration file, the default value will be set automatically. :Default: ``-1`` -Regions -======= - -In Ceph v0.67 and beyond, Ceph Object Gateway supports federated deployments and -a global namespace via the notion of regions. A region defines the geographic -location of one or more Ceph Object Gateway instances within one or more zones. - - -Configuring regions differs from typical configuration procedures, because not -all of the settings end up in a Ceph configuration file. In Ceph v0.67 and -beyond, you can list regions, get a region configuration and set a region -configuration. - - -List Regions ------------- - -A Ceph cluster contains a list of regions. To list the regions, execute:: - - sudo radosgw-admin region list - -The ``radosgw-admin`` returns a JSON formatted list of regions. - -.. code-block:: javascript - - { "default_info": { "default_region": "default"}, - "regions": [ - "default"]} - - -Get a Region Map ----------------- - -To list the details of each region, execute:: - - sudo radosgw-admin region-map get - - -.. note:: If you receive a ``failed to read region map`` error, run - ``sudo radosgw-admin region-map update`` first. - - -Get a Region ------------- - -To view the configuration of a region, execute:: - - radosgw-admin region get [--rgw-region=] - -The ``default`` region looks like this: - -.. code-block:: javascript - - {"name": "default", - "api_name": "", - "is_master": "true", - "endpoints": [], - "hostnames": [], - "master_zone": "", - "zones": [ - {"name": "default", - "endpoints": [], - "log_meta": "false", - "log_data": "false"} - ], - "placement_targets": [ - {"name": "default-placement", - "tags": [] }], - "default_placement": "default-placement"} - -Set a Region ------------- - -Defining a region consists of creating a JSON object, specifying at least the -required settings: - -#. ``name``: The name of the region. Required. - -#. ``api_name``: The API name for the region. Optional. - -#. ``is_master``: Determines if the region is the master region. Required. - **note:** You can only have one master region. - -#. ``endpoints``: A list of all the endpoints in the region. For example, - you may use multiple domain names to refer to the same region. Remember to - escape the forward slashes (``\/``). You may also specify a - port (``fqdn:port``) for each endpoint. Optional. - -#. ``hostnames``: A list of all the hostnames in the region. For example, - you may use multiple domain names to refer to the same region. Optional. - The ``rgw dns name`` setting will automatically be included in this list. - You should restart the ``radosgw`` daemon(s) after changing this setting. - -#. ``master_zone``: The master zone for the region. Optional. Uses the default - zone if not specified. **note:** You can only have one master zone per - region. - -#. ``zones``: A list of all zones within the region. Each zone has a - name (required), a list of endpoints (optional), and whether or not the - gateway will log metadata and data operations (false by default). - -#. ``placement_targets``: A list of placement targets (optional). Each - placement target contains a name (required) for the placement target - and a list of tags (optional) so that only users with the tag can use - the placement target (i.e., the user's ``placement_tags`` field in the - user info). - -#. ``default_placement``: The default placement target for the object - index and object data. Set to ``default-placement`` by default. You - may also set a per-user default placement in the user info for each - user. - -To set a region, create a JSON object consisting of the required fields, save -the object to a file (e.g., ``region.json``); then, execute the following -command:: - - sudo radosgw-admin region set --infile region.json - -Where ``region.json`` is the JSON file you created. - - -.. important:: The ``default`` region ``is_master`` setting is ``true`` by - default. If you create a new region and want to make it the master region, - you must either set the ``default`` region ``is_master`` setting to - ``false``, or delete the ``default`` region. - - -Finally, update the map. :: - - sudo radosgw-admin region-map update - - -Set a Region Map ----------------- - -Setting a region map consists of creating a JSON object consisting of one or more -regions, and setting the ``master_region`` for the cluster. Each region in the -region map consists of a key/value pair, where the ``key`` setting is equivalent to -the ``name`` setting for an individual region configuration, and the ``val`` is -a JSON object consisting of an individual region configuration. - -You may only have one region with ``is_master`` equal to ``true``, and it must be -specified as the ``master_region`` at the end of the region map. The following -JSON object is an example of a default region map. - - -.. code-block:: javascript - - { "regions": [ - { "key": "default", - "val": { "name": "default", - "api_name": "", - "is_master": "true", - "endpoints": [], - "hostnames": [], - "master_zone": "", - "zones": [ - { "name": "default", - "endpoints": [], - "log_meta": "false", - "log_data": "false"}], - "placement_targets": [ - { "name": "default-placement", - "tags": []}], - "default_placement": "default-placement" - } - } - ], - "master_region": "default" - } - -To set a region map, execute the following:: - - sudo radosgw-admin region-map set --infile regionmap.json - -Where ``regionmap.json`` is the JSON file you created. Ensure that you have -zones created for the ones specified in the region map. Finally, update the map. -:: - - sudo radosgw-admin regionmap update - - -Zones -===== - -In Ceph v0.67 and beyond, Ceph Object Gateway supports the notion of zones. A -zone defines a logical group consisting of one or more Ceph Object Gateway -instances. - -Configuring zones differs from typical configuration procedures, because not -all of the settings end up in a Ceph configuration file. In Ceph v0.67 and -beyond, you can list zones, get a zone configuration and set a zone -configuration. - - -List Zones ----------- - -To list the zones in a cluster, execute:: - - sudo radosgw-admin zone list - - -Get a Zone ----------- - -To get the configuration of a zone, execute:: +``rgw verify ssl`` - sudo radosgw-admin zone get [--rgw-zone=] - -The ``default`` zone looks like this: - -.. code-block:: javascript - - { "domain_root": ".rgw", - "control_pool": ".rgw.control", - "gc_pool": ".rgw.gc", - "log_pool": ".log", - "intent_log_pool": ".intent-log", - "usage_log_pool": ".usage", - "user_keys_pool": ".users", - "user_email_pool": ".users.email", - "user_swift_pool": ".users.swift", - "user_uid_pool": ".users.uid", - "system_key": { "access_key": "", "secret_key": ""}, - "placement_pools": [ - { "key": "default-placement", - "val": { "index_pool": ".rgw.buckets.index", - "data_pool": ".rgw.buckets"} - } - ] - } - - -Set a Zone ----------- - -Configuring a zone involves specifying a series of Ceph Object Gateway pools. -For consistency, we recommend using a pool prefix that is -the same as the zone name. See `Pools`_ for details of configuring pools. - -To set a zone, create a JSON object consisting of the pools, save -the object to a file (e.g., ``zone.json``); then, execute the following -command, replacing ``{zone-name}`` with the name of the zone:: - - sudo radosgw-admin zone set --rgw-zone={zone-name} --infile zone.json +:Description: Verify SSL certificates while making requests. +:Type: Boolean +:Default: ``true`` -Where ``zone.json`` is the JSON file you created. +Multisite Settings +================== -Region/Zone Settings -==================== +.. versionadded:: Jewel You may include the following settings in your Ceph configuration file under each ``[client.radosgw.{instance-name}]`` instance. -.. versionadded:: v.67 - ``rgw zone`` -:Description: The name of the zone for the gateway instance. +:Description: The name of the zone for the gateway instance. If no zone is + set, a cluster-wide default can be configured with the command + ``radosgw-admin zone default``. :Type: String :Default: None -.. versionadded:: v.67 +``rgw zonegroup`` + +:Description: The name of the zonegroup for the gateway instance. If no + zonegroup is set, a cluster-wide default can be configured with + the command ``radosgw-admin zonegroup default``. +:Type: String +:Default: None + -``rgw region`` +``rgw realm`` -:Description: The name of the region for the gateway instance. +:Description: The name of the realm for the gateway instance. If no realm is + set, a cluster-wide default can be configured with the command + ``radosgw-admin realm default``. :Type: String :Default: None -.. versionadded:: v.67 +``rgw run sync thread`` -``rgw default region info oid`` +:Description: If there are other zones in the realm to sync from, spawn threads + to handle the sync of data and metadata. +:Type: Boolean +:Default: ``true`` -:Description: The OID for storing the default region. We do not recommend - changing this setting. - -:Type: String -:Default: ``default.region`` - - - -Pools -===== - -Ceph zones map to a series of Ceph Storage Cluster pools. - -.. topic:: Manually Created Pools vs. Generated Pools - - If you provide write capabilities to the user key for your Ceph Object - Gateway, the gateway has the ability to create pools automatically. This - is convenient, but the Ceph Object Storage Cluster uses the default - values for the number of placement groups (which may not be ideal) or the - values you specified in your Ceph configuration file. If you allow the - Ceph Object Gateway to create pools automatically, ensure that you have - reasonable defaults for the number of placement groups. See - `Pool Configuration`_ for details. See `Cluster Pools`_ for details on - creating pools. - -The default pools for the Ceph Object Gateway's default zone include: - -- ``.rgw`` -- ``.rgw.control`` -- ``.rgw.gc`` -- ``.log`` -- ``.intent-log`` -- ``.usage`` -- ``.users`` -- ``.users.email`` -- ``.users.swift`` -- ``.users.uid`` - -You have significant discretion in determining how you want a zone to access -pools. You can create pools on a per zone basis, or use the same pools for -multiple zones. As a best practice, we recommend having a separate set of pools -for your master zone and your secondary zones in each region. When creating -pools for a specific zone, consider prepending the region name and zone name to -the default pool names. For example: - -- ``.region1-zone1.domain.rgw`` -- ``.region1-zone1.rgw.control`` -- ``.region1-zone1.rgw.gc`` -- ``.region1-zone1.log`` -- ``.region1-zone1.intent-log`` -- ``.region1-zone1.usage`` -- ``.region1-zone1.users`` -- ``.region1-zone1.users.email`` -- ``.region1-zone1.users.swift`` -- ``.region1-zone1.users.uid`` - - -Ceph Object Gateways store data for the bucket index (``index_pool``) and bucket -data (``data_pool``) in placement pools. These may overlap--i.e., you may use -the same pool for the index and the data. The index pool for default -placement is ``.rgw.buckets.index`` and for the data pool for default placement -is ``.rgw.buckets``. See `Zones`_ for details on specifying pools in a zone -configuration. - - -.. deprecated:: v.67 - -``rgw cluster root pool`` - -:Description: The Ceph Storage Cluster pool to store ``radosgw`` metadata for - this instance. Not used in Ceph version v.67 and later. Use - ``rgw zone root pool`` instead. -:Type: String -:Required: No -:Default: ``.rgw.root`` -:Replaced By: ``rgw zone root pool`` +``rgw data log window`` +:Description: The data log entries window in seconds. +:Type: Integer +:Default: ``30`` -.. versionadded:: v.67 -``rgw region root pool`` +``rgw data log changes size`` -:Description: The pool for storing all region-specific information. - Not used in Ceph version ``Jewel``. -:Type: String -:Default: ``.rgw.root`` +:Description: The number of in-memory entries to hold for the data changes log. +:Type: Integer +:Default: ``1000`` -.. versionadded:: Jewel -``rgw zonegroup root pool`` +``rgw data log obj prefix`` -:Description: The pool for storing all zonegroup-specific information. +:Description: The object name prefix for the data log. :Type: String -:Default: ``.rgw.root`` +:Default: ``data_log`` -.. versionadded:: v.67 +``rgw data log num shards`` -``rgw zone root pool`` +:Description: The number of shards (objects) on which to keep the + data changes log. -:Description: The pool for storing zone-specific information. -:Type: String -:Default: ``.rgw.root`` +:Type: Integer +:Default: ``128`` + + +``rgw md log max shards`` + +:Description: The maximum number of shards for the metadata log. +:Type: Integer +:Default: ``64`` + +.. important:: The values of ``rgw data log num shards`` and + ``rgw md log max shards`` should not be changed after sync has + started. Swift Settings @@ -970,50 +697,6 @@ Logging Settings :Default: ``false`` -``rgw data log window`` - -:Description: The data log entries window in seconds. -:Type: Integer -:Default: ``30`` - - -``rgw data log changes size`` - -:Description: The number of in-memory entries to hold for the data changes log. -:Type: Integer -:Default: ``1000`` - - -``rgw data log num shards`` - -:Description: The number of shards (objects) on which to keep the - data changes log. - -:Type: Integer -:Default: ``128`` - - -``rgw data log obj prefix`` - -:Description: The object name prefix for the data log. -:Type: String -:Default: ``data_log`` - - -``rgw replica log obj prefix`` - -:Description: The object name prefix for the replica log. -:Type: String -:Default: ``replica log`` - - -``rgw md log max shards`` - -:Description: The maximum number of shards for the metadata log. -:Type: Integer -:Default: ``64`` - - Keystone Settings ================= diff --git a/ceph/doc/radosgw/encryption.rst b/ceph/doc/radosgw/encryption.rst index 0097b1b00..a7bb7e2e9 100644 --- a/ceph/doc/radosgw/encryption.rst +++ b/ceph/doc/radosgw/encryption.rst @@ -25,7 +25,7 @@ Key Management Service ====================== This mode allows keys to be stored in a secure key management service and -retrieved on demand by the Ceph Object Gateway to service requests to encrypt +retrieved on demand by the Ceph Object Gateway to serve requests to encrypt or decrypt data. This is implemented in S3 according to the `Amazon SSE-KMS`_ specification. diff --git a/ceph/doc/radosgw/federated-config.rst b/ceph/doc/radosgw/federated-config.rst deleted file mode 100644 index 6746c7bcd..000000000 --- a/ceph/doc/radosgw/federated-config.rst +++ /dev/null @@ -1,825 +0,0 @@ -================================ - Configuring Federated Gateways -================================ - -.. versionadded:: 0.67 Dumpling - -In Ceph version 0.67 Dumpling and beyond, you may configure each :term:`Ceph -Object Gateway` to participate in a federated architecture, with multiple -regions, and with multiple zones for a region. - -- **Region**: A region represents a *logical* geographic area and contains one - or more zones. A cluster with multiple regions must specify a master region. - -- **Zone**: A zone is a *logical* grouping of one or more Ceph Object Gateway - instance(s). A region has a master zone that processes client requests. - -.. important:: Only write objects to the master zone in a region. You may read - objects from secondary zones. Currently, the Gateway does not prevent you - from writing to a secondary zone, but **DON'T DO IT**. - - -Background -========== - -When you deploy a :term:`Ceph Object Store` service that spans geographical -locales, configuring Ceph Object Gateway regions and metadata synchronization -agents enables the service to maintain a global namespace, even though Ceph -Object Gateway instances run in different geographic locales and potentially on -different Ceph Storage Clusters. When you separate one or more Ceph Object -Gateway instances within a region into separate logical containers to maintain -an extra copy (or copies) of the data, configuring Ceph Object Gateway zones and -data synchronization agents enables the service to maintain one or more -copy(ies) of the master zone's data. Extra copies of the data are important for -failover, backup and disaster recovery. - -You may deploy a single Ceph Storage Cluster with a federated architecture if -you have low latency network connections (this isn't recommended). You may also -deploy one Ceph Storage Cluster per region with a separate set of pools for -each zone (typical). You may also deploy a separate Ceph Storage Cluster for -each zone if your requirements and resources warrant this level of redundancy. - - -About this Guide -================ - -In the following sections, we will demonstrate how to configure a federated -cluster in two logical steps: - -- **Configure a Master Region:** This section of the guide describes how to - set up a region with multiple zones, and how to synchronize data between the - master zone and the secondary zone(s) within the master region. - -- **Configure a Secondary Region:** This section of the guide describes how - to repeat the section on setting up a master region and multiple zones so - that you have two regions with intra-zone synchronization in each region. - Finally, you will learn how to set up a metadata synchronization agent so - that you can maintain a global namespace for the regions in your cluster. - - - -Configure a Master Region -========================= - -This section provides an exemplary procedure for setting up a region, and two -zones within the region. The cluster will comprise two gateway daemon -instances--one per zone. This region will serve as the master region. - - -Naming for the Master Region ----------------------------- - -Before configuring the cluster, defining region, zone and instance names will -help you manage your cluster. Let's assume the region represents the United -States, and we refer to it by its standard abbreviation. - -- United States: ``us`` - -Let's assume the zones represent the Eastern and Western United States. For -continuity, our naming convention will use ``{region name}-{zone name}`` format, -but you can use any naming convention you prefer. - -- United States, East Region: ``us-east`` -- United States, West Region: ``us-west`` - -Finally, let's assume that zones may have more than one Ceph Object Gateway -instance per zone. For continuity, our naming convention will use -``{region name}-{zone name}-{instance}`` format, but you can use any naming -convention you prefer. - - -- United States Region, Master Zone, Instance 1: ``us-east-1`` -- United States Region, Secondary Zone, Instance 1: ``us-west-1`` - - -Create Pools ------------- - -You may have a Ceph Storage Cluster for the entire region or a Ceph Storage -Cluster for each zone. - -For continuity, our naming convention will use ``{region name}-{zone name}`` -format prepended to the pool name, but you can use any naming convention you -prefer. For example: - - -- ``.us-east.rgw.root`` -- ``.us-east.rgw.control`` -- ``.us-east.rgw.gc`` -- ``.us-east.rgw.buckets`` -- ``.us-east.rgw.buckets.index`` -- ``.us-east.rgw.buckets.extra`` -- ``.us-east.log`` -- ``.us-east.intent-log`` -- ``.us-east.usage`` -- ``.us-east.users`` -- ``.us-east.users.email`` -- ``.us-east.users.swift`` -- ``.us-east.users.uid`` - -| - -- ``.us-west.rgw.root`` -- ``.us-west.rgw.control`` -- ``.us-west.rgw.gc`` -- ``.us-west.rgw.buckets`` -- ``.us-west.rgw.buckets.index`` -- ``.us-west.rgw.buckets.extra`` -- ``.us-west.log`` -- ``.us-west.intent-log`` -- ``.us-west.usage`` -- ``.us-west.users`` -- ``.us-west.users.email`` -- ``.us-west.users.swift`` -- ``.us-west.users.uid`` - -See `Configuration Reference - Pools`_ for details on the default pools for -gateways. See `Pools`_ for details on creating pools. Execute the following -to create a pool:: - - ceph osd pool create {poolname} {pg-num} {pgp-num} {replicated | erasure} [{erasure-code-profile}] {ruleset-name} {ruleset-number} - - -.. tip:: When adding a large number of pools, it may take some time for your - cluster to return to a ``active + clean`` state. - -.. topic:: CRUSH Maps - - When deploying a Ceph Storage Cluster for the entire region, consider - using a CRUSH rule for the zone such that you do NOT have overlapping - failure domains. See `CRUSH Map`_ for details. - - Ceph supports multiple CRUSH hierarchies and CRUSH rulesets, enabling - great flexibility in the way you configure your gateway. Pools such - as ``rgw.buckets.index`` may benefit from a modestly sized pool of SSDs - for fast performance. Backing storage may benefit from the increased economy - of erasure-coded storage, and/or the improved performance from cache tiering. - -When you have completed this step, execute the following to ensure that -you have created all of the foregoing pools:: - - rados lspools - - -Create a Keyring ----------------- - -Each instance must have a user name and key to communicate with a Ceph Storage -Cluster. In the following steps, we use an admin node to create a keyring. -Then, we create a client user name and key for each instance. Next, we add the -keys to the Ceph Storage Cluster(s). Finally, we distribute the key ring to -each node containing an instance. - -#. Create a keyring. :: - - sudo ceph-authtool --create-keyring /etc/ceph/ceph.client.radosgw.keyring - sudo chmod +r /etc/ceph/ceph.client.radosgw.keyring - - -#. Generate a Ceph Object Gateway user name and key for each instance. :: - - sudo ceph-authtool /etc/ceph/ceph.client.radosgw.keyring -n client.radosgw.us-east-1 --gen-key - sudo ceph-authtool /etc/ceph/ceph.client.radosgw.keyring -n client.radosgw.us-west-1 --gen-key - - -#. Add capabilities to each key. See `Configuration Reference - Pools`_ for details - on the effect of write permissions for the monitor and creating pools. :: - - sudo ceph-authtool -n client.radosgw.us-east-1 --cap osd 'allow rwx' --cap mon 'allow rwx' /etc/ceph/ceph.client.radosgw.keyring - sudo ceph-authtool -n client.radosgw.us-west-1 --cap osd 'allow rwx' --cap mon 'allow rwx' /etc/ceph/ceph.client.radosgw.keyring - - -#. Once you have created a keyring and key to enable the Ceph Object Gateway - with access to the Ceph Storage Cluster, add each key as an entry to your - Ceph Storage Cluster(s). For example:: - - sudo ceph -k /etc/ceph/ceph.client.admin.keyring auth add client.radosgw.us-east-1 -i /etc/ceph/ceph.client.radosgw.keyring - sudo ceph -k /etc/ceph/ceph.client.admin.keyring auth add client.radosgw.us-west-1 -i /etc/ceph/ceph.client.radosgw.keyring - - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four users **after** - you create the master region and the secondary region. - - -Install Apache/FastCGI ----------------------- - -For each :term:`Ceph Node` that runs a :term:`Ceph Object Gateway` daemon -instance, you must install Apache, FastCGI, the Ceph Object Gateway daemon -(``radosgw``) and the Ceph Object Gateway Sync Agent (``radosgw-agent``). -See `Install Ceph Object Gateway`_ for details. - - -Create Data Directories ------------------------ - -Create data directories for each daemon instance on their respective -hosts. :: - - ssh {us-east-1} - sudo mkdir -p /var/lib/ceph/radosgw/ceph-radosgw.us-east-1 - - ssh {us-west-1} - sudo mkdir -p /var/lib/ceph/radosgw/ceph-radosgw.us-west-1 - - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four data directories - **after** you create the master region and the secondary region. - - -Create a Gateway Configuration ------------------------------- - -For each instance, create an Ceph Object Gateway configuration file under the -``/etc/apache2/sites-available`` directory on the host(s) where you installed -the Ceph Object Gateway daemon(s). See below for an exemplary embodiment of a -gateway configuration as discussed in the following text. - -.. literalinclude:: rgw.conf - :language: ini - -#. Replace the ``/{path}/{socket-name}`` entry with path to the socket and - the socket name. For example, - ``/var/run/ceph/client.radosgw.us-east-1.sock``. Ensure that you use the - same path and socket name in your ``ceph.conf`` entry. - -#. Replace the ``{fqdn}`` entry with the fully-qualified domain name of the - server. - -#. Replace the ``{email.address}`` entry with the email address for the - server administrator. - -#. Add a ``ServerAlias`` if you wish to use S3-style subdomains - (of course you do). - -#. Save the configuration to a file (e.g., ``rgw-us-east.conf``). - -Repeat the process for the secondary zone (e.g., ``rgw-us-west.conf``). - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four gateway - configuration files on the respective nodes **after** - you create the master region and the secondary region. - - -Finally, if you enabled SSL, make sure that you set the port to your SSL port -(usually 443) and your configuration file includes the following:: - - SSLEngine on - SSLCertificateFile /etc/apache2/ssl/apache.crt - SSLCertificateKeyFile /etc/apache2/ssl/apache.key - SetEnv SERVER_PORT_SECURE 443 - - -Enable the Configuration ------------------------- - -For each instance, enable the gateway configuration and disable the -default site. - -#. Enable the site for the gateway configuration. :: - - sudo a2ensite {rgw-conf-filename} - -#. Disable the default site. :: - - sudo a2dissite default - -.. note:: Failure to disable the default site can lead to problems. - - -Add a FastCGI Script --------------------- - -FastCGI requires a script for each Ceph Object Gateway instance to -enable the S3-compatible interface. To create the script, execute -the following procedures. - - -#. Go to the ``/var/www`` directory. :: - - cd /var/www - -#. Open an editor with the file name ``s3gw.fcgi``. **Note:** The configuration - file specifies this filename. :: - - sudo vim s3gw.fcgi - -#. Add a shell script with ``exec`` and the path to the gateway binary, - the path to the Ceph configuration file, and the user name (``-n``; - the same user name created in step 2 of `Create a Keyring`_. - Copy the following into the editor. :: - - #!/bin/sh - exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n client.radosgw.{ID} - - For example:: - - #!/bin/sh - exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n client.radosgw.us-east-1 - -#. Save the file. - -#. Change the permissions on the file so that it is executable. :: - - sudo chmod +x s3gw.fcgi - - -Repeat the process for the secondary zone. - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four FastCGI scripts - **after** you create the master region and the secondary region. - - - -Add Instances to Ceph Config File ---------------------------------- - -On an admin node, add an entry for each instance in the Ceph configuration file -for your Ceph Storage Cluster(s). For example:: - - [global] - rgw region root pool = .us.rgw.root # Deprecated in Jewel - rgw zonegroup root pool = .us.rgw.root # From Jewel - - [client.radosgw.us-east-1] - rgw region = us - rgw zone = us-east - rgw zone root pool = .us-east.rgw.root - keyring = /etc/ceph/ceph.client.radosgw.keyring - rgw dns name = {hostname} - rgw socket path = /var/run/ceph/$name.sock - host = {host-name} - - [client.radosgw.us-west-1] - rgw region = us - rgw zone = us-west - rgw zone root pool = .us-west.rgw.root - keyring = /etc/ceph/ceph.client.radosgw.keyring - rgw dns name = {hostname} - rgw socket path = /var/run/ceph/$name.sock - host = {host-name} - - -Then, update each :term:`Ceph Node` with the updated Ceph configuration -file. For example:: - - ceph-deploy --overwrite-conf config push {node1} {node2} {nodex} - - -.. note:: When you use this procedure to configure the secondary region, - replace ``us`` with ``eu`` for the name, region, pools and zones. - You will have a total of four entries **after** - you create the master region and the secondary region. - - - -Create a Region ---------------- - -#. Configure a region infile called ``us.json`` for the ``us`` region. - - Copy the contents of the following example to a text editor. Set - ``is_master`` to ``true``. Replace ``{fqdn}`` with the fully-qualified - domain name of the endpoint. It will specify a master zone as ``us-east`` - and list it in the ``zones`` list along with the ``us-west`` zone. - See `Configuration Reference - Regions`_ for details.:: - - { "name": "us", - "api_name": "us", - "is_master": "true", - "endpoints": [ - "http:\/\/{fqdn}:80\/"], - "master_zone": "us-east", - "zones": [ - { "name": "us-east", - "endpoints": [ - "http:\/\/{fqdn}:80\/"], - "log_meta": "true", - "log_data": "true"}, - { "name": "us-west", - "endpoints": [ - "http:\/\/{fqdn}:80\/"], - "log_meta": "true", - "log_data": "true"}], - "placement_targets": [ - { - "name": "default-placement", - "tags": [] - } - ], - "default_placement": "default-placement"} - - -#. Create the ``us`` region using the ``us.json`` infile you just - created. :: - - radosgw-admin region set --infile us.json --name client.radosgw.us-east-1 - -#. Delete the default region (if it exists). :: - - rados -p .us.rgw.root rm region_info.default - -#. Set the ``us`` region as the default region. :: - - radosgw-admin region default --rgw-region=us --name client.radosgw.us-east-1 - - Only one region can be the default region for a cluster. - -#. Update the region map. :: - - radosgw-admin regionmap update --name client.radosgw.us-east-1 - - -If you use different Ceph Storage Cluster instances for regions, you should -repeat steps 2, 4 and 5 in by executing them with ``--name -client.radosgw-us-west-1``. You may also export the region map from the initial -gateway instance and import it followed by updating the region map. - -.. note:: When you use this procedure to configure the secondary region, - replace ``us`` with ``eu``. You will have a total of two regions **after** - you create the master region and the secondary region. - - - -Create Zones ------------- - -#. Configure a zone infile called ``us-east.json`` for the - ``us-east`` zone. - - Copy the contents of the following example to a text editor. - This configuration uses pool names prepended with the region name and - zone name. See `Configuration Reference - Pools`_ for additional details on - gateway pools. See `Configuration Reference - Zones`_ for additional - details on zones. :: - - { "domain_root": ".us-east.domain.rgw", - "control_pool": ".us-east.rgw.control", - "gc_pool": ".us-east.rgw.gc", - "log_pool": ".us-east.log", - "intent_log_pool": ".us-east.intent-log", - "usage_log_pool": ".us-east.usage", - "user_keys_pool": ".us-east.users", - "user_email_pool": ".us-east.users.email", - "user_swift_pool": ".us-east.users.swift", - "user_uid_pool": ".us-east.users.uid", - "system_key": { "access_key": "", "secret_key": ""}, - "placement_pools": [ - { "key": "default-placement", - "val": { "index_pool": ".us-east.rgw.buckets.index", - "data_pool": ".us-east.rgw.buckets"} - } - ] - } - - -#. Add the ``us-east`` zone using the ``us-east.json`` infile you - just created in both the east and west pools by specifying their respective - user names (i.e., ``--name``). :: - - radosgw-admin zone set --rgw-zone=us-east --infile us-east.json --name client.radosgw.us-east-1 - radosgw-admin zone set --rgw-zone=us-east --infile us-east.json --name client.radosgw.us-west-1 - - Repeat step 1 to create a zone infile for ``us-west``. Then add the zone - using the ``us-west.json`` infile in both the east and west pools by - specifying their respective user names (i.e., ``--name``). :: - - radosgw-admin zone set --rgw-zone=us-west --infile us-west.json --name client.radosgw.us-east-1 - radosgw-admin zone set --rgw-zone=us-west --infile us-west.json --name client.radosgw.us-west-1 - - -#. Delete the default zone (if it exists). :: - - rados -p .us-east.rgw.root rm zone_info.default - rados -p .us-west.rgw.root rm zone_info.default - - -#. Update the region map. :: - - radosgw-admin regionmap update --name client.radosgw.us-east-1 - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four zones **after** - you create the master zone and the secondary zone in each region. - - -Create Zone Users ------------------ - -Ceph Object Gateway stores zone users in the zone pools. So you must create zone -users after configuring the zones. Copy the ``access_key`` and ``secret_key`` -fields for each user so you can update your zone configuration once you complete -this step. :: - - radosgw-admin user create --uid="us-east" --display-name="Region-US Zone-East" --name client.radosgw.us-east-1 --system - radosgw-admin user create --uid="us-west" --display-name="Region-US Zone-West" --name client.radosgw.us-west-1 --system - - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four zone users - **after** you create the master region and the secondary region and their - zones. These users are different from the users created in `Create a - Keyring`_. - - -Update Zone Configurations --------------------------- - -You must update the zone configuration with zone users so that -the synchronization agents can authenticate with the zones. - -#. Open your ``us-east.json`` zone configuration file and paste the contents of - the ``access_key`` and ``secret_key`` fields from the step of creating - zone users into the ``system_key`` field of your zone configuration - infile. :: - - { "domain_root": ".us-east.domain.rgw", - "control_pool": ".us-east.rgw.control", - "gc_pool": ".us-east.rgw.gc", - "log_pool": ".us-east.log", - "intent_log_pool": ".us-east.intent-log", - "usage_log_pool": ".us-east.usage", - "user_keys_pool": ".us-east.users", - "user_email_pool": ".us-east.users.email", - "user_swift_pool": ".us-east.users.swift", - "user_uid_pool": ".us-east.users.uid", - "system_key": { - "access_key": "{paste-access_key-here}", - "secret_key": "{paste-secret_key-here}" - }, - "placement_pools": [ - { "key": "default-placement", - "val": { "index_pool": ".us-east.rgw.buckets.index", - "data_pool": ".us-east.rgw.buckets"} - } - ] - } - -#. Save the ``us-east.json`` file. Then, update your zone configuration. :: - - radosgw-admin zone set --rgw-zone=us-east --infile us-east.json --name client.radosgw.us-east-1 - radosgw-admin zone set --rgw-zone=us-east --infile us-east.json --name client.radosgw.us-west-1 - -#. Repeat step 1 to update the zone infile for ``us-west``. Then, update - your zone configuration. :: - - radosgw-admin zone set --rgw-zone=us-west --infile us-west.json --name client.radosgw.us-east-1 - radosgw-admin zone set --rgw-zone=us-west --infile us-west.json --name client.radosgw.us-west-1 - - -.. note:: When you use this procedure to configure the secondary region, - replace ``us-`` with ``eu-``. You will have a total of four zones **after** - you create the master zone and the secondary zone in each region. - - -Restart Services ----------------- - -Once you have redeployed your Ceph configuration files, we recommend restarting -your Ceph Storage Cluster(s) and Apache instances. - -For Ubuntu, use the following on each :term:`Ceph Node`:: - - sudo restart ceph-all - -For Red Hat/CentOS, use the following:: - - sudo /etc/init.d/ceph restart - -To ensure that all components have reloaded their configurations, for each -gateway instance we recommend restarting the ``apache2`` service. For example:: - - sudo service apache2 restart - - -Start Gateway Instances ------------------------ - -Start up the ``radosgw`` service. :: - - sudo /etc/init.d/radosgw start - -If you are running multiple instances on the same host, you must specify the -user name. :: - - sudo /etc/init.d/radosgw start --name client.radosgw.us-east-1 - - -Open a browser and check the endpoints for each zone. A simple HTTP request -to the domain name should return the following: - -.. code-block:: xml - - - - anonymous - - - - - - -Configure a Secondary Region -============================ - -This section provides an exemplary procedure for setting up a cluster with -multiple regions. Configuring a cluster that spans regions requires maintaining -a global namespace, so that there are no namespace clashes among object names -stored across in different regions. - -This section extends the procedure in `Configure a Master Region`_, but -changes the region name and modifies a few procedures. See the following -sections for details. - - -Naming for the Secondary Region -------------------------------- - -Before configuring the cluster, defining region, zone and instance names will -help you manage your cluster. Let's assume the region represents the European -Union, and we refer to it by its standard abbreviation. - -- European Union: ``eu`` - -Let's assume the zones represent the Eastern and Western European Union. For -continuity, our naming convention will use ``{region name}-{zone name}`` -format, but you can use any naming convention you prefer. - -- European Union, East Region: ``eu-east`` -- European Union, West Region: ``eu-west`` - -Finally, let's assume that zones may have more than one Ceph Object Gateway -instance per zone. For continuity, our naming convention will use -``{region name}-{zone name}-{instance}`` format, but you can use any naming -convention you prefer. - -- European Union Region, Master Zone, Instance 1: ``eu-east-1`` -- European Union Region, Secondary Zone, Instance 1: ``eu-west-1`` - - -Configuring a Secondary Region ------------------------------- - -Repeat the exemplary procedure of `Configure a Master Region`_ -with the following differences: - -#. Use `Naming for the Secondary Region`_ in lieu of `Naming for - the Master Region`_. - -#. `Create Pools`_ using ``eu`` instead of ``us``. - -#. `Create a Keyring`_ and the corresponding keys using ``eu`` instead of - ``us``. You may use the same keyring if you desire, but ensure that you - create the keys on the Ceph Storage Cluster for that region (or region - and zone). - -#. `Install Apache/FastCGI`_. - -#. `Create Data Directories`_ using ``eu`` instead of ``us``. - -#. `Create a Gateway Configuration`_ using ``eu`` instead of ``us`` for - the socket names. - -#. `Enable the Configuration`_. - -#. `Add a FastCGI Script`_ using ``eu`` instead of ``us`` for the user names. - -#. `Add Instances to Ceph Config File`_ using ``eu`` instead of ``us`` for the - pool names. - -#. `Create a Region`_ using ``eu`` instead of ``us``. Set ``is_master`` to - ``false``. For consistency, create the master region in the secondary region - too. :: - - radosgw-admin region set --infile us.json --name client.radosgw.eu-east-1 - -#. `Create Zones`_ using ``eu`` instead of ``us``. Ensure that you update the - user name (i.e., ``--name``) so that you create the zones in the correct - cluster. - -#. `Update Zone Configurations`_ using ``eu`` instead of ``us``. - -#. Create zones from master region in the secondary region. :: - - radosgw-admin zone set --rgw-zone=us-east --infile us-east.json --name client.radosgw.eu-east-1 - radosgw-admin zone set --rgw-zone=us-east --infile us-east.json --name client.radosgw.eu-west-1 - radosgw-admin zone set --rgw-zone=us-west --infile us-west.json --name client.radosgw.eu-east-1 - radosgw-admin zone set --rgw-zone=us-west --infile us-west.json --name client.radosgw.eu-west-1 - -#. Create zones from secondary region in the master region. :: - - radosgw-admin zone set --rgw-zone=eu-east --infile eu-east.json --name client.radosgw.us-east-1 - radosgw-admin zone set --rgw-zone=eu-east --infile eu-east.json --name client.radosgw.us-west-1 - radosgw-admin zone set --rgw-zone=eu-west --infile eu-west.json --name client.radosgw.us-east-1 - radosgw-admin zone set --rgw-zone=eu-west --infile eu-west.json --name client.radosgw.us-west-1 - -#. `Restart Services`_. - -#. `Start Gateway Instances`_. - - -Multi-Site Data Replication -=========================== - -The data synchronization agent replicates the data of a master zone to a -secondary zone. The master zone of a region is the source for the secondary zone -of the region and it gets selected automatically. - -.. image:: ../images/zone-sync.png - -To configure the synchronization agent, retrieve the access key and secret for -the source and destination, and the destination URL and port. - -You may use ``radosgw-admin zone list`` to get a list of zone names. You -may use ``radosgw-admin zone get`` to identify the key and secret for the -zone. You may refer to the gateway configuration file you created under -`Create a Gateway Configuration`_ to identify the port number. - -You only need the hostname and port for a single instance (assuming all -gateway instances in a region/zone access the same Ceph Storage Cluster). -Specify these values in a configuration file -(e.g., ``cluster-data-sync.conf``), and include a ``log_file`` name. - - -For example: - -.. code-block:: ini - - src_access_key: {source-access-key} - src_secret_key: {source-secret-key} - destination: https://zone-name.fqdn.com:port - dest_access_key: {destination-access-key} - dest_secret_key: {destination-secret-key} - log_file: {log.filename} - -A concrete example may look like this: - -.. code-block:: ini - - src_access_key: DG8RE354EFPZBICHIAF0 - src_secret_key: i3U0HiRP8CXaBWrcF8bbh6CbsxGYuPPwRkixfFSb - destination: https://us-west.storage.net:80 - dest_access_key: U60RFI6B08F32T2PD30G - dest_secret_key: W3HuUor7Gl1Ee93pA2pq2wFk1JMQ7hTrSDecYExl - log_file: /var/log/radosgw/radosgw-sync-us-east-west.log - -To activate the data synchronization agent, open a terminal and -execute the following:: - - radosgw-agent -c region-data-sync.conf - -When the synchronization agent is running, you should see output -indicating that the agent is synchronizing shards of data. :: - - INFO:radosgw_agent.sync:Starting incremental sync - INFO:radosgw_agent.worker:17910 is processing shard number 0 - INFO:radosgw_agent.worker:shard 0 has 0 entries after '' - INFO:radosgw_agent.worker:finished processing shard 0 - INFO:radosgw_agent.worker:17910 is processing shard number 1 - INFO:radosgw_agent.sync:1/64 shards processed - INFO:radosgw_agent.worker:shard 1 has 0 entries after '' - INFO:radosgw_agent.worker:finished processing shard 1 - INFO:radosgw_agent.sync:2/64 shards processed - ... - -.. note:: You must have an agent for each source-destination pair. - - -Inter-Region Metadata Replication -================================= - -The data synchronization agent replicates the metadata of master zone in the -master region to a master zone in a secondary region. Metadata consists of -gateway users and buckets, but not the objects within the buckets--ensuring a -unified namespace across the cluster. The master zone of the master region is -the source for the master zone of the secondary region and it gets selected -automatically. - -.. image:: ../images/region-sync.png - :align: center - -Follow the same steps in `Multi-Site Data Replication`_ by specifying the master -zone of the master region as the source zone and the master zone of the -secondary region as the secondary zone. When activating the ``radosgw-agent``, -specify ``--metadata-only`` so that it only copies metadata. For example:: - - radosgw-agent -c inter-region-data-sync.conf --metadata-only - -Once you have completed the foregoing procedure, you should have a cluster -consisting of a master region (``us``) and a secondary region (``eu``) where -there is a unified namespace between the two regions. - - - -.. _CRUSH Map: ../../rados/operations/crush-map -.. _Install Ceph Object Gateway: ../../install/install-ceph-gateway -.. _Ceph configuration file: ../../rados/configuration/ceph-conf -.. _Configuration Reference - Pools: ../config-ref#pools -.. _Configuration Reference - Regions: ../config-ref#regions -.. _Configuration Reference - Zones: ../config-ref#zones -.. _Pools: ../../rados/operations/pools -.. _Simple Configuration: ../config-fcgi diff --git a/ceph/doc/radosgw/index.rst b/ceph/doc/radosgw/index.rst index 7bf08cdbe..d64e6dd6b 100644 --- a/ceph/doc/radosgw/index.rst +++ b/ceph/doc/radosgw/index.rst @@ -13,7 +13,7 @@ Ceph Storage Clusters. :term:`Ceph Object Storage` supports two interfaces: that is compatible with a large subset of the OpenStack Swift API. Ceph Object Storage uses the Ceph Object Gateway daemon (``radosgw``), which is -a FastCGI module for interacting with a Ceph Storage Cluster. Since it +an HTTP server for interacting with a Ceph Storage Cluster. Since it provides interfaces compatible with OpenStack Swift and Amazon S3, the Ceph Object Gateway has its own user management. Ceph Object Gateway can store data in the same Ceph Storage Cluster used to store data from Ceph Filesystem clients @@ -37,9 +37,8 @@ you may write data with one API and retrieve it with the other. :maxdepth: 1 Manual Install w/Civetweb <../../install/install-ceph-gateway> - Simple Configuration w/Apache/FastCGI - Federated Configuration (Deprecated) Multisite Configuration + Configuring Pools Config Reference Admin Guide S3 API @@ -51,8 +50,8 @@ you may write data with one API and retrieve it with the other. Multi-tenancy Compression Server-Side Encryption + Bucket Policy Data Layout in RADOS - Upgrade to Older Versions of Jewel troubleshooting Manpage radosgw <../../man/8/radosgw> Manpage radosgw-admin <../../man/8/radosgw-admin> diff --git a/ceph/doc/radosgw/layout.rst b/ceph/doc/radosgw/layout.rst index b3a6fe2ec..04a525b6a 100644 --- a/ceph/doc/radosgw/layout.rst +++ b/ceph/doc/radosgw/layout.rst @@ -82,12 +82,14 @@ The user ID in RGW is a string, typically the actual user name from the user credentials and not a hashed or mapped identifier. When accessing a user's data, the user record is loaded from an object -"" in pool ".users.uid". +"" in pool "default.rgw.meta" with namespace "users.uid". -Bucket names are represented directly in the pool ".rgw". Bucket record is +Bucket names are represented in the pool "default.rgw.meta" with namespace +"root". Bucket record is loaded in order to obtain so-called marker, which serves as a bucket ID. -The object is located in pool ".rgw.buckets". Object name is "_", +The object is located in pool "default.rgw.buckets.data". +Object name is "_", for example "default.7593.4_image.png", where the marker is "default.7593.4" and the key is "image.png". Since these concatenated names are not parsed, only passed down to RADOS, the choice of the separator is not important and @@ -110,7 +112,8 @@ Bucket and Object Listing ------------------------- Buckets that belong to a given user are listed in an omap of an object named -".buckets" (for example, "foo.buckets") in pool ".users.uid". +".buckets" (for example, "foo.buckets") in pool "default.rgw.meta" +with namespace "users.uid". These objects are accessed when listing buckets, when updating bucket contents, and updating and retrieving bucket statistics (e.g. for quota). @@ -121,7 +124,7 @@ These listings are kept consistent with buckets in pool ".rgw". Objects that belong to a given bucket are listed in a bucket index, as discussed in sub-section 'Bucket Index' above. The default naming -for index objects is ".dir." in pool ".rgw.buckets.index". +for index objects is ".dir." in pool "default.rgw.buckets.index". Footnotes --------- @@ -136,64 +139,66 @@ In Hammer, one LevelDB is used to store omap in each OSD. exist and the 'bucket' metadata contained its information. It is possible to encounter such buckets in old installations. -[3] In Infernalis, a pending commit exists that removes the need of prefixing -all the rgw system pools with a period, and also renames all of these pools. -See Github pull request #4944 "rgw noperiod". +[3] The pool names have been changed starting with the Infernalis release. +If you are looking at an older setup, some details may be different. In +particular there was a different pool for each of the namespaces that are +now being used inside the default.root.meta pool. -Appendix: Compendum -------------------- +Appendix: Compendium +-------------------- Known pools: .rgw.root Unspecified region, zone, and global information records, one per object. -.rgw.control +.rgw.control notify. -.rgw - - .bucket.meta.: # see put_bucket_instance_info() +.rgw.meta + Multiple namespaces with different kinds of metadata: - The tenant is used to disambiguate buckets, but not bucket instances. - Example: + namespace: root + + .bucket.meta.: # see put_bucket_instance_info() - .bucket.meta.prodtx:test%25star:default.84099.6 - .bucket.meta.testcont:default.4126.1 - .bucket.meta.prodtx:testcont:default.84099.4 - prodtx/testcont - prodtx/test%25star - testcont + The tenant is used to disambiguate buckets, but not bucket instances. + Example:: -.rgw.gc - gc. + .bucket.meta.prodtx:test%25star:default.84099.6 + .bucket.meta.testcont:default.4126.1 + .bucket.meta.prodtx:testcont:default.84099.4 + prodtx/testcont + prodtx/test%25star + testcont -.users.uid - Contains _both_ per-user information (RGWUserInfo) in "" objects - and per-user lists of buckets in omaps of ".buckets" objects. - The "" may contain the tenant if non-empty, for example: + namespace: users.uid + Contains _both_ per-user information (RGWUserInfo) in "" objects + and per-user lists of buckets in omaps of ".buckets" objects. + The "" may contain the tenant if non-empty, for example:: - prodtx$prodt - test2.buckets - prodtx$prodt.buckets - test2 + prodtx$prodt + test2.buckets + prodtx$prodt.buckets + test2 -.users.email - Unimportant + namespace: users.email + Unimportant -.users - 47UA98JSTJZ9YAN3OS3O - It's unclear why user ID is not used to name objects in this pool. + namespace: users.keys + 47UA98JSTJZ9YAN3OS3O -.users.swift - test:tester + This allows radosgw to look up users by their access keys during authentication. -.rgw.buckets.index + namespace: users.swift + test:tester + +.rgw.buckets.index Objects are named ".dir.", each contains a bucket index. If the index is sharded, each shard appends the shard index after the marker. -.rgw.buckets +.rgw.buckets.data default.7593.4__shadow_.488urDFerTYXavx4yAd-Op8mxehnvTI_1 _ diff --git a/ceph/doc/radosgw/multisite.rst b/ceph/doc/radosgw/multisite.rst index e81e90142..0c2c44258 100644 --- a/ceph/doc/radosgw/multisite.rst +++ b/ceph/doc/radosgw/multisite.rst @@ -63,7 +63,7 @@ gateway instances, one for each Ceph storage cluster. This guide assumes at least two Ceph storage clusters in geographically separate locations; however, the configuration can work on the same -site. This guide also assumes four Ceph object gateway servers named +site. This guide also assumes two Ceph object gateway servers named ``rgw1`` and ``rgw2``. A multi-site configuration requires a master zone group and a master @@ -74,58 +74,8 @@ In this guide, the ``rgw1`` host will serve as the master zone of the master zone group; and, the ``rgw2`` host will serve as the secondary zone of the master zone group. -Pools -===== - -We recommend using the `Ceph Placement Group’s per Pool -Calculator `__ to calculate a -suitable number of placement groups for the pools the ``ceph-radosgw`` -daemon will create. Set the calculated values as defaults in your Ceph -configuration file. For example: - -:: - - osd pool default pg num = 50 - osd pool default pgp num = 50 - -.. note:: Make this change to the Ceph configuration file on your - storage cluster; then, either make a runtime change to the - configuration so that it will use those defaults when the gateway - instance creates the pools. - -Alternatively, create the pools manually. See -`Pools `__ -for details on creating pools. - -Pool names particular to a zone follow the naming convention -``{zone-name}.pool-name``. For example, a zone named ``us-east`` will -have the following pools: - -- ``.rgw.root`` - -- ``us-east.rgw.control`` - -- ``us-east.rgw.data.root`` - -- ``us-east.rgw.gc`` - -- ``us-east.rgw.log`` - -- ``us-east.rgw.intent-log`` - -- ``us-east.rgw.usage`` - -- ``us-east.rgw.users.keys`` - -- ``us-east.rgw.users.email`` - -- ``us-east.rgw.users.swift`` - -- ``us-east.rgw.users.uid`` - -- ``us-east.rgw.buckets.index`` - -- ``us-east.rgw.buckets.data`` +See `Pools`_ for instructions on creating and tuning pools for Ceph +Object Storage. Configuring a Master Zone @@ -814,8 +764,8 @@ realm. Alternatively, to change which realm is the default, execute: # radosgw-admin realm default --rgw-realm=movies -..note:: When the realm is default, the command line assumes - ``--rgw-realm=`` as an argument. +.. note:: When the realm is default, the command line assumes + ``--rgw-realm=`` as an argument. Delete a Realm ~~~~~~~~~~~~~~ @@ -1504,3 +1454,6 @@ instance. | | keeping inter-zone group | | | | | synchronization progress. | | | +-------------------------------------+-----------------------------------+---------+-----------------------+ + + +.. _`Pools`: ../pools diff --git a/ceph/doc/radosgw/nfs.rst b/ceph/doc/radosgw/nfs.rst new file mode 100644 index 000000000..55b88afe3 --- /dev/null +++ b/ceph/doc/radosgw/nfs.rst @@ -0,0 +1,366 @@ +=== +NFS +=== + +.. versionadded:: Jewel + +Ceph Object Gateway namespaces can now be exported over file-based +access protocols such as NFSv3 and NFSv4, alongside traditional HTTP access +protocols (S3 and Swift). + +In particular, the Ceph Object Gateway can now be configured to +provide file-based access when embedded in the NFS-Ganesha NFS server. + +librgw +====== + +The librgw.so shared library (Unix) provides a loadable interface to +Ceph Object Gateway services, and instantiates a full Ceph Object Gateway +instance on initialization. + +In turn, librgw.so exports rgw_file, a stateful API for file-oriented +access to RGW buckets and objects. The API is general, but its design +is strongly influenced by the File System Abstraction Layer (FSAL) API +of NFS-Ganesha, for which it has been primarily designed. + +A set of Python bindings is also provided. + +Namespace Conventions +===================== + +The implementation conforms to Amazon Web Services (AWS) hierarchical +namespace conventions which map UNIX-style path names onto S3 buckets +and objects. + +The top level of the attached namespace consists of S3 buckets, +represented as NFS directories. Files and directories subordinate to +buckets are each represented as objects, following S3 prefix and +delimiter conventions, with '/' being the only supported path +delimiter [#]_. + +For example, if an NFS client has mounted an RGW namespace at "/nfs", +then a file "/nfs/mybucket/www/index.html" in the NFS namespace +corresponds to an RGW object "www/index.html" in a bucket/container +"mybucket." + +Although it is generally invisible to clients, the NFS namespace is +assembled through concatenation of the corresponding paths implied by +the objects in the namespace. Leaf objects, whether files or +directories, will always be materialized in an RGW object of the +corresponding key name, "" if a file, "/" if a directory. +Non-leaf directories (e.g., "www" above) might only be implied by +their appearance in the names of one or more leaf objects. Directories +created within NFS or directly operated on by an NFS client (e.g., via +an attribute-setting operation such as chown or chmod) always have a +leaf object representation used to store materialized attributes such +as Unix ownership and permissions. + +Supported Operations +==================== + +The RGW NFS interface supports most operations on files and +directories, with the following restrictions: + +- Links, including symlinks, are not supported +- NFS ACLs are not supported + + + Unix user and group ownership and permissions *are* supported + +- Directories may not be moved/renamed + + + files may be moved between directories + +- Only full, sequential *write* i/o is supported + + + i.e., write operations are constrained to be **uploads** + + many typical i/o operations such as editing files in place will necessarily fail as they perform non-sequential stores + + some file utilities *apparently* writing sequentially (e.g., some versions of GNU tar) may fail due to infrequent non-sequential stores + + When mounting via NFS, sequential application i/o can generally be constrained to be written sequentially to the NFS server via a synchronous mount option (e.g. -osync in Linux) + + NFS clients which cannot mount synchronously (e.g., MS Windows) will not be able to upload files + +Security +======== + +The RGW NFS interface provides a hybrid security model with the +following characteristics: + +- NFS protocol security is provided by the NFS-Ganesha server, as negotiated by the NFS server and clients + + + e.g., clients can by trusted (AUTH_SYS), or required to present Kerberos user credentials (RPCSEC_GSS) + + RPCSEC_GSS wire security can be integrity only (krb5i) or integrity and privacy (encryption, krb5p) + + various NFS-specific security and permission rules are available + + * e.g., root-squashing + +- a set of RGW/S3 security credentials (unknown to NFS) is associated with each RGW NFS mount (i.e., NFS-Ganesha EXPORT) + + + all RGW object operations performed via the NFS server will be performed by the RGW user associated with the credentials stored in the export being accessed (currently only RGW and RGW LDAP credentials are supported) + + * additional RGW authentication types such as Keystone are not currently supported + +Configuring an NFS-Ganesha Instance +=================================== + +Each NFS RGW instance is an NFS-Ganesha server instance *embeddding* +a full Ceph RGW instance. + +Therefore, the RGW NFS configuration includes Ceph and Ceph Object +Gateway-specific configuration in a local ceph.conf, as well as +NFS-Ganesha-specific configuration in the NFS-Ganesha config file, +ganesha.conf. + +ceph.conf +--------- + +Required ceph.conf configuration for RGW NFS includes: + +* valid [client.radosgw.{instance-name}] section +* valid values for minimal instance configuration, in particular, an installed and correct ``keyring`` + +Other config variables are optional, front-end-specific and front-end +selection variables (e.g., ``rgw data`` and ``rgw frontends``) are +optional and in some cases ignored. + +A small number of config variables (e.g., ``rgw_namespace_expire_secs``) +are unique to RGW NFS. + +ganesha.conf +------------ + +A strictly minimal ganesha.conf for use with RGW NFS includes one +EXPORT block with embedded FSAL block of type RGW:: + + EXPORT + { + Export_ID={numeric-id}; + Path = "/"; + Pseudo = "/"; + Access_Type = RW; + SecType = "sys"; + NFS_Protocols = 4; + Transport_Protocols = TCP; + + # optional, permit unsquashed access by client "root" user + #Squash = No_Root_Squash; + + FSAL { + Name = RGW; + User_Id = {s3-user-id}; + Access_Key_Id ="{s3-access-key}"; + Secret_Access_Key = "{s3-secret}"; + } + } + +``Export_ID`` must have an integer value, e.g., "77" + +``Path`` (for RGW) should be "/" + +``Pseudo`` defines an NFSv4 pseudo root name (NFSv4 only) + +``SecType = sys;`` allows clients to attach without Kerberos +authentication + +``Squash = No_Root_Squash;`` enables the client root user to override +permissions (Unix convention). When root-squashing is enabled, +operations attempted by the root user are performed as if by the local +"nobody" (and "nogroup") user on the NFS-Ganesha server + +The RGW FSAL additionally supports RGW-specific configuration +variables in the RGW config section:: + + RGW { + cluster = "{cluster name, default 'ceph'}"; + name = "client.rgw.{instance-name}"; + ceph_conf = "/opt/ceph-rgw/etc/ceph/ceph.conf"; + init_args = "-d --debug-rgw=16"; + } + +``cluster`` sets a Ceph cluster name (must match the cluster being exported) + +``name`` sets an RGW instance name (must match the cluster being exported) + +``ceph_conf`` gives a path to a non-default ceph.conf file to use + + +Other useful NFS-Ganesha configuration: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Any EXPORT block which should support NFSv3 should include version 3 +in the NFS_Protocols setting. Additionally, NFSv3 is the last major +version to support the UDP transport. To enable UDP, include it in the +Transport_Protocols setting. For example:: + + EXPORT { + ... + NFS_Protocols = 3,4; + Transport_Protocols = UDP,TCP; + ... + } + +One important family of options pertains to interaction with the Linux +idmapping service, which is used to normalize user and group names +across systems. Details of idmapper integration are not provided here. + +With Linux NFS clients, NFS-Ganesha can be configured +to accept client-supplied numeric user and group identifiers with +NFSv4, which by default stringifies these--this may be useful in small +setups and for experimentation:: + + NFSV4 { + Allow_Numeric_Owners = true; + Only_Numeric_Owners = true; + } + +Troubleshooting +~~~~~~~~~~~~~~~ + +NFS-Ganesha configuration problems are usually debugged by running the +server with debugging options, controlled by the LOG config section. + +NFS-Ganesha log messages are grouped into various components, logging +can be enabled separately for each component. Valid values for +component logging include:: + + *FATAL* critical errors only + *WARN* unusual condition + *DEBUG* mildly verbose trace output + *FULL_DEBUG* verbose trace output + +Example:: + + LOG { + + Components { + MEMLEAKS = FATAL; + FSAL = FATAL; + NFSPROTO = FATAL; + NFS_V4 = FATAL; + EXPORT = FATAL; + FILEHANDLE = FATAL; + DISPATCH = FATAL; + CACHE_INODE = FATAL; + CACHE_INODE_LRU = FATAL; + HASHTABLE = FATAL; + HASHTABLE_CACHE = FATAL; + DUPREQ = FATAL; + INIT = DEBUG; + MAIN = DEBUG; + IDMAPPER = FATAL; + NFS_READDIR = FATAL; + NFS_V4_LOCK = FATAL; + CONFIG = FATAL; + CLIENTID = FATAL; + SESSIONS = FATAL; + PNFS = FATAL; + RW_LOCK = FATAL; + NLM = FATAL; + RPC = FATAL; + NFS_CB = FATAL; + THREAD = FATAL; + NFS_V4_ACL = FATAL; + STATE = FATAL; + FSAL_UP = FATAL; + DBUS = FATAL; + } + # optional: redirect log output + # Facility { + # name = FILE; + # destination = "/tmp/ganesha-rgw.log"; + # enable = active; + } + } + +Running Multiple NFS Gateways +============================= + +Each NFS-Ganesha instance acts as a full gateway endpoint, with the +limitation that currently an NFS-Ganesha instance cannot be configured +to export HTTP services. As with ordinary gateway instances, any +number of NFS-Ganesha instances can be started, exporting the same or +different resources from the cluster. This enables the clustering of +NFS-Ganesha instances. However, this does not imply high availability. + +When regular gateway instances and NFS-Ganesha instances overlap the +same data resources, they will be accessible from both the standard S3 +API and through the NFS-Ganesha instance as exported. You can +co-locate the NFS-Ganesha instance with a Ceph Object Gateway instance +on the same host. + +RGW vs RGW NFS +============== + +Exporting an NFS namespace and other RGW namespaces (e.g., S3 or Swift +via the Civetweb HTTP front-end) from the same program instance is +currently not supported. + +When adding objects and buckets outside of NFS, those objects will +appear in the NFS namespace in the time set by +``rgw_nfs_namespace_expire_secs``, which defaults to 300 seconds (5 minutes). +Override the default value for ``rgw_nfs_namespace_expire_secs`` in the +Ceph configuration file to change the refresh rate. + +If exporting Swift containers that do not conform to valid S3 bucket +naming requirements, set ``rgw_relaxed_s3_bucket_names`` to true in the +[client.radosgw] section of the Ceph configuration file. For example, +if a Swift container name contains underscores, it is not a valid S3 +bucket name and will be rejected unless ``rgw_relaxed_s3_bucket_names`` +is set to true. + +Configuring NFSv4 clients +========================= + +To access the namespace, mount the configured NFS-Ganesha export(s) +into desired locations in the local POSIX namespace. As noted, this +implementation has a few unique restrictions: + +- NFS 4.1 and higher protocol flavors are preferred + + + NFSv4 OPEN and CLOSE operations are used to track upload transactions + +- To upload data successfully, clients must preserve write ordering + + + on Linux and many Unix NFS clients, use the -osync mount option + +Conventions for mounting NFS resources are platform-specific. The +following conventions work on Linux and some Unix platforms: + +From the command line:: + + mount -t nfs -o nfsvers=4,noauto,soft,proto=tcp :/ + +In /etc/fstab:: + +:/ nfs noauto,soft,nfsvers=4.1,sync,proto=tcp 0 0 + +Specify the NFS-Ganesha host name and the path to the mount point on +the client. + +Configuring NFSv3 Clients +========================= + +Linux clients can be configured to mount with NFSv3 by supplying +``nfsvers=3`` and ``noacl`` as mount options. To use UDP as the +transport, add ``proto=udp`` to the mount options. However, TCP is the +preferred transport:: + + :/ nfs noauto,noacl,soft,nfsvers=3,sync,proto=tcp 0 0 + +Configure the NFS Ganesha EXPORT block Protocols setting with version +3 and the Transports setting with UDP if the mount will use version 3 with UDP. + +NFSv3 Semantics +--------------- + +Since NFSv3 does not communicate client OPEN and CLOSE operations to +file servers, RGW NFS cannot use these operations to mark the +beginning and ending of file upload transactions. Instead, RGW NFS +starts a new upload when the first write is sent to a file at offset +0, and finalizes the upload when no new writes to the file have been +seen for a period of time, by default, 10 seconds. To change this +timeout, set an alternate value for ``rgw_nfs_write_completion_interval_s`` +in the RGW section(s) of the Ceph configuration file. + +References +========== + +.. [#] http://docs.aws.amazon.com/AmazonS3/latest/dev/ListingKeysHierarchy.html diff --git a/ceph/doc/radosgw/pools.rst b/ceph/doc/radosgw/pools.rst new file mode 100644 index 000000000..2d88a3c10 --- /dev/null +++ b/ceph/doc/radosgw/pools.rst @@ -0,0 +1,55 @@ +===== +Pools +===== + +The Ceph Object Gateway uses several pools for its various storage needs, +which are listed in the Zone object (see ``radosgw-admin zone get``). A +single zone named ``default`` is created automatically with pool names +starting with ``default.rgw.``, but a `Multisite Configuration`_ will have +multiple zones. + +Tuning +====== + +When ``radosgw`` first tries to operate on a zone pool that does not +exist, it will create that pool with the default values from +``osd pool default pg num`` and ``osd pool default pgp num``. These defaults +are sufficient for some pools, but others (especially those listed in +``placement_pools`` for the bucket index and data) will require additional +tuning. We recommend using the `Ceph Placement Group’s per Pool +Calculator `__ to calculate a suitable number of +placement groups for these pools. See +`Pools `__ +for details on pool creation. + +Pool Namespaces +=============== + +.. versionadded:: Luminous + +Pool names particular to a zone follow the naming convention +``{zone-name}.pool-name``. For example, a zone named ``us-east`` will +have the following pools: + +- ``.rgw.root`` + +- ``us-east.rgw.control`` + +- ``us-east.rgw.meta`` + +- ``us-east.rgw.log`` + +- ``us-east.rgw.buckets.index`` + +- ``us-east.rgw.buckets.data`` + +The zone definitions list several more pools than that, but many of those +are consolidated through the use of rados namespaces. For example, all of +the following pool entries use namespaces of the ``us-east.rgw.meta`` pool:: + + "user_keys_pool": "us-east.rgw.meta:users.keys", + "user_email_pool": "us-east.rgw.meta:users.email", + "user_swift_pool": "us-east.rgw.meta:users.swift", + "user_uid_pool": "us-east.rgw.meta:users.uid", + +.. _`Multisite Configuration`: ../multisite diff --git a/ceph/doc/radosgw/rgw-centos.conf b/ceph/doc/radosgw/rgw-centos.conf deleted file mode 100644 index 54ef72cf3..000000000 --- a/ceph/doc/radosgw/rgw-centos.conf +++ /dev/null @@ -1,30 +0,0 @@ -FastCgiExternalServer /var/www/html/s3gw.fcgi -socket /var/run/ceph/ceph.radosgw.gateway.fastcgi.sock - - - - - ServerName {fqdn} - - - ServerAdmin {email.address} - DocumentRoot /var/www/html - RewriteEngine On - RewriteRule ^/(.*) /s3gw.fcgi?%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] - - - - Options +ExecCGI - AllowOverride All - SetHandler fastcgi-script - Order allow,deny - Allow from all - AuthBasicAuthoritative Off - - - - AllowEncodedSlashes On - ErrorLog /var/log/httpd/error.log - CustomLog /var/log/httpd/access.log combined - ServerSignature Off - - \ No newline at end of file diff --git a/ceph/doc/radosgw/rgw-debian.conf b/ceph/doc/radosgw/rgw-debian.conf deleted file mode 100644 index 127805ed4..000000000 --- a/ceph/doc/radosgw/rgw-debian.conf +++ /dev/null @@ -1,29 +0,0 @@ -FastCgiExternalServer /var/www/s3gw.fcgi -socket /var/run/ceph/ceph.radosgw.gateway.fastcgi.sock - - - - ServerName {fqdn} - - - ServerAdmin {email.address} - DocumentRoot /var/www - RewriteEngine On - RewriteRule ^/(.*) /s3gw.fcgi?%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] - - - - Options +ExecCGI - AllowOverride All - SetHandler fastcgi-script - Order allow,deny - Allow from all - AuthBasicAuthoritative Off - - - - AllowEncodedSlashes On - ErrorLog /var/log/apache2/error.log - CustomLog /var/log/apache2/access.log combined - ServerSignature Off - - \ No newline at end of file diff --git a/ceph/doc/radosgw/rgw.conf b/ceph/doc/radosgw/rgw.conf deleted file mode 100644 index 5e4cc0858..000000000 --- a/ceph/doc/radosgw/rgw.conf +++ /dev/null @@ -1,30 +0,0 @@ -FastCgiExternalServer /var/www/s3gw.fcgi -socket /{path}/{socket-name}.sock - - - - - ServerName {fqdn} - - - ServerAdmin {email.address} - DocumentRoot /var/www - RewriteEngine On - RewriteRule ^/(.*) /s3gw.fcgi?%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] - - - - Options +ExecCGI - AllowOverride All - SetHandler fastcgi-script - Order allow,deny - Allow from all - AuthBasicAuthoritative Off - - - - AllowEncodedSlashes On - ErrorLog /var/log/apache2/error.log - CustomLog /var/log/apache2/access.log combined - ServerSignature Off - - \ No newline at end of file diff --git a/ceph/doc/radosgw/upgrade_to_jewel.rst b/ceph/doc/radosgw/upgrade_to_jewel.rst deleted file mode 100644 index 19d94ff6e..000000000 --- a/ceph/doc/radosgw/upgrade_to_jewel.rst +++ /dev/null @@ -1,43 +0,0 @@ -================================================================= -RGW upgrading to Jewel versions 10.2.0, 10.2.1, 10.2.2 and 10.2.3 -================================================================= - -.. versionadded:: Jewel - -Upgrade of :term:`Ceph Object Gateway` to older versions of jewel (up to 10.2.3 included) caused issues. This document describes the needed recovery procedure. - -Mixed version of :term:`Ceph Object Gateway` is not supported - -Backup of old configuration -=========================== -rados mkpool .rgw.root.backup -rados cppool .rgw.root .rgw.root.backup - -Non default setting for `rgw region root pool` -============================================== -If an existing multisite configuration uses a non-default setting for -`rgw region root pool`, the new pool settings `rgw zonegroup root pool`, -`rgw period root pool` and `rgw realm root pool` should be set to match. - -Fix confgiuration after upgrade -=============================== -Stop all :term:`Ceph Object Gateway` running in the cluster. - -Run the following commands::: - - $ rados rmpool .rgw.root - - $ radosgw-admin zonegroup get --rgw-zonegroup=default | sed 's/"id":.*/"id": "default",/g' | sed 's/"master_zone.*/"master_zone":"default",/g' > default-zg.json - - $ raodsgw-admin zone get --zone-id=default > default-zone.json - - $ radosgw-admin realm create --rgw-realm=myrealm - - $ radosgw-admin zonegroup set --rgw-zonegroup=default --default < default-zg.json - - $ radosgw-admin zone set --rgw-zone=default --default < default-zone.json - - $ radosgw-admin period update --commit - -Start all :term:`Ceph Object Gateway` in the cluster. - diff --git a/ceph/doc/release-notes.rst b/ceph/doc/release-notes.rst index 9b657e622..e466614f0 100644 --- a/ceph/doc/release-notes.rst +++ b/ceph/doc/release-notes.rst @@ -2,6 +2,823 @@ Release Notes =============== +v12.1.0 Luminous (RC) +==================== + +This is the first release candidate for Luminous, the next long term stable release. + +Major Changes from Kraken +------------------------- + +* When assigning a network to the public network and not to + the cluster network the network specification of the public + network will be used for the cluster network as well. + In older versions this would lead to cluster services + being bound to 0.0.0.0:, thus making the + cluster service even more publicly available than the + public services. When only specifying a cluster network it + will still result in the public services binding to 0.0.0.0. + +* In previous versions, if a client sent an op to the wrong OSD, the OSD + would reply with ENXIO. The rationale here is that the client or OSD is + clearly buggy and we want to surface the error as clearly as possible. + We now only send the ENXIO reply if the osd_enxio_on_misdirected_op option + is enabled (it's off by default). This means that a VM using librbd that + previously would have gotten an EIO and gone read-only will now see a + blocked/hung IO instead. + +* The "journaler allow split entries" config setting has been removed. + +- *librados*: + + * Some variants of the omap_get_keys and omap_get_vals librados + functions have been deprecated in favor of omap_get_vals2 and + omap_get_keys2. The new methods include an output argument + indicating whether there are additional keys left to fetch. + Previously this had to be inferred from the requested key count vs + the number of keys returned, but this breaks with new OSD-side + limits on the number of keys or bytes that can be returned by a + single omap request. These limits were introduced by kraken but + are effectively disabled by default (by setting a very large limit + of 1 GB) because users of the newly deprecated interface cannot + tell whether they should fetch more keys or not. In the case of + the standalone calls in the C++ interface + (IoCtx::get_omap_{keys,vals}), librados has been updated to loop on + the client side to provide a correct result via multiple calls to + the OSD. In the case of the methods used for building + multi-operation transactions, however, client-side looping is not + practical, and the methods have been deprecated. Note that use of + either the IoCtx methods on older librados versions or the + deprecated methods on any version of librados will lead to + incomplete results if/when the new OSD limits are enabled. + + * The original librados rados_objects_list_open (C) and objects_begin + (C++) object listing API, deprecated in Hammer, has finally been + removed. Users of this interface must update their software to use + either the rados_nobjects_list_open (C) and nobjects_begin (C++) API or + the new rados_object_list_begin (C) and object_list_begin (C++) API + before updating the client-side librados library to Luminous. + Object enumeration (via any API) with the latest librados version + and pre-Hammer OSDs is no longer supported. Note that no in-tree + Ceph services rely on object enumeration via the deprecated APIs, so + only external librados users might be affected. + + The newest (and recommended) rados_object_list_begin (C) and + object_list_begin (C++) API is only usable on clusters with the + SORTBITWISE flag enabled (Jewel and later). (Note that this flag is + required to be set before upgrading beyond Jewel.) + +- *CephFS*: + + * When configuring ceph-fuse mounts in /etc/fstab, a new syntax is + available that uses "ceph.=" in the options column, instead + of putting configuration in the device column. The old style syntax + still works. See the documentation page "Mount CephFS in your + file systems table" for details. + + * CephFS clients without the 'p' flag in their authentication capability + string will no longer be able to set quotas or any layout fields. This + flag previously only restricted modification of the pool and namespace + fields in layouts. + * CephFS directory fragmentation (large directory support) is enabled + by default on new filesystems. To enable it on existing filesystems + use "ceph fs set allow_dirfrags". + * CephFS will generate a health warning if you have fewer standby daemons + than it thinks you wanted. By default this will be 1 if you ever had + a standby, and 0 if you did not. You can customize this using + ``ceph fs set standby_count_wanted ``. Setting it + to zero will effectively disable the health check. + * The "ceph mds tell ..." command has been removed. It is superceded + by "ceph tell mds. ..." + +- *MGR* + + * ceph-mgr supports a default dashboard + * ceph-mgr introduces a new pecan based rest API + +- *RGW*: + + * RGW introduces server side encryption of uploaded objects with 3 options for + the management of encryption keys, automatic encryption (only recommended for + test setups), customer provided keys similar to Amazon SSE-C specification and + using a key management service (Openstack Barbician) similar to Amazon SSE-KMS + specification. + * RGW's metadata search with ElasticSearch now supports end user requests + serviced via RGW itself and now supports custom metadata fields + * RGW has consolidated the several metadata index pools via the use of rados + namespaces + * RGW now supports dynamic bucket index sharding + +Notable Changes +--------------- +* bluestore: ceph-disk: add --filestore argument, default to --bluestore (`pr#15437 `_, Loic Dachary, Sage Weil) +* bluestore,core: os/bluestore: fix warning (`pr#15435 `_, Sage Weil) +* bluestore,core: os/bluestore: improve mempool usage (`pr#15402 `_, Sage Weil) +* bluestore,core: os/bluestore: write "mkfs_done" into disk only if we pass fsck() tests (`pr#15238 `_, xie xingguo) +* bluestore,core: os: remove experimental status for BlueStore (`pr#15177 `_, Sage Weil) +* bluestore: os/bluestore/BlockDevice: support pmem device as bluestore backend (`pr#15102 `_, Jianpeng Ma) +* bluestore: os/bluestore: fix a typo about bleustore (`pr#15357 `_, Dongsheng Yang) +* bluestore: os/bluestore: fix BitMapAllocator assert on out-of-bound hint value (`pr#15289 `_, Igor Fedotov) +* bluestore: os/bluestore: fix buffers pinned by indefinitely deferred writes (`pr#15398 `_, Sage Weil) +* bluestore: os/bluestore: fix false assert in IOContext::aio_wake (`pr#15268 `_, Igor Fedotov) +* bluestore: os/bluestore: fix false asserts in Cache::trim_all() (`pr#15470 `_, xie xingguo) +* bluestore: os/bluestore: fix fsck deferred_replay (`pr#15295 `_, Sage Weil) +* bluestore: os/bluestore/KernelDevice: fix comments (`pr#15264 `_, xie xingguo) +* bluestore: os/bluestore/KernelDevice: helpful warning when aio limit exhausted (`pr#15116 `_, Sage Weil) +* bluestore,performance: os/bluestore: avoid overloading extents during reshard; atomic deferred_batch_ops (`pr#15502 `_, xie xingguo) +* bluestore,performance: os/bluestore: batch throttle (`pr#15284 `_, Jianpeng Ma) +* bluestore,performance: os/bluestore: keep statfs replica in RAM to avoid expensive KV retrieval (`pr#15309 `_, Igor Fedotov) +* bluestore,performance: os/bluestore/KernelDevice: fix sync write vs flush (`pr#15034 `_, Sage Weil) +* bluestore,performance: os/bluestore: move cache_trim into MempoolThread (`pr#15380 `_, xie xingguo) +* bluestore,performance: os/bluestore: put bluefs in the middle of the shared device (`pr#14873 `_, Sage Weil) +* bluestore,performance: os/bluestore: separate kv_sync_thread into two parts (`pr#14035 `_, Jianpeng Ma, Igor Fedotov, Sage Weil) +* bluestore,performance: os/bluestore: try to unshare blobs for EC overwrite workload (`pr#14239 `_, Sage Weil) +* build/ops: 12.0.3 (`pr#15600 `_, Jenkins Build Slave User) +* build/ops: build: move bash_completion.d/ceph to ceph-common (`pr#15148 `_, Leo Zhang) +* build/ops: build: remove ceph-disk-udev entirely (`pr#15259 `_, Leo Zhang) +* build/ops: build: revert -Wvla from #15342 (`pr#15469 `_, Willem Jan Withagen) +* build/ops: build: Use .S suffix for ppc64le assembly files (`issue#20106 `_, `pr#15373 `_, Andrew Solomon) +* build/ops: ceph-detect-init: detect init system by poking the system (`issue#19884 `_, `pr#15043 `_, Kefu Chai) +* build/ops,common: build: Adds C++ warning flag for C Variable-Length Arrays. (`pr#15342 `_, Jesse Williamson) +* build/ops,common: common/blkdev.cc: propagate get_device_by_fd to different OSes (`pr#15547 `_, Willem Jan Withagen) +* build/ops: conditionalize rgw Beast frontend so it isn't built on s390x architecture (`issue#20048 `_, `pr#15225 `_, Willem Jan Withagen, Nathan Cutler, Kefu Chai, Tim Serong, Casey Bodley) +* build/ops,core,tests: osd/dmclock/testing: reorganize testing, building now optional (`pr#15375 `_, J. Eric Ivancich) +* build/ops: debian: ceph-mgr: fix package description (`pr#15513 `_, Fabian Grünbichler) +* build/ops: debian: sync logrotate packaging with downstream (`issue#19938 `_, `pr#15567 `_, Fabian Grünbichler) +* build/ops: do_cmake.sh: enable ccache if installed (`pr#15274 `_, Sage Weil) +* build/ops: drop libfcgi build dependency (`pr#15285 `_, Nathan Cutler) +* build/ops: install-deps.sh: workaround setuptools' dependency on six (`pr#15406 `_, Kefu Chai) +* build/ops: rpm: apply epoch only if %epoch macro is defined (`pr#15286 `_, Nathan Cutler) +* build/ops: rpm: make librbd1 %post scriptlet depend on coreutils (`issue#20052 `_, `pr#15231 `_, Giacomo Comes, Nathan Cutler) +* build/ops: rpm: move _epoch_prefix below Epoch definition (`pr#15417 `_, Nathan Cutler) +* build/ops: rpm: move RDMA and python-prettytables build dependencies to distro-conditional section (`pr#15200 `_, Nathan Cutler) +* build/ops: selinux: Allow read on var_run_t (`issue#16674 `_, `pr#15523 `_, Boris Ranto) +* build/ops: selinux: Do parallel relabel on package install (`issue#20077 `_, `pr#14871 `_, Boris Ranto) +* build/ops: selinux: Install ceph-base before ceph-selinux (`issue#20184 `_, `pr#15490 `_, Boris Ranto) +* build/ops: Set subman cron attributes in spec file (`issue#20074 `_, `pr#15270 `_, Thomas Serlin) +* build/ops: The Clangtastic Mr. Clocks (`pr#15186 `_, Adam C. Emerson) +* build/ops: yasm-wrapper: filter -pthread (`pr#15249 `_, Alessandro Barbieri) +* cephfs: #17980: MDS client blacklisting and blacklist on eviction (`issue#17980 `_, `issue#9754 `_, `pr#14610 `_, John Spray) +* cephfs: ceph: simplify CInode::maybe_export_pin() (`pr#15106 `_, "Yan, Zheng") +* cephfs: client: fix display ino in the ldout (`pr#15314 `_, huanwen ren) +* cephfs: client/inode: fix the dump type of Inode::dump() (`pr#15198 `_, huanwen ren) +* cephfs,common,rbd: blkin: librbd trace hooks (`pr#15053 `_, Victor Araujo, Jason Dillaman) +* cephfs: mon/FSCommand: fix indentation (`pr#15423 `_, Sage Weil) +* cephfs: mon/MDSMonitor: respect mds_standby_for_rank config (`pr#15129 `_, "Yan, Zheng") +* cephfs: osdc/Journaler: avoid executing on_safe contexts prematurely (`issue#20055 `_, `pr#15240 `_, "Yan, Zheng") +* cephfs: qa/cephfs: disable mds_bal_frag for TestStrays.test_purge_queue_op_rate (`issue#19892 `_, `pr#15105 `_, "Yan, Zheng") +* cephfs: qa/tasks/cephfs: use getattr to guarantee inode is in client cache (`issue#19912 `_, `pr#15062 `_, "Yan, Zheng") +* cephfs: qa: update log whitelists for kcephfs suite (`pr#14922 `_, "Yan, Zheng") +* cephfs,tests: qa: fix float parse error in test_fragment (`pr#15122 `_, Patrick Donnelly) +* cephfs,tests: qa: silence upgrade test failure (`issue#19934 `_, `pr#15126 `_, Patrick Donnelly) +* cephfs,tests: qa: simplify TestJournalRepair (`pr#15096 `_, John Spray) +* cleanup: src: put-to operator function - const input cleanup (`issue#3977 `_, `pr#15364 `_, Jos Collin) +* cmake: Add -finstrument-functions flag to OSD code (`pr#15055 `_, Mohamad Gebai) +* cmake: check the existence of gperf before using it (`pr#15164 `_, Kefu Chai) +* cmake: do not link libcommon against some libs (`pr#15340 `_, Willem Jan Withagen) +* cmake: fix boost components for WITH_SYSTEM_BOOST (`pr#15160 `_, Bassam Tabbara) +* cmake: improved build speed by 5x when using ccache (`pr#15147 `_, Bassam Tabbara) +* cmake: link against fcgi only if enabled (`pr#15425 `_, Yao Zongyou) +* cmake: misc fixes for build on i386 (`pr#15516 `_, James Page) +* cmake: rgw: do not link against boost in a wholesale (`pr#15347 `_, Nathan Cutler, Kefu Chai) +* cmake: workaound ccache issue with .S assembly files (`pr#15142 `_, Bassam Tabbara) +* common: add ceph::size() (`pr#15181 `_, Kefu Chai) +* common: ceph_osd: remove client message cap limit (`pr#14944 `_, Haomai Wang) +* common: cls: optimize header file dependency (`pr#15165 `_, Brad Hubbard, Xiaowei Chen) +* common: cmdparse: more constness (`pr#15023 `_, Kefu Chai) +* common: common/ceph_context: 'config diff get' option added (`pr#10736 `_, Daniel Oliveira) +* common: common/ceph_context: fix leak of registered commands on exit (`pr#15302 `_, xie xingguo) +* common: common/iso_8601.cc: Make return expression Clang compatible (`pr#15336 `_, Willem Jan Withagen) +* common: common/LogEntry: include EntityName in log entries (`pr#15395 `_, Sage Weil) +* common: common,osdc: remove atomic_t completely (`pr#15562 `_, Kefu Chai) +* common: common/perf_counters: add average time for PERFCOUNTER_TIME (`pr#15478 `_, xie xingguo) +* common: common/perf_counters: make schema more friendly and update docs (`pr#14933 `_, Sage Weil) +* common: common,test: migrate atomic_t to std::atomic (`pr#14866 `_, Jesse Williamson) +* common,core: ceph_test_rados_api_misc: fix LibRadosMiscConnectFailure.ConnectFailure retry (`issue#19901 `_, `pr#15522 `_, Sage Weil) +* common,core: osd/OSDMap: make osd_state 32 bits wide (`pr#15390 `_, Sage Weil) +* common,core: osd/OSDMap: replace require_*_osds flags with a single require_osd_release field (`pr#15068 `_, Sage Weil) +* common,core: osd/OSDMap: replace string-based min_compat_client with a CEPH_RELEASE_* uint8_t (`pr#15351 `_, Sage Weil) +* common: crc32c: include acconfig.h to fix ceph_crc32c_aarch64() (`pr#15515 `_, Kefu Chai) +* common: crush/CrushWrapper: fix has_incompat_choose_args (`pr#15218 `_, Sage Weil) +* common: crush/CrushWrapper: fix has_incompat_choose_args() (`pr#15244 `_, Sage Weil) +* common: denc: add encode/decode for basic_sstring (`pr#15135 `_, Kefu Chai, Casey Bodley) +* common: get_process_name: use getprogname on bsd systems (`pr#15338 `_, Mykola Golub) +* common: Improved CRC calculation for zero buffers (`pr#11966 `_, Adam Kupczyk) +* common: include/lru.h: add const to member functions (`pr#15408 `_, yonghengdexin735) +* common: include/rados: Fix typo in rados_ioctx_cct() doc (`pr#15220 `_, Jos Collin) +* common: include: Redo some includes for FreeBSD (`issue#19883 `_, `pr#15337 `_, Willem Jan Withagen) +* common: int_types.h: remove hacks to workaround old systems (`pr#15069 `_, Kefu Chai) +* common: librados,libradosstriper,test: migrate atomic_t to std::atomic (baragon) (`pr#14658 `_, Jesse Williamson) +* common: libradosstriper: Add example code (`pr#15350 `_, Logan Blyth) +* common: mempool: improve dump; fix buffer accounting bugs (`pr#15403 `_, Sage Weil) +* common,mon: messenger,client,compressor: migrate atomic_t to std::atomic (`pr#14657 `_, Jesse Williamson) +* common,mon: mon,crush: add 'osd crush swap-bucket' command (`pr#15072 `_, Sage Weil) +* common,performance: buffer: allow buffers to be accounted in arbitrary mempools (`pr#15352 `_, Sage Weil) +* common,performance: crc32c: Add ppc64le fast zero optimized assembly. (`pr#15100 `_, Andrew Solomon) +* common,performance: inline_memory: optimized mem_is_zero for non-x64 (`pr#15307 `_, Piotr Dałek) +* common,performance: kv/rocksdb: supports SliceParts interface (`pr#15058 `_, Haomai Wang) +* common,performance: osd/OSDMap: make pg_temp more efficient (`pr#15291 `_, Sage Weil) +* common: Remove redundant includes - 2 (`issue#19883 `_, `pr#15169 `_, Jos Collin) +* common: Remove redundant includes - 3 (`issue#19883 `_, `pr#15204 `_, Jos Collin) +* common: Remove redundant includes - 5 (`issue#19883 `_, `pr#15267 `_, Jos Collin) +* common: Remove redundant includes - 6 (`issue#19883 `_, `pr#15299 `_, Jos Collin) +* common: Remove redundant includes (`issue#19883 `_, `pr#15042 `_, Brad Hubbard) +* common: Remove redundant includes (`issue#19883 `_, `pr#15086 `_, Jos Collin) +* common,tests: ceph_test_rados_api_list: more fix LibRadosListNP.ListObjectsError (`issue#19963 `_, `pr#15138 `_, Sage Weil) +* common: xio: migrate atomic_t to std::atomic<> (`pr#15230 `_, Jesse Williamson) +* core: ceph-disk: do not setup_statedir on trigger (`issue#19941 `_, `pr#15410 `_, Loic Dachary) +* core: compressor: add LZ4 support (`pr#15434 `_, Haomai Wang) +* core: compressor: optimize header file dependency (`pr#15187 `_, Brad Hubbard, Xiaowei Chen) +* core: crush, mon: make jewel the lower bound for client/crush compat for new clusters (`pr#15370 `_, Sage Weil) +* core: erasure-code: optimize header file dependency (`pr#15172 `_, Brad Hubbard, Xiaowei Chen) +* core: erasure-code: Remove duplicate of isa-l files (`pr#15372 `_, Ganesh Mahalingam) +* core: filestore: migrate atomic_t to std::atomic<> (`pr#15228 `_, Jesse Williamson) +* core: include/types.h, introduce host_to_ceph_errno (`pr#15496 `_, Willem Jan Withagen) +* core: Install Pecan for FreeBSD (`pr#15610 `_, Willem Jan Withagen) +* core,mgr: mgr/DaemonServer: stop spamming log with pg stats (`pr#15487 `_, Sage Weil) +* core,mgr,mon: mon/PGMap: fix osd_epoch update when removing osd_stat (`issue#20208 `_, `pr#15573 `_, Sage Weil) +* core,mon: mon/LogMonitor: 'log last' command (`pr#15497 `_, Sage Weil) +* core,mon: mon/OSDMonitor: cancel mapping job from update_from_paxos (`issue#20067 `_, `pr#15320 `_, Sage Weil) +* core,mon: mon/OSDMonitor: use up set instead of acting set in reweight_by_utilization (`pr#13802 `_, Mingxin Liu) +* core,mon: mon/PGMap: call blocked requests ERR not WARN (`pr#15501 `_, Sage Weil) +* core: mon/OSDMonitor: change info in 'osd failed' messages (`pr#15321 `_, Sage Weil) +* core: mon,osd/OSDMap: a couple pg-upmap fixes (`pr#15319 `_, Sage Weil) +* core: msg/async: avoid requeue racing with handle_write (`issue#20093 `_, `pr#15324 `_, Haomai Wang) +* core: osd,librados: add manifest, redirect (`pr#15325 `_, Sage Weil) +* core: osd/OSDMap: improve upmap calculation (`issue#19818 `_, `pr#14902 `_, Sage Weil) +* core: osd/PG: drop pre-firefly compat_mode for choose_*_acting (`pr#15057 `_, Sage Weil) +* core: osd/pglog: remove loop through empty collection (`pr#15121 `_, J. Eric Ivancich) +* core,performance: msg/async: reduce write_lock contention (`pr#15092 `_, Haomai Wang) +* core,rgw: qa: Removed all 'default_idle_timeout' due to chnage in rwg task (`pr#15420 `_, Yuri Weinstein) +* core,rgw,tests: qa/rgw_snaps: move default_idle_timeout config under the client (`issue#20128 `_, `pr#15400 `_, Yehuda Sadeh) +* core: src/ceph.in: Use env(CEPH_DEV) to suppress noise from ceph (`pr#14746 `_, Willem Jan Withagen) +* core,tests: ceph-disk: sensible default for block.db (`pr#15576 `_, Loic Dachary) +* core,tests: qa/suites/rados/*/at-end: wait for healthy before scrubbing (`pr#15245 `_, Sage Weil) +* core,tests: qa/suites/rados/singleton-nomsg/health-warnings: behave on ext4 (`issue#20043 `_, `pr#15207 `_, Sage Weil) +* core,tests: qa/suites/rados: temporarily remove scrub_test from basic/ until post-luminous (`issue#19935 `_, `pr#15202 `_, Sage Weil) +* core,tests: qa/suites/upgrade/kraken-x: enable experimental for bluestore (`pr#15359 `_, Sage Weil) +* core,tests: qa/workunits/cephtool/test.sh: fix osd full health detail grep (`issue#20187 `_, `pr#15494 `_, Sage Weil) +* core,tests: qa/workunits/rados/test_health_warning: misc fixes (`issue#19990 `_, `pr#15201 `_, Sage Weil) +* core,tests: test/osd/TestRados.cc: run set-redirect test after finishing setup (`issue#20114 `_, `pr#15385 `_, Myoungwon Oh) +* core,tools: osdmaptool: require --upmap-save before modifying input osdmap (`pr#15247 `_, Sage Weil) +* crush: add missing tunable in tests (`pr#15412 `_, Loic Dachary) +* crush: encode can override weights with weight set (`issue#19836 `_, `pr#15002 `_, Loic Dachary) +* crush: optimize header file dependency (`pr#9307 `_, Xiaowei Chen) +* crush: update choose_args when items are added/removed (`pr#15311 `_, Loic Dachary) +* doc: add descriptions for mon/mgr options (`pr#15032 `_, Kefu Chai) +* doc: add FreeBSD manual install (`pr#14941 `_, Willem Jan Withagen) +* doc: add new cn ceph mirror to doc and mirroring (`pr#15089 `_, Shengjing Zhu) +* doc: add rados xattr commands to manpage (`pr#15362 `_, Andreas Gerstmayr) +* doc: add README to dmclock subdir to inform developers it's a git subtree (`pr#15386 `_, J. Eric Ivancich) +* doc: AUTHORS: update with release manager, backport team (`pr#15391 `_, Sage Weil) +* doc: Change the default values of some OSD options (`issue#20199 `_, `pr#15566 `_, Bara Ancincova) +* doc: describe CephFS max_file_size (`pr#15287 `_, Ken Dreyer) +* doc: dev improve the s3tests doc to reflect current scripts (`pr#15180 `_, Abhishek Lekshmanan) +* doc: doc/cephfs: mention RADOS object size limit (`pr#15550 `_, John Spray) +* doc: doc/release-notes: update which jewel version does sortbitwise warning (`pr#15209 `_, Sage Weil) +* doc: doc/rgw: remove fastcgi page and sample configs (`pr#15133 `_, Casey Bodley) +* doc: Documentation Fixes for http://tracker.ceph.com/issues/19879 (`issue#20057 `_, `issue#19879 `_, `pr#15606 `_, Sameer Tiwari) +* doc: document perf historgrams (`pr#15150 `_, Piotr Dałek) +* doc: Document RGW quota cache options (`issue#18747 `_, `pr#13395 `_, Daniel Gryniewicz) +* doc: fix broken link in erasure-code.rst (`issue#19972 `_, `pr#15143 `_, MinSheng Lin) +* doc: fix factual inaccuracy in doc/architecture.rst (`pr#15235 `_, Nathan Cutler, Sage Weil) +* doc: fixing an error in 12.0.3 release notes (`pr#15195 `_, Abhishek Lekshmanan) +* doc: fix syntax on code snippets in cephfs/multimds (`pr#15499 `_, John Spray) +* doc: kill some broken links (`pr#15203 `_, liuchang0812) +* doc: mailmap: Leo Zhang infomation and affiliation (`pr#15145 `_, Leo Zhang) +* doc: mention certain conf vars should be in global (`pr#15119 `_, Ali Maredia) +* doc: Merge pull request from stiwari/wip-19879 (`issue#19879 `_, `pr#15609 `_, Sameer Tiwari) +* doc: minor fixes in radosgw/ (`pr#15103 `_, Drunkard Zhang) +* doc: PendingReleaseNotes: notes on whiteouts vs pgnls (`pr#15575 `_, Sage Weil) +* doc: PendingReleaseNotes: warning about 'osd rm ...' and #19119 (`issue#19119 `_, `pr#13731 `_, Sage Weil) +* doc: release-notes clarify about rgw encryption (`pr#14800 `_, Abhishek Lekshmanan) +* doc: release notes for v12.0.3 (dev) (`pr#15090 `_, Abhishek Lekshmanan) +* docs document "osd recovery max single start" setting (`issue#17396 `_, `pr#15275 `_, Ken Dreyer) +* doc: typo fixes on hyperlink/words (`pr#15144 `_, Drunkard Zhang) +* doc: update sample explaning "%" operator in test suites (`pr#15511 `_, Kefu Chai) +* doc: Update some RGW documentation (`pr#15175 `_, Jens Rosenboom) +* doc: update the usage of 'ceph-deploy purge' (`pr#15080 `_, Yu Shengzuo) +* doc: use do_cmake.sh instead of `cmake ..` (`pr#15110 `_, Kefu Chai) +* librbd: discard related IO should skip op if object non-existent (`issue#19962 `_, `pr#15239 `_, Mykola Golub) +* librbd: do not raise an error if trash list returns -ENOENT (`pr#15085 `_, runsisi) +* librbd: filter expected error codes from is_exclusive_lock_owner (`issue#20182 `_, `pr#15483 `_, Jason Dillaman) +* librbd: fix valgrind errors and ensure tests detect future leaks (`pr#15415 `_, Jason Dillaman) +* librbd: optimize copy-up to add hints only once to object op (`issue#19875 `_, `pr#15037 `_, Mykola Golub) +* librbd: potential read IO hang when image is flattened (`issue#19832 `_, `pr#15234 `_, Jason Dillaman) +* librbd: reacquire lock should update lock owner client id (`issue#19929 `_, `pr#15093 `_, Jason Dillaman) +* librbd: reduce potential of erroneous blacklisting on image close (`issue#19970 `_, `pr#15162 `_, Jason Dillaman) +* librbd: remove unused rbd_image_options_t ostream operator (`pr#15443 `_, Mykola Golub) +* mds: change the type of data_pools (`pr#15278 `_, Vicente Cheng) +* mds: check export pin during replay (`issue#20039 `_, `pr#15205 `_, Patrick Donnelly) +* mds: fix CDir::merge() for mds_debug_auth_pins (`issue#19946 `_, `pr#15130 `_, "Yan, Zheng") +* mds: fix client ID truncation (`pr#15258 `_, Henry Chang) +* mds: limit client writable range increment (`issue#19955 `_, `pr#15131 `_, "Yan, Zheng") +* mds: miscellaneous multimds fixes (`pr#14550 `_, "Yan, Zheng") +* mds: Pass empty string to clear mantle balancer (`issue#20076 `_, `pr#15282 `_, Zhi Zhang) +* mds: properly create aux subtrees for pinned directory (`issue#20083 `_, `pr#15300 `_, "Yan, Zheng") +* mgr: ceph-create-keys: update client.admin if it already exists (`issue#19940 `_, `pr#15112 `_, John Spray) +* mgr: ceph: introduce "tell x help" subcommand (`issue#19885 `_, `pr#15111 `_, liuchang0812) +* mgr: ceph-mgr: Implement new pecan-based rest api (`pr#14457 `_, Boris Ranto) +* mgr: cleanup, stop clients sending in perf counters (`pr#15578 `_, John Spray) +* mgr: dashboard code cleanup (`pr#15577 `_, John Spray) +* mgr: dashboard GUI module (`pr#14946 `_, John Spray, Dan Mick) +* mgr: load modules in separate python sub-interpreters (`pr#14971 `_, Tim Serong) +* mgr: Mark session connections down on shutdown (`issue#19900 `_, `pr#15192 `_, Brad Hubbard) +* mgr: mgr/DaemonServer.cc: log daemon type string as well as id (`pr#15560 `_, Dan Mick) +* mgr: mgr/MgrStandby: prevent use-after-free on just-shut-down Mgr (`issue#19595 `_, `pr#15297 `_, Sage Weil) +* mgr: mgr/MgrStandby: respawn when deactivated (`issue#19595 `_, `issue#19549 `_, `pr#15557 `_, Sage Weil) +* mgr: mgr,osd: ceph-mgr --help, unify usage text of other daemons (`pr#15176 `_, Tim Serong) +* mgr,mon: mon,mgr: extricate PGmap from monitor (`issue#20067 `_, `issue#20174 `_, `issue#20050 `_, `pr#15073 `_, Kefu Chai, Sage Weil, Greg Farnum) +* mgr,mon: mon/MgrMonitor: add 'mgr dump [epoch]' command (`pr#15158 `_, Sage Weil) +* mgr: optimize DaemonStateIndex::cull() a little bit (`pr#14967 `_, Kefu Chai) +* mgr: pybind/mgr/dashboard: monkeypatch os.exit to stop cherrypy from taking down mgr (`issue#20216 `_, `pr#15588 `_, Sage Weil) +* mgr: pybind/mgr: Delete `rest` module (`pr#15429 `_, John Spray) +* mgr: pybind/mgr/restful: improve cert handling; work with vstart (`pr#15405 `_, Sage Weil) +* mon: add crush type down health warnings (`pr#14914 `_, Neha Ojha) +* mon: Add override for FsNewHandler::handle() (`pr#15331 `_, yonghengdexin735) +* mon: cleanups (`pr#15272 `_, Kefu Chai) +* mon: delete useless function definition (`pr#15188 `_, shiqi) +* mon: don't prefix mgr summary with epoch number (`pr#15512 `_, John Spray) +* mon: fix accesing pending_fsmap from peon (`issue#20040 `_, `pr#15213 `_, John Spray) +* mon: fix a few bugs with the osd health reporting (`pr#15179 `_, Sage Weil) +* mon: Fixed typo in function comment blocks and in other comments (`pr#15304 `_, linbing) +* mon: Fixed typo in @post of _active() (`pr#15191 `_, Linbing) +* mon: fix mon_keyvaluedb application (`pr#15059 `_, Sage Weil) +* mon: it's no need to get pg action_primary osd twice in pg scrub (`pr#15313 `_, linbing) +* mon: mon/MgrMonitor: send digests only if is_active() (`pr#15109 `_, Kefu Chai) +* mon: mon/MonClient: cancel pending commands on shutdown (`issue#20051 `_, `pr#15227 `_, Kefu Chai, Sage Weil) +* mon: {mon,osd,mds} {versions,count-metadata} (`pr#15436 `_, Sage Weil) +* mon: mon/PGMap: show %used in formatted output (`issue#20123 `_, `pr#15387 `_, Joao Eduardo Luis) +* mon: Removed unnecessary function declaration in MDSMonitor.h (`pr#15374 `_, yonghengdexin735) +* mon: replace osds with `osd destroy` and `osd new` (`pr#14074 `_, Joao Eduardo Luis, Sage Weil) +* mon: revise "ceph status" output (`pr#15396 `_, John Spray) +* mon: show io status quickly if no update in a long period (`pr#14176 `_, Mingxin Liu) +* mon: track features from connect clients, and use it to gate set-require-min-compat-client (`pr#15371 `_, Sage Weil) +* mon: trim the creating_pgs after updating it with pgmap (`issue#20067 `_, `pr#15318 `_, Kefu Chai) +* msg: do not enable client-side binding by default (`issue#20049 `_, `pr#15392 `_, Jason Dillaman) +* msg: don't set msgr addr when disabing client bind (`pr#15243 `_, Haomai Wang) +* msgr: msg/async: Lower down the AsyncMessenger's standby warning from debug (`pr#15242 `_, Pan Liu) +* msgr: msg/async: remove false alert "assert" (`pr#15288 `_, Haomai Wang) +* osd: don't leak pgrefs or reservations in SnapTrimmer (`issue#19931 `_, `pr#15214 `_, Greg Farnum) +* osd: fix argument-dependent lookup of swap() (`pr#15124 `_, Casey Bodley) +* osd: fix past_intervals base case by adding epoch_pool_created to pg_history_t (`issue#19877 `_, `pr#14989 `_, Sage Weil) +* osd: hdd vs ssd defaults for osd op thread pool (`pr#15422 `_, Sage Weil) +* osd: Implement asynchronous recovery sleep (`pr#15212 `_, Neha Ojha) +* osd: Move scrub sleep timer to osdservice (`issue#19986 `_, `pr#15217 `_, Brad Hubbard) +* osd: Object level shard errors are tracked and used if no auth available (`issue#20089 `_, `pr#15397 `_, David Zafman) +* osd: osd/OSDMap.cc: check if osd is out in subtree_type_is_down (`issue#19989 `_, `pr#15250 `_, Neha Ojha) +* osd: 'osd tree in|out|up|down' to filter tree results (`pr#15294 `_, Sage Weil) +* osd: reduce buffer pinning from EC entries (`pr#15120 `_, Sage Weil) +* osd: reduce map cache size (`pr#15292 `_, Sage Weil) +* osd: reduce rados_max_object_size from 100 GB -> 128 MB (`pr#15520 `_, Sage Weil) +* osd: rename osd -> osd_pglog; include pglog-related bufferlists (`pr#15531 `_, Sage Weil) +* osd: Return early on shutdown (`issue#19900 `_, `pr#15345 `_, Brad Hubbard) +* osd: take PGRef for recovery sleep wakeup event (`issue#20226 `_, `pr#15582 `_, Sage Weil) +* osd: when osd in not in failure_pending, we don't need to get osd inst from osdmap. (`pr#15558 `_, linbing) +* osd: When scrub finds an attr error mark shard inconsistent (`issue#20089 `_, `pr#15368 `_, David Zafman) +* performance: common/config_opts.h: Lower HDD throttle cost. (`pr#15485 `_, Mark Nelson) +* performance: denc: add need_contiguous to denc_traits (`pr#15224 `_, Kefu Chai) +* pybind: pybind/ceph_argparse: fix empty string check (`issue#20135 `_, `pr#15500 `_, Sage Weil) +* pybind: pybind/ceph_daemon.py: fix Termsize.update (`pr#15253 `_, Kefu Chai) +* pybind: pybind/rados: avoid call free() on invalid pointer (`pr#15159 `_, Mingxin Liu) +* pybind,rbd: pybind/rbd: OSError should be picklable (`issue#20223 `_, `pr#15574 `_, Jason Dillaman) +* pybind: support mon target in pybind (`pr#15409 `_, liuchang0812) +* rbd-mirror: coordinate image syncs with leader (`issue#18789 `_, `pr#14745 `_, Mykola Golub) +* rbd-mirror: lock loss during sync should wait for in-flight copies (`pr#15532 `_, Jason Dillaman) +* rbd-mirror: permit release of local image exclusive lock after force promotion (`issue#18963 `_, `pr#15140 `_, Jason Dillaman) +* rbd: properly decode features when using image name optional (`issue#20185 `_, `pr#15492 `_, Jason Dillaman) +* rbd: pybind/rbd: fix crash if more than 1024 images in trash bin (`pr#15134 `_, runsisi) +* rbd: rbd/bench: fix write gaps when doing sequential writes with io-threads > 1 (`pr#15206 `_, Igor Fedotov) +* rbd: removed hardcoded default pool (`pr#15518 `_, Jason Dillaman) +* rbd,tests: qa: krbd discard/zeroout tests (`pr#15388 `_, Ilya Dryomov) +* rbd,tests: qa/suites/krbd: unmap subsuite needs straw buckets (`pr#15290 `_, Ilya Dryomov) +* rbd,tests: qa: update krbd_data_pool.sh to match the new rados ls behavior (`pr#15594 `_, Ilya Dryomov) +* rbd,tests: test/librbd: unit tests cleanup (`pr#15113 `_, Mykola Golub) +* rdma: msg/async/rdma: Add DSCP support (`pr#15484 `_, Sarit Zubakov) +* rdma: msg/async: Revert RDMA-CM (`pr#15262 `_, Amir Vadai) +* rgw: Adding code to create tenanted user for s3 bucket policy tests. (`pr#15028 `_, Pritha Srivastava) +* rgw: add "rgw_verify_ssl" config (`pr#15301 `_, Shasha Lu) +* rgw: add the Vim's modeline into rgw_orphan.cc. (`pr#15431 `_, Radoslaw Zarzynski) +* rgw: bucket index check in radosgw-admin removes valid index. (`issue#18470 `_, `pr#12851 `_, Zhang Shaowen) +* rgw: datalog trim and mdlog trim handles the result returned by osd incorrectly. (`issue#20190 `_, `pr#15507 `_, Zhang Shaowen) +* rgw: display more info when using radosgw-admin bucket stats (`pr#15256 `_, fang.yuxiang) +* rgw: drop asio/{yield,coroutine}.hpp replacements (`pr#15413 `_, Kefu Chai) +* rgw: drop using std ns in header files and other cleanups (`pr#15137 `_, Abhishek Lekshmanan) +* rgw: dynamic resharding (`pr#15493 `_, Yehuda Sadeh, Orit Wasserman) +* rgw: fix 'gc list --include-all' command infinite loop the first items (`issue#19978 `_, `pr#12774 `_, Shasha Lu, fang yuxiang) +* rgw: fix lc list failure when shards not be all created (`issue#19898 `_, `pr#15025 `_, Jiaying Ren) +* rgw: fix radosgw-admin retcode (`pr#15257 `_, Shasha Lu) +* rgw: fix test_multi.py default config file path (`pr#15306 `_, Jiaying Ren) +* rgw: fix X-Object-Meta-Static-Large-Object in SLO download (`issue#19951 `_, `pr#15045 `_, Shasha Lu) +* rgw: metadata search part 2 (`pr#14351 `_, Yehuda Sadeh) +* rgw: migrate atomic_t to std::atomic<> (`pr#15001 `_, Jesse Williamson) +* rgw: optimize data sync. Add zones_trace in log to avoid needless sync. (`issue#19219 `_, `pr#13851 `_, Zhang Shaowen) +* rgw: optimize generating torrent file. Object data won't stay in memory now. (`pr#15153 `_, Zhang Shaowen) +* rgw: pass authentication domain to civetweb (`issue#17657 `_, `pr#12861 `_, Abhishek Lekshmanan) +* rgw: polymorphic error codes (`pr#10690 `_, Pritha Srivastava, Marcus Watts) +* rgw: remove fastcgi from default rgw frontends (`pr#15098 `_, Casey Bodley) +* rgw: rename s3_code to err_code for swift (`pr#12300 `_, Guo Zhandong) +* rgw: return the version id in get object and object metadata request. (`issue#19370 `_, `pr#14117 `_, Zhang Shaowen) +* rgw: rgw-admin: fix bucket limit check argparse, div(0) (`pr#15316 `_, Matt Benjamin) +* rgw: rgw_common: use string::npos for the results of str.find (`pr#14341 `_, Abhishek Lekshmanan) +* rgw: rgw_file: add lock protection for readdir against gc (`issue#20121 `_, `pr#15329 `_, Gui Hecheng) +* rgw: rgw_file cleanup names (`pr#15568 `_, Gui Hecheng) +* rgw: rgw_file: fix flags set on unsuccessful unlink (`pr#15222 `_, Gui Hecheng) +* rgw: rgw_file: release rgw_fh lock and ref on ENOTEMPTY (`issue#20061 `_, `pr#15246 `_, Matt Benjamin) +* rgw: rgw_file: removed extra rele() on fs in rgw_umount() (`pr#15152 `_, Gui Hecheng) +* rgw: rgw_file: remove hidden uxattr objects from buckets on delete (`issue#20045 `_, `pr#15210 `_, Matt Benjamin) +* rgw: rgw_file: remove post-unlink lookup check (`issue#20047 `_, `pr#15216 `_, Matt Benjamin) +* rgw: rgw_file: replace raw fs->fh_lru.unref with predefined fs->unref (`pr#15541 `_, Gui Hecheng) +* rgw: rgw_file: store bucket uxattrs on the bucket (`issue#20082 `_, `pr#15293 `_, Matt Benjamin) +* rgw: rgw_file: v3: fix write-timer action (`issue#19932 `_, `pr#15097 `_, Matt Benjamin) +* rgw: rgw_rados: create sync module instances only if run_sync_thread is set (`issue#19830 `_, `pr#14994 `_, Abhishek Lekshmanan) +* rgw: rgw/rgw_swift_auth.cc: using string::back() instead as the C++11 recommend (`pr#14827 `_, liuyuhong) +* rgw: segment fault when shard id out of range (`issue#19732 `_, `pr#14389 `_, redickwang) +* rgw: set object accounted size correctly (`issue#20071 `_, `pr#14950 `_, fang yuxiang) +* rgw: set placement rule properly (`pr#15221 `_, fang.yuxiang) +* rgw: support certain archaic and antiquated distributions (`pr#15498 `_, Adam C. Emerson) +* rgw,tests: qa/rgw: add multisite suite to configure and run multisite tests (`pr#14688 `_, Casey Bodley) +* rgw,tests: qa/rgw: remove apache/fastcgi and radosgw-agent tests (`pr#15184 `_, Casey Bodley) +* rgw: Turn off fcgi as a frontend (`issue#16784 `_, `pr#15070 `_, Thomas Serlin) +* rgw: use get_data_extra_pool() when get extra pool (`issue#20064 `_, `pr#15219 `_, fang yuxiang) +* rgw: use pre-defined calls to replace raw flag operation (`pr#15107 `_, Gui Hecheng) +* tests: Add integration tests for admin socket output (`pr#15223 `_, Brad Hubbard) +* tests: ceph-disk: add setting for external py-modules for tox-testing (`pr#15433 `_, Willem Jan Withagen) +* tests: Check make_writeable() return value (`pr#15266 `_, zhanglei) +* tests: config_opts: drop unused opts (`pr#15031 `_, Kefu Chai) +* tests: qa: add task for dnsmasq configuration (`pr#15071 `_, Casey Bodley) +* tests: qa: split test_tiering into smaller pieces (`pr#15146 `_, Kefu Chai) +* tests: qa/suites/rados: fix ec thrashing (`pr#15087 `_, Sage Weil) +* tests: qa/suites/rados/singleton-nomsgr: fix syntax (`pr#15276 `_, Sage Weil) +* tests: qa/suites/rados/thrash: make sure osds have map before legacy scrub (`pr#15117 `_, Sage Weil) +* tests: qa/suites/rados/upgrade: restart mds (`pr#15517 `_, Sage Weil) +* tests: qa/tasks/ceph_manager: 'ceph $service tell ...' is obsolete (`pr#15252 `_, Sage Weil) +* tests: qa/tasks/rebuild_mondb: grant "mgr:allow *" to client.admin (`issue#19439 `_, `pr#14284 `_, Kefu Chai) +* tests: qa/tasks/repair_test: unset flags we set (`pr#15296 `_, Sage Weil) +* tests: qa/workunits/ceph-helpers.sh: use syntax understood by jq 1.3 (`pr#15530 `_, Kefu Chai) +* tests: Rename FileJournal object to distinguish (`pr#15279 `_, Jos Collin) +* tests: test/crush: silence warnings from -Walloc-size-larger-than= and -Wstringop-overflow= (`pr#15173 `_, Jos Collin) +* tests: test: migrate atomic_t to std::atomic (`pr#14655 `_, Jesse Williamson) +* tests: test/msgr: silence warnings from -Wsign-compare (`pr#15356 `_, Jos Collin) +* tests: test/msgr: silence warnings from -Wsign-compare (`pr#15570 `_, Jos Collin) +* tests: test/objectstore: Check apply_transaction() return values (`pr#15171 `_, zhanglei) +* tests: test/old: Removed commented code (`pr#15366 `_, Jos Collin) +* tests: test/osdc: fix comparison error and silence warning from -Wunused-value (`pr#15353 `_, Willem Jan Withagen) +* tests: test: osd/TestOSDMap.cc: fix Clang complain about promotion (`pr#15525 `_, Willem Jan Withagen) +* tests: test: test_denc.cc: silence warning from -Wsign-compare (`pr#15355 `_, Jos Collin) +* tests: test: Test fix for SnapSet change (`pr#15161 `_, David Zafman) +* tests: test/unittest_bluefs: check whether mounted success (`pr#14988 `_, shiqi) +* tools: ceph.in: adjust usage width according to user's tty (`pr#15190 `_, Kefu Chai) +* tools: ceph.in: assert(state==connected) before help_for_target() (`pr#15156 `_, Kefu Chai) +* tools: ceph.in: drop the compatiiblity to handle non json commands (`pr#15508 `_, Kefu Chai) +* tools: ceph.in: print return code when json_command failed (`pr#15378 `_, liuchang0812) +* tools: tools/ceph_kvstore_tool: add "bluestore-kv" to usage (`pr#15326 `_, xie xingguo) +* tools: tools/crushtool: replicated-rule API support (`pr#15011 `_, xie xingguo) +* tools: vstart: "debug_ms=1" for mgr by default (`pr#15127 `_, Kefu Chai) +* tools: vstart: print "start osd.$id" instead of "start osd$id" (`pr#15427 `_, Kefu Chai) + +v12.0.3 Luminous (dev) +====================== + +This is the fourth development checkpoint release of Luminous, the next long +term stable release. This release introduces several improvements in bluestore, +monitor, rbd & rgw. + +Major changes from v12.0.2 +-------------------------- + +Notable Changes +--------------- +* bluestore,core: osd/OSDMap: should update input param if osd dne (`pr#14863 `_, Kefu Chai) +* bluestore: include/intarith: templatize ctz/clz/cbits helpers (`pr#14862 `_, Kefu Chai) +* bluestore: os/bluestore: align reclaim size to bluefs_alloc_size (`pr#14744 `_, Haomai Wang) +* bluestore: os/bluestore: assert blob map returns success (`pr#14473 `_, shiqi) +* bluestore: os/bluestore: fix deferred write race (`issue#19880 `_, `pr#15004 `_, Sage Weil) +* bluestore: os/bluestore: fix typo(s/trasnaction/transaction/) (`pr#14890 `_, xie xingguo) +* bluestore: os/bluestore: fix use after free race with aio_wait (`pr#14956 `_, Sage Weil) +* bluestore: os/bluestore: pre-calculate number of ghost buffers to evict (`pr#15029 `_, xie xingguo) +* bluestore: os/bluestore: Record l_bluestore_state_kv_queued_lat for sync_submit_… (`pr#14448 `_, Jianpeng Ma) +* bluestore: os/bluestore: Remove ExtentFreeListManager. (`pr#14772 `_, Jianpeng Ma) +* bluestore: os/bluestore: remove unused condition variable (`pr#14973 `_, Igor Fedotov) +* bluestore: os/bluestore: rename/fix throttle options (`pr#14717 `_, Sage Weil) +* bluestore: os/bluestore: roundoff bluefs allocs to bluefs_alloc_size (`pr#14876 `_, Ramesh Chander) +* bluestore: os/bluestore: use correct bound encode size for unused (`pr#14731 `_, Haomai Wang) +* bluestore,performance: common/config_opts.h: compaction readahead for bluestore/rocksdb (`pr#14932 `_, Mark Nelson) +* bluestore,performance: os/bluestore/BlueFS: add bluefs_sync_write option (`pr#14510 `_, Sage Weil) +* bluestore,performance: os/bluestore: do not balance bluefs on every kv_sync_thread iteration (`pr#14557 `_, Sage Weil) +* bluestore,performance: os/bluestore: eliminate some excessive stuff (`pr#14675 `_, Igor Fedotov) +* bluestore,performance: os/bluestore: get rid off excessive lock at BitMapAllocator (`pr#14749 `_, Igor Fedotov) +* bluestore,performance: os/blueStore: In osd_tp_thread, call _txc_finalize_kv. (`pr#14709 `_, Jianpeng Ma) +* bluestore,performance: os/bluestore: make bluestore_max_blob_size parameter hdd/ssd case dependant (`pr#14434 `_, Igor Fedotov) +* bluestore,performance: os/bluestore: rewrite deferred write handling (`issue#16644 `_, `pr#14491 `_, Sage Weil) +* bluestore,performance: os/bluestore: use denc for varint encoding (`pr#14911 `_, Piotr Dałek) +* bluestore,performance: os/fs/aio: use small_vector for aio_t; clean up header location (`pr#14853 `_, Sage Weil) +* bluestore,tests: unittest_alloc: add test_alloc_big (`issue#16662 `_, `pr#14844 `_, Sage Weil) +* bluestore,tools: ceph-kvstore-tool: allow 'bluestore-kv' as kvdb type; add escaping, compaction (`pr#14718 `_, Sage Weil) +* build/ops: alpine: add alpine linux dev support (`pr#9853 `_, John Coyle) +* build/ops: arch: use __get_cpuid instead of do_cpuid (`issue#7869 `_, `pr#14857 `_, Jos Collin) +* build/ops: CMakeLists.txt: don't do crypto/isa-l if not Intel (`pr#14721 `_, Dan Mick) +* build/ops: compressor/zlib: fix plugin for non-Intel arches (`pr#14947 `_, Dan Mick) +* build/ops: debian/rpm: move radosgw-admin to ceph-common (`issue#19577 `_, `pr#14940 `_, Ali Maredia) +* build/ops: dmclock: error: ‘function’ in namespace ‘std’ does not name a template type (`pr#14909 `_, Jos Collin) +* build/ops: dmclock: initial commit of dmclock QoS library (`pr#14330 `_, J. Eric Ivancich) +* build/ops: init-ceph: add ceph libraries path to environment (`pr#14693 `_, Mohamad Gebai) +* build/ops: init-ceph: should have a space before "]" (`pr#14796 `_, Kefu Chai) +* build/ops: merge v12.0.2 release tag (`pr#15091 `_, Jenkins Build Slave User) +* build/ops,mgr: debian/ceph-base.dirs: create bootstrap-mgr dirs (`pr#14838 `_, Sage Weil) +* build/ops,mon: mon/ConfigKeyService: add 'config-key dump' to show keys and vals (`pr#14858 `_, Dan Mick) +* build/ops,performance,rbd: byteorder: use gcc intrinsics for byteswap (`pr#15012 `_, Kefu Chai) +* build/ops: rocksdb: sync with upstream (`pr#14818 `_, Nathan Cutler, Kefu Chai) +* build/ops: rpm: fix python-Sphinx package name for SUSE (`pr#15015 `_, Nathan Cutler, Jan Matejek) +* build/ops: rpm: gperftools-devel >= 2.4 (`issue#13522 `_, `pr#14870 `_, Nathan Cutler) +* build/ops: rpm: package crypto on x86_64 only (`pr#14779 `_, Nathan Cutler) +* build/ops: debian: package crypto plugin only on amd64 (`pr#14820 `_, Kefu Chai) +* build/ops: src/init-ceph.in: allow one((re)?start|stop) as commands (`pr#14560 `_, Willem Jan Withagen) +* build/ops: yasm-wrapper: strip -E (stops ccache trashing source files) (`pr#14633 `_, Tim Serong) +* cephfs: ceph-fuse: use user space permission check by default (`issue#19820 `_, `pr#14907 `_, "Yan, Zheng") +* cephfs: client: client_quota no longer optional (`pr#14978 `_, Dan van der Ster) +* cephfs: client: fix UserPerm::gid_in_group() (`issue#19903 `_, `pr#15039 `_, "Yan, Zheng") +* cephfs: client: getattr before returning quota/layout xattrs (`issue#17939 `_, `pr#14018 `_, John Spray) +* cephfs: fs/ceph-fuse: normalize file open flags on the wire (`pr#14822 `_, Jan Fajerski) +* cephfs: mds/Server.cc: Don't evict a slow client if... (`issue#17855 `_, `pr#12935 `_, Michal Jarzabek) +* cephfs: osdc/Filer: truncate large file party by party (`issue#19755 `_, `pr#14769 `_, "Yan, Zheng") +* cephfs: osdc: remove journaler_allow_split_entries option (`issue#19691 `_, `pr#14636 `_, John Spray) +* cephfs,performance: client: make seeky readdir more efficiency (`issue#19306 `_, `pr#14317 `_, "Yan, Zheng") +* cephfs: qa/cephfs: Fix for test_data_scan (`issue#19893 `_, `pr#15094 `_, Douglas Fuller) +* cephfs: qa/suites/fs: reserve more space for mds in full tests (`issue#19891 `_, `pr#15026 `_, "Yan, Zheng") +* cephfs,tests: qa: silence spurious insufficient standby health warnings (`pr#15035 `_, Patrick Donnelly) +* cephfs,tests: qa: Tidy up fs/ suite (`pr#14575 `_, John Spray) +* cleanup: dmclock: include missing header. (`pr#14923 `_, Jos Collin) +* cleanup: kill clang warnings (`pr#14549 `_, Kefu Chai) +* cleanup: test: c_write_operations.cc: silence warning from -Wsign-compare (`pr#14889 `_, Jos Collin) +* cmake: add "container" to required boost components (`pr#14850 `_, Kefu Chai) +* cmake: align cmake names of library packages (`issue#19853 `_, `pr#14951 `_, Nathan Cutler) +* cmake: Allow tests to build without NSS (`pr#13315 `_, Daniel Gryniewicz) +* cmake: do not compile crush twice (`pr#14725 `_, Kefu Chai) +* cmake: enable cross-compilation of boost (`issue#18938 `_, `pr#14881 `_, Kefu Chai) +* cmake: fix the linked lib reference of unittest_rgw_crypto (`pr#14869 `_, Willem Jan Withagen) +* cmake: kill duplicated cmake commands (`pr#14948 `_, liuchang0812) +* cmake: pass -d0 to b2 if not CMAKE_VERBOSE_MAKEFILE (`pr#14651 `_, Kefu Chai) +* cmake: should not compile crc32c_ppc.c on intel arch. (`pr#14423 `_, Kefu Chai) +* common: Better handling for missing/inaccessible ceph.conf files (`issue#19658 `_, `pr#14757 `_, Dan Mick) +* common: cls/log/cls_log.cc: reduce logging noise (`issue#19835 `_, `pr#14879 `_, Willem Jan Withagen) +* common: common/admin_socket: add config for admin socket permission bits (`pr#11684 `_, runsisi) +* common: common/ceph_context.cc: Use CEPH_DEV to reduce logfile noise (`pr#10384 `_, Willem Jan Withagen) +* common: common/config: Add /usr/local/etc/ceph to default paths (`pr#14797 `_, Willem Jan Withagen) +* common: common/config_opts: Set the HDD throttle cost to 1.5M (`pr#14808 `_, Mark Nelson) +* common: common/Finisher: fix uninitialized variable warning (`pr#14958 `_, Piotr Dałek) +* common: common/interval_set: return int64_t for size() (`pr#12898 `_, Xinze Chi) +* common: crypto: cleanup NSPR in main thread (`pr#14801 `_, Kefu Chai) +* common: fix building against libcryptopp (`pr#14949 `_, Shengjing Zhu) +* common: Fix unused variable references warnings (`pr#14790 `_, Willem Jan Withagen) +* common: msg/async: return right away in NetHandler::set_priority() if not supported (`pr#14795 `_, Kefu Chai) +* common: osdc/Objecter: fix pool dne corner case (`issue#19552 `_, `pr#14901 `_, Sage Weil) +* common: osdc/Objecter: handle command target that goes down (`issue#19452 `_, `pr#14302 `_, Sage Weil) +* common: osd/OSDMap: fix feature commit comment (`pr#15056 `_, Sage Weil) +* common,performance: common/Finisher: batch handle perfcounter && only send signal when waiter existed. (`pr#14363 `_, Jianpeng Ma) +* common: Remove redundant includes (`issue#19883 `_, `pr#15003 `_, Brad Hubbard) +* common: Remove redundant includes (`issue#19883 `_, `pr#15019 `_, Brad Hubbard) +* common: src/common: change last_work_queue to next_work_queue. (`pr#14738 `_, Pan Liu) +* core: ceph-disk: ceph-disk on FreeBSD should not use mpath-code (`pr#14837 `_, Willem Jan Withagen) +* core: ceph-disk: implement prepare --no-locking (`pr#14728 `_, Dan van der Ster, Loic Dachary) +* core: ceph-disk: separate ceph-osd --check-needs-* logs (`issue#19888 `_, `pr#15016 `_, Loic Dachary) +* core: erasure-code: sync jerasure/gf-complete submodules (`pr#14424 `_, Loic Dachary) +* core: introduce DirectMessenger (`pr#14755 `_, Casey Bodley, Matt Benjamin) +* core: messages: remove compat cruft (`pr#14475 `_, Sage Weil) +* core,mon: common/Finisher: fix uninitialized variable warning (`issue#19874 `_, `pr#14979 `_, Sage Weil) +* core: mon,osd: add require_min_compat_client setting to enforce and clarify client compatibility (`pr#14959 `_, Sage Weil) +* core: mon/OSDMonitor: skip prime_pg_temp if mapping is prior to osdmap (`pr#14826 `_, Kefu Chai) +* core: mon/PGMonitor: fix wrongly report "pg stuck in inactive" (`pr#14391 `_, Mingxin Liu) +* core: osd,librados: cmpext support (`pr#14715 `_, Zhengyong Wang, David Disseldorp, Mike Christie) +* core: osd/OSDMap: bump encoding version for require_min_compat_client (`pr#15046 `_, "Yan, Zheng") +* core: osd/PG.cc: Optimistic estimation on PG.last_active (`pr#14799 `_, Xiaoxi Chen) +* core: osd/PG.cc: unify the call of checking whether lock is held (`pr#15013 `_, Jin Cai) +* core: osd/PG: fix possible overflow on unfound objects (`pr#12669 `_, huangjun) +* core: osd/PrimaryLogPG: do not call on_shutdown() if (pg.deleting) (`issue#19902 `_, `pr#15040 `_, Kefu Chai) +* core: osd/PrimayLogPG: update modified range to include the whole object size for write_full op (`pr#15021 `_, runsisi) +* core: osd/ReplicatedBackend: remove MOSDSubOp cruft from repop_applied (`pr#14358 `_, Jianpeng Ma) +* core: os/filestore/FileJournal: Fix typo in the comment (`pr#14493 `_, Zhou Zhengping) +* core: os/filestore: fix infinit loops in fiemap() (`pr#14367 `_, Ning Yao) +* core,performance: osd, os: reduce fiemap burden (`pr#14640 `_, Piotr Dałek) +* core,performance: os/filestore: use new sleep strategy when io_submit gets EAGAIN. (`pr#14860 `_, Pan Liu) +* core,performance: os/kstore: Added rocksdb bloom filter settings (`pr#13053 `_, Ted-Chang) +* core,tests: ceph_test_rados_api_watch_notify: make LibRadosWatchNotify.Watch3Timeout tolerate thrashing (`issue#19433 `_, `pr#14899 `_, Sage Weil) +* core,tools: ceph: perfcounter priorities and daemonperf updates to use them (`pr#14793 `_, Sage Weil, Dan Mick) +* core,tools: kv: move 'bluestore-kv' hackery out of KeyValueDB into ceph-kvstore-tool (`issue#19778 `_, `pr#14895 `_, Sage Weil) +* crush: builder: legacy has chooseleaf_stable = 0 (`pr#14695 `_, Loic Dachary) +* crush: crush_init_workspace starts with struct crush_work (`pr#14696 `_, Loic Dachary) +* crush: update documentation for negative choose step (`pr#14970 `_, Loic Dachary) +* doc: AUTHORS: update tech leads (`pr#14350 `_, Patrick Donnelly) +* doc: correct and improve add user capability section (`pr#14055 `_, Chu, Hua-Rong) +* doc: Correcting the remove bucket example and adding bucket link/unlink examples (`pr#12460 `_, Uday Mullangi) +* doc: dev add a note about ccache (`pr#14478 `_, Abhishek Lekshmanan) +* doc: doc/dev: add some info about FreeBSD (`pr#14503 `_, Willem Jan Withagen) +* doc: fio: update README.md so only the fio ceph engine is built (`pr#15081 `_, Kefu Chai) +* doc: fix link that pointed to a nonexistent file (`pr#14740 `_, Peter Maloney) +* doc: Indicate how to add multiple admin capbabilies (`pr#13956 `_, Chu, Hua-Rong) +* doc: mailmap: add Alibaba into organization map (`pr#14900 `_, James Liu) +* doc: mailmap: update organization info (`pr#14747 `_, liuchang0812) +* doc: mailmap: V12.0.1 credits (`pr#14479 `_, M Ranga Swami Reddy) +* doc: mailmap: Weibing Zhang mailmap affiliation (`pr#15076 `_, Weibing Zhang) +* doc: mailmap: ztczll affiliation (`pr#15079 `_, zhanglei) +* doc: mention teuthology-worker security group (`pr#14748 `_, Nathan Cutler) +* doc: peoplemap: add pdonnell alias (`pr#14352 `_, Patrick Donnelly) +* doc: remove deprecated subcommand in man/8/ceph.rst (`pr#14928 `_, Drunkard Zhang) +* doc: Re-word the warnings about using git subtrees. (`pr#14999 `_, J. Eric Ivancich) +* doc: rgw: Clean up create subuser parameters (`pr#14335 `_, hrchu) +* doc: rgw: correct get usage parameter default value (`pr#14372 `_, hrchu) +* doc: rgw: Get user usage needs to specify user (`pr#14804 `_, hrchu) +* doc: rgw: note rgw_enable_usage_log option in adminops guide (`pr#14803 `_, hrchu) +* doc: rgw: Rewrite Java swift examples (`pr#14268 `_, Chu, Hua-Rong) +* doc: rgw: Rewrite the key management (`pr#14384 `_, hrchu) +* doc: style fix for doc/cephfs/client-config-ref.rst (`pr#14840 `_, Drunkard Zhang) +* doc: two minor fixes (`pr#14494 `_, Drunkard Zhang) +* doc: update the support status of swift static website (`pr#13824 `_, Jing Wenjun) +* doc: v12.0.2 (dev) release notes (`pr#14625 `_, Abhishek Lekshmanan) +* librados: fix rados_pool_list when buf is null (`pr#14859 `_, Sage Weil) +* librbd: cleanup logging code under librbd/io (`pr#14975 `_, runsisi) +* librbd: do not instantiate templates while building tests (`issue#18938 `_, `pr#14891 `_, Kefu Chai) +* librbd: minor fixes for image trash move (`pr#14834 `_, runsisi) +* librbd: remove redundant check for image id emptiness (`pr#14830 `_, runsisi) +* librbd: silence -Wunused-variable warning (`pr#14953 `_, Kefu Chai) +* mds: add perf counters for file system operations (`pr#14938 `_, Michael Sevilla) +* mds: change_attr++ and set ctime for set_vxattr (`issue#19583 `_, `pr#14726 `_, Patrick Donnelly) +* mds: fix mantle script to not fail for last rank (`issue#19589 `_, `pr#14704 `_, Patrick Donnelly) +* mds: fix use-after-free in Locker::file_update_finish() (`issue#19828 `_, `pr#14991 `_, "Yan, Zheng") +* mds: issue new caps when sending reply to client (`issue#19635 `_, `pr#14743 `_, "Yan, Zheng") +* mds: relocate PTRWAITER put near get (`pr#14921 `_, Patrick Donnelly) +* mds: remove boost::pool usage and use tcmalloc directly (`issue#18425 `_, `pr#12792 `_, Zhi Zhang) +* mds: remove "mds log" config option (`issue#18816 `_, `pr#14652 `_, John Spray) +* mds: support export pinning on directories (`issue#17834 `_, `pr#14598 `_, "Yan, Zheng", Patrick Donnelly) +* mds: use debug_mds for most subsys (`issue#19734 `_, `pr#15052 `_, Patrick Donnelly) +* mgr: add machinery for python modules to send MCommands to daemons (`pr#14920 `_, John Spray) +* mgr: add mgr allow * to client.admin (`pr#14864 `_, huanwen ren) +* mgr: do shutdown using finisher so we can do it in the right order (`issue#19743 `_, `pr#14835 `_, Kefu Chai) +* mgr: do the shutdown in the right order (`issue#19813 `_, `pr#14952 `_, Kefu Chai) +* mgr: fix crash on set_config from python module with insufficient caps (`issue#19629 `_, `pr#14706 `_, Tim Serong) +* mgr: fix metadata handling from old MDS daemons (`pr#14161 `_, John Spray) +* mgr: fix python module teardown & add tests (`issue#19407 `_, `issue#19412 `_, `issue#19258 `_, `pr#14232 `_, John Spray) +* mgr: fix session leak (`issue#19591 `_, `pr#14720 `_, Sage Weil) +* mgr: Misc. bug fixes (`issue#18994 `_, `pr#14883 `_, John Spray) +* mgr: mkdir bootstrap-mgr (`pr#14824 `_, huanwen ren) +* mgr,mon: mon/MgrMonitor: only propose if we updated (`pr#14645 `_, Sage Weil) +* mgr,mon: mon,mgr: trim osdmap without the help of pgmap (`pr#14504 `_, Kefu Chai) +* mgr: pybind/mgr/rest: completely terminate cherrypy in shutdown (`pr#14995 `_, Tim Serong) +* mgr: redirect python stdout,stderr to ceph log (`pr#14189 `_, Kefu Chai, Tim Serong, Dan Mick) +* mgr: release allocated PyString (`pr#14716 `_, Kefu Chai) +* mgr: remove non-existent MDS daemons from FSMap (`issue#17453 `_, `pr#14937 `_, Spandan Kumar Sahu) +* mgr,tests: qa/suites: move mgr tests into rados suite (`pr#14687 `_, John Spray) +* mgr: various cleanups (`pr#14802 `_, Kefu Chai) +* mon: check is_shutdown() in timer callbacks (`issue#19825 `_, `pr#14919 `_, Kefu Chai) +* mon: do not prime_pg_temp creating pgs; clean up pg create conditions (`issue#19826 `_, `pr#14913 `_, Sage Weil) +* mon: don't call propose_pending in prepare_update() (`issue#19738 `_, `pr#14711 `_, John Spray) +* mon: logclient: use the seq id of the 1st log entry when resetting session (`issue#19427 `_, `pr#14927 `_, Kefu Chai) +* mon: mon/OSDMonitor: check get()'s return value instead of bl's length (`pr#14805 `_, Kefu Chai) +* mon: mon/OSDMonitor: cleanup pending_created_pgs after done with it (`pr#14898 `_, Kefu Chai) +* mon: mon/OSDMonitor: do not alter the "created" epoch of a pg (`issue#19787 `_, `pr#14849 `_, Kefu Chai) +* mon: mon/OSDMonitor: fix output func name in can_mark_out (`pr#14758 `_, xie xingguo) +* mon: mon/OSDMonitor: increase last_epoch_clean's lower bound if possible (`pr#14855 `_, Kefu Chai) +* mon: mon/OSDMonitor: tolerate upgrade from post-kraken dev cluster (`pr#14442 `_, Sage Weil) +* mon: mon/OSDMonitor: update creating_pgs using pending_creatings (`issue#19814 `_, `pr#14897 `_, Kefu Chai) +* mon: mon/OSDMonitor: update pg_creatings even the new acting set is empty (`issue#19744 `_, `pr#14730 `_, Kefu Chai) +* mon: mon/PGMap: add up_primary pg number field for pg-dump cmd (`pr#13451 `_, xie xingguo) +* mon: mon/PGMap.cc: fix "osd_epochs" section of dump_basic (`pr#14996 `_, xie xingguo) +* mon: mon/PGMonitor: clean up min/max span warning (`pr#14611 `_, Sage Weil) +* mon: move 'pg map' to OSDMonitor (`pr#14559 `_, Sage Weil) +* mon: osd/PGMonitor: always update pgmap with latest osdmap (`issue#19398 `_, `pr#14777 `_, Kefu Chai) +* mon: show inactive % in ceph status (`pr#14810 `_, Sage Weil) +* msg: Increase loglevels on some messages (`pr#14707 `_, Willem Jan Withagen) +* msg: msg/async/net_handler: errno should be stored before calling next function (`pr#14985 `_, Zhou Zhengping) +* msg: msg/simple: use my addr when setting sock priority (`issue#19801 `_, `pr#14878 `_, Kefu Chai) +* msg: src/msg/async/AsyncConnect.cc: Use of sizeof() on a Pointer Type (`pr#14773 `_, Svyatoslav) +* msg: src/msg/simple/Pipe.cc: Fix the inclusion of '}' (`pr#14843 `_, Willem Jan Withagen) +* osd: check fsid is normal before osd mkfs (`pr#13898 `_, song baisen) +* osd: clean nonused work queue (`pr#14990 `_, Wei Jin) +* osd: eliminate snapdir objects and move clone snaps vector into SnapSet (`pr#13610 `_, Sage Weil) +* osd: fix occasional MOSDMap leak (`issue#18293 `_, `pr#14558 `_, Sage Weil) +* osd: fix typo in comment (`pr#13061 `_, Gu Zhongyan) +* osd: Implement asynchronous scrub sleep (`issue#19497 `_, `pr#14886 `_, Brad Hubbard) +* osd: Implement peering state timing (`pr#14627 `_, Brad Hubbard) +* osd: objclass sdk (`pr#14723 `_, Neha Ojha) +* osd: osdc/Objecter: more constness (`pr#14819 `_, Kefu Chai) +* osd: osdc: silence warning from `-Wsign-compare` (`pr#14729 `_, Jos Collin) +* osd: pglog trimming fixes (`pr#12882 `_, Zhiqiang Wang) +* osd: pglog: with config, don't assert in the presence of stale diverg… (`issue#17916 `_, `pr#14648 `_, Greg Farnum) +* osd: put osdmap in mempool (`pr#14780 `_, Sage Weil) +* osd: renamed the new vector name in OSDMap::build_simple_crush_map_from_conf (`pr#14583 `_, Jos Collin) +* osd: ReplicatedBackend::prep_push() remove redundant variable assignments (`pr#14817 `_, Jin Cai) +* osd: sched_scrub() lock pg only if all scrubbing conditions are fulfilled (`pr#14968 `_, Jin Cai) +* osd: simplify past_intervals representation (`pr#14444 `_, Samuel Just, Sage Weil) +* osd: stop mgrc earlier in shutdown() (`issue#19638 `_, `pr#14904 `_, Kefu Chai) +* osd: stop MgrClient callbacks on shutdown (`issue#19638 `_, `pr#14896 `_, Sage Weil) +* osd: strip pglog op name (`pr#14764 `_, liuchang0812) +* osd: support dumping long ops (`pr#13019 `_, Zhiqiang Wang) +* osd: switch filestore to default to rocksdb (`pr#14814 `_, Neha Ojha) +* osd: tag fast dispatch messages with min_epoch (`pr#13681 `_, Sage Weil) +* osd: use append(bufferlist &) to avoid unnecessary copy (`pr#12272 `_, Yunchuan Wen) +* osd: zipkin tracing (`pr#14305 `_, Sage Weil, Marios-Evaggelos Kogias, Victor Araujo, Casey Bodley, Andrew Shewmaker, Chendi.Xue) +* performance: buffer, osd: add missing crc cache miss perf counter (`pr#14957 `_, Piotr Dałek) +* performance: osd/PG.cc: loop invariant code motion (`pr#12720 `_, Li Wang) +* pybind: better error msg (`pr#14497 `_, Kefu Chai) +* pybind: fix open flags calculation (`issue#19890 `_, `pr#15018 `_, "Yan, Zheng") +* qa: qa/added overrides (`pr#14917 `_, Yuri Weinstein) +* qa: qa/suite: replace reference to fs/xfs.yaml (`pr#14756 `_, Yehuda Sadeh) +* qa: qa/suites/rados/singleton-bluestore: concat settings (`pr#14884 `_, Kefu Chai) +* rbd: cls_rbd: default initialize snapshot namespace for legacy clients (`issue#19413 `_, `pr#14903 `_, Jason Dillaman) +* rbd: common/bit_vector: utilize deep-copy during data decode (`issue#19863 `_, `pr#15017 `_, Jason Dillaman) +* rbd: import needs to sanity check auto-generated image name (`issue#19128 `_, `pr#14754 `_, Mykola Golub) +* rbd: info command should indicate if parent is in trash (`pr#14875 `_, Jason Dillaman) +* rbd-mirror: ensure missing images are re-synced when detected (`issue#19811 `_, `pr#14945 `_, Jason Dillaman) +* rbd-mirror: failover and failback of unmodified image results in split-brain (`issue#19858 `_, `pr#14963 `_, Jason Dillaman) +* rbd-mirror: image deletions should be handled by assigned instance (`pr#14832 `_, Jason Dillaman) +* rbd-mirror: remove tracking of image names from pool watcher (`pr#14712 `_, Jason Dillaman) +* rbd-mirror: resolve admin socket path names collision (`issue#19907 `_, `pr#15048 `_, Mykola Golub) +* rbd-nbd: relax size check for newer kernel versions (`issue#19871 `_, `pr#14976 `_, Mykola Golub) +* rbd: rbd/bench: add notes of default values, it's easy to use (`pr#14762 `_, Zheng Yin) +* rbd: rbd, librbd: migrate atomic_t to std::atomic (`pr#14656 `_, Jesse Williamson) +* rbd: rbd-mirror A/A: proxy InstanceReplayer APIs via InstanceWatcher RPC (`issue#18787 `_, `pr#13978 `_, Mykola Golub) +* rbd: recognize exclusive option (`pr#14785 `_, Ilya Dryomov) +* rbd: removed spurious error message from mirror pool commands (`pr#14935 `_, Jason Dillaman) +* rbd: stop indefinite thread waiting in krbd udev handling (`issue#17195 `_, `pr#14051 `_, Spandan Kumar Sahu) +* rbd,tests: qa: krbd write-after-checksum tests (`pr#14836 `_, Ilya Dryomov) +* rbd,tests: qa/workunits/rbd: increased trash deferment period (`pr#14846 `_, Jason Dillaman) +* rbd,tests: qa/workunits: switch to OpenStack Ocata release for RBD testing (`pr#14465 `_, Jason Dillaman) +* rbd,tests: test/librbd/test_librbd.cc: set *features even if RBD_FEATURES is unset (`issue#19865 `_, `pr#14965 `_, Dan Mick) +* rbd,tests: test/librbd/test_notify.py: don't disable feature in slave (`issue#19716 `_, `pr#14751 `_, Mykola Golub) +* rbd,tests: test/rbd_mirror: race in TestMockLeaderWatcher.AcquireError (`issue#19405 `_, `pr#14741 `_, Mykola Golub) +* rbd,tests: test: remove hard-coded image name from RBD metadata test (`issue#19798 `_, `pr#14848 `_, Jason Dillaman) +* rdma: msg/async/rdma: add inqueue rx chunks perf counter (`pr#14782 `_, Haomai Wang) +* rgw: add bucket size limit check to radosgw-admin (`issue#17925 `_, `pr#11796 `_, Matt Benjamin) +* rgw: add 'state==SyncState::IncrementalSync' condition when add item … (`pr#14552 `_, Shasha Lu) +* rgw: add support container and object levels of swift bulkupload (`pr#14775 `_, Jing Wenjun) +* rgw: add support for FormPost of Swift API (`issue#17273 `_, `pr#11179 `_, Radoslaw Zarzynski, Orit Wasserman) +* rgw: civetweb don't go past the array index while calling mg_start (`issue#19749 `_, `pr#14750 `_, Abhishek Lekshmanan, Jesse Williamson) +* rgw: clean unuse code in cls_statelog_check_state (`pr#10260 `_, weiqiaomiao) +* rgw: cleanup: fix variable name in RGWRados::create_pool() declaration (`pr#14547 `_, Nathan Cutler) +* rgw: cleanup lc continuation (`pr#14906 `_, Jiaying Ren) +* rgw: cls/rgw: list_plain_entries() stops before bi_log entries (`issue#19876 `_, `pr#14981 `_, Casey Bodley) +* rgw: custom user data header (`issue#19644 `_, `pr#14592 `_, Pavan Rallabhandi) +* rgw: deduplicate variants of rgw_make_bucket_entry_name(). (`pr#14299 `_, Radoslaw Zarzynski) +* rgw: don't do unneccesary write if buffer with zero length (`pr#14925 `_, fang yuxiang) +* rgw: dont spawn error_repo until lease is acquired (`issue#19446 `_, `pr#14714 `_, Casey Bodley) +* rgw: drop unused param "bucket" from select_bucket_placement (`pr#14390 `_, Shasha Lu) +* rgw: drop unused port var (`pr#14412 `_, Jiaying Ren) +* rgw: fix broken /crossdomain.xml, /info and /healthcheck of Swift API. (`issue#19520 `_, `pr#14373 `_, Radoslaw Zarzynski) +* rgw: fix forward request for bulkupload to be applied in multisite (`issue#19645 `_, `pr#14601 `_, Jing Wenjun) +* rgw: fix handling of --remote in radosgw-admin period commands (`issue#19554 `_, `pr#14407 `_, Casey Bodley) +* rgw: fix RadosGW hang during multi-chunk upload of AWSv4. (`issue#19754 `_, `pr#14770 `_, Radoslaw Zarzynski) +* rgw: migrate atomic_t to std::atomic<> (ebirah) (`pr#14839 `_, Jesse Williamson) +* rgw: radosgw-admin: warn that 'realm rename' does not update other clusters (`issue#19746 `_, `pr#14722 `_, Casey Bodley) +* rgw: rgw_file: cleanup virtual keyword on derived functions (`pr#14908 `_, Gui Hecheng) +* rgw: rgw_ldap: log the ldap err in case of bind failure (`pr#14781 `_, Abhishek Lekshmanan) +* rgw: rgw multisite: automated mdlog trimming (`pr#13111 `_, Casey Bodley) +* rgw: rgw multisite: fixes for meta sync across periods (`issue#18639 `_, `pr#13070 `_, Casey Bodley) +* rgw: rgw multisite: remove the redundant post in OPT_ZONEGROUP_MODIFY (`pr#14359 `_, Jing Wenjun) +* rgw: RGWPeriodPusher spawns http thread before cr thread (`issue#19834 `_, `pr#14936 `_, Casey Bodley) +* rgw: rgw_rados drop deprecated global var (`pr#14411 `_, Jiaying Ren) +* rgw: should delete in_stream_req if conn->get_obj(...) return not zero value (`pr#9950 `_, weiqiaomiao) +* rgw: swift: ability to update swift read and write acls separately. (`issue#19289 `_, `pr#14499 `_, Marcus Watts) +* rgw: swift: disable revocation thread if sleep == 0 (`issue#19499 `_, `issue#9493 `_, `pr#14501 `_, Marcus Watts) +* rgw,tests: qa/rgw: add cluster name to path when s3tests scans rgw log (`pr#14845 `_, Casey Bodley) +* rgw,tests: qa/rgw: don't scan radosgw logs for encryption keys on jewel upgrade test (`pr#14697 `_, Casey Bodley) +* rgw,tests: qa/rgw: fix assertions in radosgw_admin task (`pr#14842 `_, Casey Bodley) +* rgw,tests: test/rgw: fixes for test_multi_period_incremental_sync() (`pr#13067 `_, Casey Bodley) +* rgw,tests: test/rgw: fix for empty lists as default arguments (`pr#14816 `_, Casey Bodley) +* rgw: update Beast for streaming reads in asio frontend (`pr#14273 `_, Casey Bodley) +* rgw: using the same bucket num_shards as master zg when create bucket in secondary zg (`issue#19745 `_, `pr#14388 `_, Shasha Lu) +* rgw: when create_bucket use the same num_shards with info.num_shards (`issue#19745 `_, `pr#15010 `_, Shasha Lu) +* tests: ceph_test_rados_api_tier: tolerate ENOENT from 'pg scrub' (`pr#14807 `_, Sage Weil) +* tests: cephtool/test.sh error on full tests (`issue#19698 `_, `pr#14647 `_, Willem Jan Withagen, David Zafman) +* tests: Don't dump core when using EXPECT_DEATH (`pr#14821 `_, Kefu Chai, Brad Hubbard) +* tests: fio_ceph_objectstore: fixes improper write request data lifetime (`pr#14338 `_, Adam Kupczyk) +* tests: fix broken links in upgrade/hammer-jewel-x/stress-split (`issue#19793 `_, `pr#14831 `_, Nathan Cutler) +* tests: include/denc: support ENCODE_DUMP (`pr#14962 `_, Sage Weil) +* tests: libradosstriper: do not assign garbage to returned value (`pr#15009 `_, Kefu Chai) +* tests: qa/erasure-code: override min_size to 2 (`issue#19770 `_, `pr#14872 `_, Kefu Chai) +* tests: qa/suites/jewel-x/point-to-point: don't scane for keys on second s3tests either (`pr#14788 `_, Sage Weil) +* tests: qa/suites: Reduce fs combination tests for smoke, use bluestore (`pr#14854 `_, Vasu Kulkarni) +* tests: qa/suites: Revert "qa/suites: add mon-reweight-min-pgs-per-osd = 4" (`pr#14584 `_, Kefu Chai) +* tests: qa/suites/upgrade/jewel-x: add mgr.x role (`pr#14689 `_, Sage Weil) +* tests: qa/suites/upgrade/kraken-x: misc fixes (`pr#14887 `_, Sage Weil) +* tests: qa/tasks/ceph_manager: always fix pgp_num when done with thrashosd task (`issue#19771 `_, `pr#14931 `_, Kefu Chai) +* tests: qa/tasks: few fixes to get ceph-deploy 1node to working state (`pr#14400 `_, Vasu Kulkarni) +* tests: rados: move cephtool.yaml to new singleton/bluestore subsuite (`issue#19797 `_, `pr#14847 `_, Nathan Cutler) +* tests: set -x in suites/iozone.sh workunit (`issue#19740 `_, `pr#14713 `_, Nathan Cutler) +* tests: test/compressor: disable isal tests if not available (`pr#14929 `_, Kefu Chai) +* tests: test: c_read_operations.cc: silence warning from -Wsign-compare (`pr#14888 `_, Jos Collin) +* tests: test/fio_ceph_objectstore: fix fio plugin build failure by engine_data (`pr#15044 `_, lisali) +* tests: test: fixing assert that creates warning: comparison between signed and unsigned integer expressions (`pr#14794 `_, Jos Collin) +* tests: test/fsx: Remove the dead code associated with aio backend (`pr#14905 `_, Zhou Zhengping) +* tests: test/objectstore/: Check put_ref return value (`pr#15007 `_, zhanglei) +* tests: test/osd/osd-dup.sh: lower wb fd throttle limits (`pr#14984 `_, Dan Mick) +* tests: test: use 7130 for crush-classes.sh (`pr#14783 `_, Loic Dachary) +* tests: test: warning: comparison between signed and unsigned integer expressions (`pr#14705 `_, Jos Collin) +* tests,tools: test: kill warnings (`pr#14892 `_, Kefu Chai) +* tools: change compare_exchange_weak to compare_exchange_strong (`pr#15030 `_, Jesse Williamson) +* tools: rados: check for negative return value of rados_create_with_context() as its comment put (`pr#10893 `_, zhang.zezhu) +* tools: rados: out json 'df' values as numbers, not strings (`issue#15546 `_, `pr#14644 `_, Sage Weil) + + v12.0.2 Luminous (dev) ====================== This is the third development checkpoint release of Luminous, the next long term @@ -10,40 +827,6 @@ stable release. Major changes from v12.0.1 -------------------------- -* The original librados rados_objects_list_open (C) and objects_begin - (C++) object listing API, deprecated in Hammer, has finally been - removed. Users of this interface must update their software to use - either the rados_nobjects_list_open (C) and nobjects_begin (C++) API or - the new rados_object_list_begin (C) and object_list_begin (C++) API - before updating the client-side librados library to Luminous. - - Object enumeration (via any API) with the latest librados version - and pre-Hammer OSDs is no longer supported. Note that no in-tree - Ceph services rely on object enumeration via the deprecated APIs, so - only external librados users might be affected. - - The newest (and recommended) rados_object_list_begin (C) and - object_list_begin (C++) API is only usable on clusters with the - SORTBITWISE flag enabled (Jewel and later). (Note that this flag is - required to be set before upgrading beyond Jewel.) -* CephFS clients without the 'p' flag in their authentication capability - string will no longer be able to set quotas or any layout fields. This - flag previously only restricted modification of the pool and namespace - fields in layouts. -* CephFS directory fragmentation (large directory support) is enabled - by default on new filesystems. To enable it on existing filesystems - use "ceph fs set allow_dirfrags". -* CephFS will generate a health warning if you have fewer standby daemons - than it thinks you wanted. By default this will be 1 if you ever had - a standby, and 0 if you did not. You can customize this using - ``ceph fs set standby_count_wanted ``. Setting it - to zero will effectively disable the health check. -* The "ceph mds tell ..." command has been removed. It is superceded - by "ceph tell mds. ..." -* RGW introduces server side encryption of uploaded objects with 3 options for - the management of encryption keys, automatic encryption (only recommended for - test setups), customer provided keys similar to Amazon SSE KMS specification & - using a key management service (openstack barbician) Notable Changes --------------- @@ -924,51 +1707,6 @@ This is the first development checkpoint release of Luminous series, the next long term release. We're off to a good start to release Luminous in the spring of '17. -Major changes from Kraken -------------------------- - * When assigning a network to the public network and not to - the cluster network the network specification of the public - network will be used for the cluster network as well. - In older versions this would lead to cluster services - being bound to 0.0.0.0:, thus making the - cluster service even more publicly available than the - public services. When only specifying a cluster network it - will still result in the public services binding to 0.0.0.0. - -* Some variants of the omap_get_keys and omap_get_vals librados - functions have been deprecated in favor of omap_get_vals2 and - omap_get_keys2. The new methods include an output argument - indicating whether there are additional keys left to fetch. - Previously this had to be inferred from the requested key count vs - the number of keys returned, but this breaks with new OSD-side - limits on the number of keys or bytes that can be returned by a - single omap request. These limits were introduced by kraken but - are effectively disabled by default (by setting a very large limit - of 1 GB) because users of the newly deprecated interface cannot - tell whether they should fetch more keys or not. In the case of - the standalone calls in the C++ interface - (IoCtx::get_omap_{keys,vals}), librados has been updated to loop on - the client side to provide a correct result via multiple calls to - the OSD. In the case of the methods used for building - multi-operation transactions, however, client-side looping is not - practical, and the methods have been deprecated. Note that use of - either the IoCtx methods on older librados versions or the - deprecated methods on any version of librados will lead to - incomplete results if/when the new OSD limits are enabled. - -* In previous versions, if a client sent an op to the wrong OSD, the OSD - would reply with ENXIO. The rationale here is that the client or OSD is - clearly buggy and we want to surface the error as clearly as possible. - We now only send the ENXIO reply if the osd_enxio_on_misdirected_op option - is enabled (it's off by default). This means that a VM using librbd that - previously would have gotten an EIO and gone read-only will now see a - blocked/hung IO instead. - -* When configuring ceph-fuse mounts in /etc/fstab, a new syntax is - available that uses "ceph.=" in the options column, instead - of putting configuration in the device column. The old style syntax - still works. See the documentation page "Mount CephFS in your - file systems table" for details. Notable Changes @@ -1475,7 +2213,7 @@ Upgrading from Jewel to Kraken 11.2.z (or, eventually, Luminous 12.2.z). * The ``sortbitwise`` flag must be set on the Jewel cluster before upgrading - to Kraken. The latest Jewel (10.2.4+) releases issue a health warning if + to Kraken. The latest Jewel (10.2.8+) releases issue a health warning if the flag is not set, so this is probably already set. If it is not, Kraken OSDs will refuse to start and will print and error message in their log. diff --git a/ceph/doc/start/documenting-ceph.rst b/ceph/doc/start/documenting-ceph.rst index 76b4f5f5b..856f4fb66 100644 --- a/ceph/doc/start/documenting-ceph.rst +++ b/ceph/doc/start/documenting-ceph.rst @@ -346,7 +346,8 @@ Then, download them from a mirror and install them. For example:: sudo yum install ditaa-0.9-13.r74.fc21.noarch.rpm Once you have installed all these packages, build the documentation by following -the steps given in ``Build the Source``. +the steps given in `Build the Source`_. + Commit the Change ----------------- diff --git a/ceph/doc/start/get-involved.rst b/ceph/doc/start/get-involved.rst index cfe3f4d64..5cbb1d6de 100644 --- a/ceph/doc/start/get-involved.rst +++ b/ceph/doc/start/get-involved.rst @@ -12,11 +12,11 @@ These are exciting times in the Ceph community! Get involved! | **Blog** | Check the Ceph Blog_ periodically to keep track | http://ceph.com/community/blog/ | | | of Ceph progress and important announcements. | | +----------------------+-------------------------------------------------+-----------------------------------------------+ -| **Planet Ceph** | Check the blog aggregation on Planet Ceph for | http://ceph.com/community/planet-ceph/ | +| **Planet Ceph** | Check the blog aggregation on Planet Ceph for | https://ceph.com/category/planet/ | | | interesting stories, information and | | | | experiences from the community. | | +----------------------+-------------------------------------------------+-----------------------------------------------+ -| **Wiki** | Check the Ceph Wiki is a source for more | https://wiki.ceph.com/ | +| **Wiki** | Check the Ceph Wiki is a source for more | http://wiki.ceph.com/ | | | community and development related topics. You | | | | can find there information about blueprints, | | | | meetups, the Ceph Developer Summits and more. | | diff --git a/ceph/doc/start/quick-ceph-deploy.rst b/ceph/doc/start/quick-ceph-deploy.rst index 560d50b12..e2bf65975 100644 --- a/ceph/doc/start/quick-ceph-deploy.rst +++ b/ceph/doc/start/quick-ceph-deploy.rst @@ -38,15 +38,12 @@ Create a Cluster ================ If at any point you run into trouble and you want to start over, execute -the following to purge the configuration:: +the following to purge the Ceph packages, and erase all its data and configuration:: + ceph-deploy purge {ceph-node} [{ceph-node}] ceph-deploy purgedata {ceph-node} [{ceph-node}] ceph-deploy forgetkeys -To purge the Ceph packages too, you may also execute:: - - ceph-deploy purge {ceph-node} [{ceph-node}] - If you execute ``purge``, you must re-install Ceph. On your admin node from the directory you created for holding your diff --git a/ceph/examples/librados/Makefile b/ceph/examples/librados/Makefile index 8d9d92693..533a4c647 100644 --- a/ceph/examples/librados/Makefile +++ b/ceph/examples/librados/Makefile @@ -1,7 +1,7 @@ CXX?=g++ CXX_FLAGS?=-std=c++11 -Wall -Wextra -Werror -g -CXX_LIBS?=-lboost_system -lrados +CXX_LIBS?=-lboost_system -lrados -lradosstriper CXX_INC?=$(LOCAL_LIBRADOS_INC) CXX_CC=$(CXX) $(CXX_FLAGS) $(CXX_INC) $(LOCAL_LIBRADOS) $(CXX_LIBS) @@ -13,11 +13,12 @@ CC_CC=$(CC) $(CC_FLAGS) $(CC_INC) $(LOCAL_LIBRADOS) $(CC_LIBS) # Relative path to the Ceph source: CEPH_SRC_HOME?=../../src +CEPH_BLD_HOME?=../../build -LOCAL_LIBRADOS?=-L$(CEPH_SRC_HOME)/.libs/ -Wl,-rpath,$(CEPH_SRC_HOME)/.libs +LOCAL_LIBRADOS?=-L$(CEPH_BLD_HOME)/lib/ -Wl,-rpath,$(CEPH_BLD_HOME)/lib LOCAL_LIBRADOS_INC?=-I$(CEPH_SRC_HOME)/include -all: hello_world_cpp hello_world_c +all: hello_world_cpp hello_radosstriper_cpp hello_world_c # Build against the system librados instead of the one in the build tree: all-system: LOCAL_LIBRADOS= @@ -27,9 +28,12 @@ all-system: all hello_world_cpp: hello_world.cc $(CXX_CC) -o hello_world_cpp hello_world.cc +hello_radosstriper_cpp: hello_radosstriper.cc + $(CXX_CC) -o hello_radosstriper_cpp hello_radosstriper.cc + hello_world_c: hello_world_c.c $(CC_CC) -o hello_world_c hello_world_c.c clean: - rm -f hello_world_cpp hello_world_c + rm -f hello_world_cpp hello_radosstriper_cpp hello_world_c diff --git a/ceph/examples/librados/hello_radosstriper.cc b/ceph/examples/librados/hello_radosstriper.cc new file mode 100644 index 000000000..f1b43d8fc --- /dev/null +++ b/ceph/examples/librados/hello_radosstriper.cc @@ -0,0 +1,102 @@ +#include "rados/librados.hpp" +#include "radosstriper/libradosstriper.hpp" +#include +#include + + +int main(int argc, char* argv[]) +{ + if(argc != 6) + { + std::cout <<"Please put in correct params\n"<< + "Stripe Count:\n"<< + "Object Size:\n" << + "File Name:\n" << + "Object Name:\n" + "Pool Name:"<< std::endl; + return EXIT_FAILURE; + } + uint32_t strip_count = std::stoi(argv[1]); + uint32_t obj_size = std::stoi(argv[2]); + std::string fname = argv[3]; + std::string obj_name = argv[4]; + std::string pool_name = argv[5]; + int ret = 0; + librados::IoCtx io_ctx; + librados::Rados cluster; + libradosstriper::RadosStriper* rs = new libradosstriper::RadosStriper; + + // make sure the keyring file is in /etc/ceph/ and is world readable + ret = cluster.init2("client.admin","ceph",0); + if( ret < 0) + { + std::cerr << "Couldn't init cluster "<< ret << std::endl; + } + + // make sure ceph.conf is in /etc/ceph/ and is world readable + ret = cluster.conf_read_file("ceph.conf"); + if( ret < 0) + { + std::cerr << "Couldn't read conf file "<< ret << std::endl; + } + ret = cluster.connect(); + if(ret < 0) + { + std::cerr << "Couldn't connect to cluster "<< ret << std::endl; + } + else + { + std::cout << "Connected to Cluster"<< std::endl; + } + + ret = cluster.ioctx_create(pool_name.c_str(), io_ctx); + + if(ret < 0) + { + std::cerr << "Couldn't Create IO_CTX"<< ret << std::endl; + } + ret = libradosstriper::RadosStriper::striper_create(io_ctx,rs); + if(ret < 0) + { + std::cerr << "Couldn't Create RadosStriper"<< ret << std::endl; + delete rs; + } + uint64_t alignment = 0; + ret = io_ctx.pool_required_alignment2(&alignment); + if(ret < 0) + { + std::cerr << "IO_CTX didn't give alignment "<< ret + << "\n Is this an erasure coded pool? "<< std::endl; + + delete rs; + io_ctx.close(); + cluster.shutdown(); + return EXIT_FAILURE; + } + std::cout << "Pool alignment: "<< alignment << std::endl; + rs->set_object_layout_stripe_unit(alignment); + // how many objects are we striping across? + rs->set_object_layout_stripe_count(strip_count); + // how big should each object be? + rs->set_object_layout_object_size(obj_size); + + std::string err = "no_err"; + librados::bufferlist bl; + bl.read_file(fname.c_str(),&err); + if(err != "no_err") + { + std::cout << "Error reading file into bufferlist: "<< err << std::endl; + delete rs; + io_ctx.close(); + cluster.shutdown(); + return EXIT_FAILURE; + } + + std::cout << "Writing: " << fname << "\nas: "<< obj_name << std::endl; + rs->write_full(obj_name,bl); + std::cout << "done with: " << fname << std::endl; + + delete rs; + io_ctx.close(); + cluster.shutdown(); +} diff --git a/ceph/install-deps.sh b/ceph/install-deps.sh index 90347622e..626cbc9e3 100755 --- a/ceph/install-deps.sh +++ b/ceph/install-deps.sh @@ -22,6 +22,7 @@ export LC_ALL=C # the following is vulnerable to i18n if [ x`uname`x = xFreeBSDx ]; then $SUDO pkg install -yq \ devel/git \ + devel/gperf \ devel/gmake \ devel/cmake \ devel/yasm \ @@ -29,7 +30,6 @@ if [ x`uname`x = xFreeBSDx ]; then devel/boost-python-libs \ devel/valgrind \ devel/pkgconf \ - devel/libatomic_ops \ devel/libedit \ devel/libtool \ devel/google-perftools \ @@ -52,6 +52,7 @@ if [ x`uname`x = xFreeBSDx ]; then emulators/fuse \ java/junit \ lang/python27 \ + devel/py-pip \ devel/py-argparse \ devel/py-nose \ www/py-flask \ @@ -59,6 +60,9 @@ if [ x`uname`x = xFreeBSDx ]; then sysutils/flock \ sysutils/fusefs-libs \ + # Now use pip to install some extra python modules + pip install pecan + exit else source /etc/os-release @@ -159,7 +163,8 @@ function populate_wheelhouse() { # although pip comes with virtualenv, having a recent version # of pip matters when it comes to using wheel packages - pip --timeout 300 $install 'setuptools >= 0.8' 'pip >= 7.0' 'wheel >= 0.24' || return 1 + # workaround of https://github.com/pypa/setuptools/issues/1042 + pip --timeout 300 $install 'setuptools >= 0.8,< 36' 'pip >= 7.0' 'wheel >= 0.24' || return 1 if test $# != 0 ; then pip --timeout 300 $install $@ || return 1 fi diff --git a/ceph/mirroring/MIRRORS b/ceph/mirroring/MIRRORS index 24b0b520f..408a2bb3b 100644 --- a/ceph/mirroring/MIRRORS +++ b/ceph/mirroring/MIRRORS @@ -8,3 +8,4 @@ us-east.ceph.com: Tyler Bishop hk.ceph.com: Mart van Santen fr.ceph.com: Adrien Gillard uk.ceph.com: Tim Bishop +cn.ceph.com: USTC LUG diff --git a/ceph/qa/clusters/extra-client.yaml b/ceph/qa/clusters/extra-client.yaml index 2b495374f..33fa505b7 100644 --- a/ceph/qa/clusters/extra-client.yaml +++ b/ceph/qa/clusters/extra-client.yaml @@ -7,3 +7,8 @@ openstack: - volumes: # attached to each instance count: 3 size: 10 # GB +overrides: + ceph: + conf: + osd: + osd shutdown pgref assert: true \ No newline at end of file diff --git a/ceph/qa/clusters/fixed-1.yaml b/ceph/qa/clusters/fixed-1.yaml index 38725b086..d8e5898b9 100644 --- a/ceph/qa/clusters/fixed-1.yaml +++ b/ceph/qa/clusters/fixed-1.yaml @@ -6,5 +6,9 @@ overrides: osd crush chooseleaf type: 0 osd pool default pg num: 128 osd pool default pgp num: 128 + ceph: + conf: + osd: + osd shutdown pgref assert: true roles: - [mon.a, mgr.x, osd.0, osd.1, osd.2, client.0] diff --git a/ceph/qa/clusters/fixed-2.yaml b/ceph/qa/clusters/fixed-2.yaml index 6886d1701..3b08e287d 100644 --- a/ceph/qa/clusters/fixed-2.yaml +++ b/ceph/qa/clusters/fixed-2.yaml @@ -5,3 +5,8 @@ openstack: - volumes: # attached to each instance count: 3 size: 10 # GB +overrides: + ceph: + conf: + osd: + osd shutdown pgref assert: true \ No newline at end of file diff --git a/ceph/qa/clusters/fixed-3-cephfs.yaml b/ceph/qa/clusters/fixed-3-cephfs.yaml index 7e2e5f05c..2d2112f9f 100644 --- a/ceph/qa/clusters/fixed-3-cephfs.yaml +++ b/ceph/qa/clusters/fixed-3-cephfs.yaml @@ -9,3 +9,8 @@ openstack: log-rotate: ceph-mds: 10G ceph-osd: 10G +overrides: + ceph: + conf: + osd: + osd shutdown pgref assert: true \ No newline at end of file diff --git a/ceph/qa/clusters/fixed-3.yaml b/ceph/qa/clusters/fixed-3.yaml index 3ed30b94f..cd4f4e8ec 100644 --- a/ceph/qa/clusters/fixed-3.yaml +++ b/ceph/qa/clusters/fixed-3.yaml @@ -6,3 +6,8 @@ openstack: - volumes: # attached to each instance count: 3 size: 10 # GB +overrides: + ceph: + conf: + osd: + osd shutdown pgref assert: true \ No newline at end of file diff --git a/ceph/qa/clusters/fixed-4.yaml b/ceph/qa/clusters/fixed-4.yaml index 86eb2c634..df767f357 100644 --- a/ceph/qa/clusters/fixed-4.yaml +++ b/ceph/qa/clusters/fixed-4.yaml @@ -3,3 +3,8 @@ roles: - [mon.b, osd.1, osd.5, osd.9, osd.13] - [mon.c, osd.2, osd.6, osd.10, osd.14] - [mgr.x, osd.3, osd.7, osd.11, osd.15, client.0] +overrides: + ceph: + conf: + osd: + osd shutdown pgref assert: true \ No newline at end of file diff --git a/ceph/qa/machine_types/vps.yaml b/ceph/qa/machine_types/vps.yaml index bffa0985d..64a3da47d 100644 --- a/ceph/qa/machine_types/vps.yaml +++ b/ceph/qa/machine_types/vps.yaml @@ -6,8 +6,6 @@ overrides: # this line to address issue #1017 mon lease: 15 mon lease ack timeout: 25 - rgw: - default_idle_timeout: 1200 s3tests: idle_timeout: 1200 ceph-fuse: diff --git a/ceph/qa/objectstore/bluestore-comp.yaml b/ceph/qa/objectstore/bluestore-comp.yaml index 6c466bed6..274962f0f 100644 --- a/ceph/qa/objectstore/bluestore-comp.yaml +++ b/ceph/qa/objectstore/bluestore-comp.yaml @@ -12,8 +12,8 @@ overrides: debug bdev: 20 debug bluefs: 20 debug rocksdb: 10 - enable experimental unrecoverable data corrupting features: "*" bluestore compression mode: aggressive + bluestore fsck on mount: true # this doesn't work with failures bc the log writes are not atomic across the two backends # bluestore bluefs env mirror: true diff --git a/ceph/qa/objectstore/bluestore.yaml b/ceph/qa/objectstore/bluestore.yaml index 361dae308..d7f59aa45 100644 --- a/ceph/qa/objectstore/bluestore.yaml +++ b/ceph/qa/objectstore/bluestore.yaml @@ -12,6 +12,7 @@ overrides: debug bdev: 20 debug bluefs: 20 debug rocksdb: 10 - enable experimental unrecoverable data corrupting features: "*" + bluestore fsck on mount: true + # this doesn't work with failures bc the log writes are not atomic across the two backends # bluestore bluefs env mirror: true diff --git a/ceph/qa/releases/luminous-with-mgr.yaml b/ceph/qa/releases/luminous-with-mgr.yaml index 880df732b..ea3130768 100644 --- a/ceph/qa/releases/luminous-with-mgr.yaml +++ b/ceph/qa/releases/luminous-with-mgr.yaml @@ -1,7 +1,7 @@ tasks: - exec: osd.0: - - ceph osd set require_luminous_osds + - ceph osd require-osd-release luminous - ceph osd set-require-min-compat-client luminous - ceph.healthy: overrides: diff --git a/ceph/qa/releases/luminous.yaml b/ceph/qa/releases/luminous.yaml index 22bb78b2d..9ed76715a 100644 --- a/ceph/qa/releases/luminous.yaml +++ b/ceph/qa/releases/luminous.yaml @@ -9,7 +9,7 @@ tasks: wait-for-healthy: false - exec: osd.0: - - ceph osd set require_luminous_osds + - ceph osd require-osd-release luminous - ceph osd set-require-min-compat-client luminous - ceph.healthy: overrides: diff --git a/ceph/qa/suites/fs/basic_functional/tasks/client-recovery.yaml b/ceph/qa/suites/fs/basic_functional/tasks/client-recovery.yaml index 1433ee1d8..a329ff5d1 100644 --- a/ceph/qa/suites/fs/basic_functional/tasks/client-recovery.yaml +++ b/ceph/qa/suites/fs/basic_functional/tasks/client-recovery.yaml @@ -4,6 +4,7 @@ overrides: ceph: log-whitelist: + - evicting unresponsive client - wrongly marked me down - slow request diff --git a/ceph/qa/suites/fs/standbyreplay/tasks/migration.yaml b/ceph/qa/suites/fs/basic_functional/tasks/test_journal_migration.yaml similarity index 100% rename from ceph/qa/suites/fs/standbyreplay/tasks/migration.yaml rename to ceph/qa/suites/fs/basic_functional/tasks/test_journal_migration.yaml diff --git a/ceph/qa/suites/fs/multiclient/tasks/cephfs_misc_tests.yaml b/ceph/qa/suites/fs/multiclient/tasks/cephfs_misc_tests.yaml index 4192fcafb..0f1572377 100644 --- a/ceph/qa/suites/fs/multiclient/tasks/cephfs_misc_tests.yaml +++ b/ceph/qa/suites/fs/multiclient/tasks/cephfs_misc_tests.yaml @@ -2,3 +2,8 @@ tasks: - cephfs_test_runner: modules: - tasks.cephfs.test_misc + +overrides: + ceph: + log-whitelist: + - evicting unresponsive client diff --git a/ceph/qa/suites/fs/multifs/tasks/failover.yaml b/ceph/qa/suites/fs/multifs/tasks/failover.yaml index d837d4b26..3358b664e 100644 --- a/ceph/qa/suites/fs/multifs/tasks/failover.yaml +++ b/ceph/qa/suites/fs/multifs/tasks/failover.yaml @@ -1,4 +1,7 @@ overrides: + ceph: + log-whitelist: + - not responding, replacing ceph-fuse: disabled: true tasks: diff --git a/ceph/qa/suites/fs/standbyreplay/begin.yaml b/ceph/qa/suites/fs/standbyreplay/begin.yaml deleted file mode 120000 index 0c4ae31e9..000000000 --- a/ceph/qa/suites/fs/standbyreplay/begin.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../cephfs/begin.yaml \ No newline at end of file diff --git a/ceph/qa/suites/fs/standbyreplay/clusters/standby-replay.yaml b/ceph/qa/suites/fs/standbyreplay/clusters/standby-replay.yaml deleted file mode 100644 index a4bafed29..000000000 --- a/ceph/qa/suites/fs/standbyreplay/clusters/standby-replay.yaml +++ /dev/null @@ -1,17 +0,0 @@ - -overrides: - ceph: - conf: - mds: - mds standby replay: true - -roles: -- [mon.a, mgr.x, mds.a, mds.b-s-0, osd.0, osd.1, client.0] -- [mon.b, mds.c-s-0, mds.d-s-0, mon.c, osd.2, osd.3] -openstack: -- volumes: # attached to each instance - count: 2 - size: 10 # GB -log-rotate: - ceph-mds: 10G - ceph-osd: 10G diff --git a/ceph/qa/suites/fs/standbyreplay/mount/fuse.yaml b/ceph/qa/suites/fs/standbyreplay/mount/fuse.yaml deleted file mode 120000 index af9ee0ab7..000000000 --- a/ceph/qa/suites/fs/standbyreplay/mount/fuse.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../cephfs/mount/fuse.yaml \ No newline at end of file diff --git a/ceph/qa/suites/fs/standbyreplay/objectstore b/ceph/qa/suites/fs/standbyreplay/objectstore deleted file mode 120000 index c72da2f82..000000000 --- a/ceph/qa/suites/fs/standbyreplay/objectstore +++ /dev/null @@ -1 +0,0 @@ -../../../objectstore_cephfs \ No newline at end of file diff --git a/ceph/qa/suites/fs/standbyreplay/overrides/debug.yaml b/ceph/qa/suites/fs/standbyreplay/overrides/debug.yaml deleted file mode 120000 index 9bc8eb1e7..000000000 --- a/ceph/qa/suites/fs/standbyreplay/overrides/debug.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../cephfs/overrides/debug.yaml \ No newline at end of file diff --git a/ceph/qa/suites/fs/standbyreplay/overrides/frag_enable.yaml b/ceph/qa/suites/fs/standbyreplay/overrides/frag_enable.yaml deleted file mode 120000 index e9b2d64d0..000000000 --- a/ceph/qa/suites/fs/standbyreplay/overrides/frag_enable.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../cephfs/overrides/frag_enable.yaml \ No newline at end of file diff --git a/ceph/qa/suites/fs/standbyreplay/overrides/whitelist_wrongly_marked_down.yaml b/ceph/qa/suites/fs/standbyreplay/overrides/whitelist_wrongly_marked_down.yaml deleted file mode 120000 index a26a6579c..000000000 --- a/ceph/qa/suites/fs/standbyreplay/overrides/whitelist_wrongly_marked_down.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../cephfs/overrides/whitelist_wrongly_marked_down.yaml \ No newline at end of file diff --git a/ceph/qa/suites/fs/thrash/ceph-thrash/default.yaml b/ceph/qa/suites/fs/thrash/ceph-thrash/default.yaml index aefdf826c..154615c51 100644 --- a/ceph/qa/suites/fs/thrash/ceph-thrash/default.yaml +++ b/ceph/qa/suites/fs/thrash/ceph-thrash/default.yaml @@ -1,2 +1,7 @@ tasks: - mds_thrash: + +overrides: + ceph: + log-whitelist: + - not responding, replacing diff --git a/ceph/qa/suites/kcephfs/recovery/tasks/auto-repair.yaml b/ceph/qa/suites/kcephfs/recovery/tasks/auto-repair.yaml index e331cdd65..629804ec7 100644 --- a/ceph/qa/suites/kcephfs/recovery/tasks/auto-repair.yaml +++ b/ceph/qa/suites/kcephfs/recovery/tasks/auto-repair.yaml @@ -3,6 +3,7 @@ overrides: log-whitelist: - force file system read-only - bad backtrace + - MDS in read-only mode tasks: diff --git a/ceph/qa/suites/kcephfs/recovery/tasks/client-limits.yaml b/ceph/qa/suites/kcephfs/recovery/tasks/client-limits.yaml index 2f710a206..d297e5c3a 100644 --- a/ceph/qa/suites/kcephfs/recovery/tasks/client-limits.yaml +++ b/ceph/qa/suites/kcephfs/recovery/tasks/client-limits.yaml @@ -4,6 +4,11 @@ overrides: log-whitelist: - responding to mclientcaps\(revoke\) - not advance its oldest_client_tid + - failing to advance its oldest client/flush tid + - Too many inodes in cache + - failing to respond to cache pressure + - slow requests are blocked + - failing to respond to capability release tasks: - cephfs_test_runner: diff --git a/ceph/qa/suites/kcephfs/recovery/tasks/damage.yaml b/ceph/qa/suites/kcephfs/recovery/tasks/damage.yaml index 4b8497771..3f4aac9e5 100644 --- a/ceph/qa/suites/kcephfs/recovery/tasks/damage.yaml +++ b/ceph/qa/suites/kcephfs/recovery/tasks/damage.yaml @@ -16,6 +16,7 @@ overrides: - corrupt sessionmap header - Corrupt dentry - Scrub error on inode + - Metadata damage detected tasks: - cephfs_test_runner: diff --git a/ceph/qa/suites/kcephfs/recovery/tasks/data-scan.yaml b/ceph/qa/suites/kcephfs/recovery/tasks/data-scan.yaml index dd0a85f68..9428624e0 100644 --- a/ceph/qa/suites/kcephfs/recovery/tasks/data-scan.yaml +++ b/ceph/qa/suites/kcephfs/recovery/tasks/data-scan.yaml @@ -8,6 +8,8 @@ overrides: - error reading sessionmap - unmatched fragstat - was unreadable, recreating it now + - Scrub error on inode + - Metadata damage detected tasks: - cephfs_test_runner: diff --git a/ceph/qa/suites/kcephfs/recovery/tasks/forward-scrub.yaml b/ceph/qa/suites/kcephfs/recovery/tasks/forward-scrub.yaml index dbbed4bf7..b92cf1052 100644 --- a/ceph/qa/suites/kcephfs/recovery/tasks/forward-scrub.yaml +++ b/ceph/qa/suites/kcephfs/recovery/tasks/forward-scrub.yaml @@ -6,6 +6,7 @@ overrides: - bad backtrace on inode - inode table repaired for inode - Scrub error on inode + - Metadata damage detected tasks: - cephfs_test_runner: diff --git a/ceph/qa/suites/kcephfs/recovery/tasks/journal-repair.yaml b/ceph/qa/suites/kcephfs/recovery/tasks/journal-repair.yaml index c85f46cb8..324ff75df 100644 --- a/ceph/qa/suites/kcephfs/recovery/tasks/journal-repair.yaml +++ b/ceph/qa/suites/kcephfs/recovery/tasks/journal-repair.yaml @@ -4,6 +4,9 @@ overrides: log-whitelist: - bad backtrace on dir ino - error reading table object + - Metadata damage detected + - slow requests are blocked + - Behind on trimming tasks: - cephfs_test_runner: diff --git a/ceph/qa/suites/kcephfs/thrash/thrashers/mds.yaml b/ceph/qa/suites/kcephfs/thrash/thrashers/mds.yaml index cab4a01a5..d5d1f4357 100644 --- a/ceph/qa/suites/kcephfs/thrash/thrashers/mds.yaml +++ b/ceph/qa/suites/kcephfs/thrash/thrashers/mds.yaml @@ -2,3 +2,8 @@ tasks: - install: - ceph: - mds_thrash: + +overrides: + ceph: + log-whitelist: + - not responding, replacing diff --git a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_misc_test_o_trunc.yaml b/ceph/qa/suites/krbd/rbd-nomount/tasks/krbd_fallocate.yaml similarity index 57% rename from ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_misc_test_o_trunc.yaml rename to ceph/qa/suites/krbd/rbd-nomount/tasks/krbd_fallocate.yaml index c9de5c386..a72869824 100644 --- a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_misc_test_o_trunc.yaml +++ b/ceph/qa/suites/krbd/rbd-nomount/tasks/krbd_fallocate.yaml @@ -2,4 +2,4 @@ tasks: - workunit: clients: all: - - fs/test_o_trunc.sh + - rbd/krbd_fallocate.sh diff --git a/ceph/qa/suites/krbd/unmap/ceph/ceph.yaml b/ceph/qa/suites/krbd/unmap/ceph/ceph.yaml index a9713b393..c58aaca48 100644 --- a/ceph/qa/suites/krbd/unmap/ceph/ceph.yaml +++ b/ceph/qa/suites/krbd/unmap/ceph/ceph.yaml @@ -4,3 +4,6 @@ overrides: tasks: - install: - ceph: +- exec: + client.0: + - "ceph osd getcrushmap -o /dev/stdout | crushtool -d - | sed -e 's/alg straw2/alg straw/g' | crushtool -c /dev/stdin -o /dev/stdout | ceph osd setcrushmap -i /dev/stdin" diff --git a/ceph/qa/suites/multimds/basic/q_check_counter/check_counter.yaml b/ceph/qa/suites/multimds/basic/q_check_counter/check_counter.yaml new file mode 100644 index 000000000..1018b1e42 --- /dev/null +++ b/ceph/qa/suites/multimds/basic/q_check_counter/check_counter.yaml @@ -0,0 +1,8 @@ + +tasks: +- check-counter: + counters: + mds: + - "mds.exported" + - "mds.imported" + diff --git a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_fsync.yaml b/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_fsync.yaml deleted file mode 100644 index 7efa1adb8..000000000 --- a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_fsync.yaml +++ /dev/null @@ -1,5 +0,0 @@ -tasks: -- workunit: - clients: - all: - - suites/fsync-tester.sh diff --git a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iogen.yaml b/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iogen.yaml deleted file mode 100644 index 8d4c27108..000000000 --- a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iogen.yaml +++ /dev/null @@ -1,6 +0,0 @@ -tasks: -- workunit: - clients: - all: - - suites/iogen.sh - diff --git a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iozone.yaml b/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iozone.yaml deleted file mode 100644 index 9270f3c51..000000000 --- a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_iozone.yaml +++ /dev/null @@ -1,5 +0,0 @@ -tasks: -- workunit: - clients: - all: - - suites/iozone.sh diff --git a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_truncate_delay.yaml b/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_truncate_delay.yaml deleted file mode 100644 index b47b56569..000000000 --- a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_suites_truncate_delay.yaml +++ /dev/null @@ -1,14 +0,0 @@ -overrides: - ceph: - conf: - client: - ms_inject_delay_probability: 1 - ms_inject_delay_type: osd - ms_inject_delay_max: 5 - client_oc_max_dirty_age: 1 -tasks: -- exec: - client.0: - - cd $TESTDIR/mnt.* && dd if=/dev/zero of=./foo count=100 - - sleep 2 - - cd $TESTDIR/mnt.* && truncate --size 0 ./foo diff --git a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_trivial_sync.yaml b/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_trivial_sync.yaml deleted file mode 120000 index 55a4c85a1..000000000 --- a/ceph/qa/suites/multimds/basic/tasks/cfuse_workunit_trivial_sync.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../../cephfs/tasks/cfuse_workunit_trivial_sync.yaml \ No newline at end of file diff --git a/ceph/qa/suites/multimds/thrash/tasks/cfuse_workunit_trivial_sync.yaml b/ceph/qa/suites/multimds/thrash/tasks/cfuse_workunit_trivial_sync.yaml deleted file mode 120000 index 8a5485751..000000000 --- a/ceph/qa/suites/multimds/thrash/tasks/cfuse_workunit_trivial_sync.yaml +++ /dev/null @@ -1 +0,0 @@ -../../../fs/thrash/tasks/cfuse_workunit_trivial_sync.yaml \ No newline at end of file diff --git a/ceph/qa/suites/fs/standbyreplay/% b/ceph/qa/suites/rados/basic-luminous/% similarity index 100% rename from ceph/qa/suites/fs/standbyreplay/% rename to ceph/qa/suites/rados/basic-luminous/% diff --git a/ceph/qa/suites/rados/basic-luminous/ceph.yaml b/ceph/qa/suites/rados/basic-luminous/ceph.yaml new file mode 120000 index 000000000..1e1b9ef4a --- /dev/null +++ b/ceph/qa/suites/rados/basic-luminous/ceph.yaml @@ -0,0 +1 @@ +../basic/ceph.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/basic-luminous/clusters b/ceph/qa/suites/rados/basic-luminous/clusters new file mode 120000 index 000000000..ae92569e8 --- /dev/null +++ b/ceph/qa/suites/rados/basic-luminous/clusters @@ -0,0 +1 @@ +../basic/clusters \ No newline at end of file diff --git a/ceph/qa/suites/rados/basic-luminous/objectstore b/ceph/qa/suites/rados/basic-luminous/objectstore new file mode 120000 index 000000000..f81a13b68 --- /dev/null +++ b/ceph/qa/suites/rados/basic-luminous/objectstore @@ -0,0 +1 @@ +../basic/objectstore \ No newline at end of file diff --git a/ceph/qa/suites/rados/basic-luminous/rados.yaml b/ceph/qa/suites/rados/basic-luminous/rados.yaml new file mode 120000 index 000000000..9b356bf34 --- /dev/null +++ b/ceph/qa/suites/rados/basic-luminous/rados.yaml @@ -0,0 +1 @@ +../basic/rados.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/basic/tasks/scrub_test.yaml b/ceph/qa/suites/rados/basic-luminous/scrub_test.yaml similarity index 95% rename from ceph/qa/suites/rados/basic/tasks/scrub_test.yaml rename to ceph/qa/suites/rados/basic-luminous/scrub_test.yaml index 1847f80d4..07f039aae 100644 --- a/ceph/qa/suites/rados/basic/tasks/scrub_test.yaml +++ b/ceph/qa/suites/rados/basic-luminous/scrub_test.yaml @@ -1,5 +1,6 @@ overrides: ceph: + wait-for-scrub: false log-whitelist: - '!= data_digest' - '!= omap_digest' diff --git a/ceph/qa/suites/rados/basic/tasks/repair_test.yaml b/ceph/qa/suites/rados/basic/tasks/repair_test.yaml index bd98522d1..f69866994 100644 --- a/ceph/qa/suites/rados/basic/tasks/repair_test.yaml +++ b/ceph/qa/suites/rados/basic/tasks/repair_test.yaml @@ -1,5 +1,6 @@ overrides: ceph: + wait-for-scrub: false log-whitelist: - candidate had a stat error - candidate had a read error diff --git a/ceph/qa/suites/rados/basic/tasks/rgw_snaps.yaml b/ceph/qa/suites/rados/basic/tasks/rgw_snaps.yaml index 135db06b8..2108317a9 100644 --- a/ceph/qa/suites/rados/basic/tasks/rgw_snaps.yaml +++ b/ceph/qa/suites/rados/basic/tasks/rgw_snaps.yaml @@ -8,8 +8,7 @@ overrides: osd_max_omap_entries_per_request: 10 tasks: - rgw: - default_idle_timeout: 3600 - client.0: null + client.0: - thrash_pool_snaps: pools: - .rgw.buckets diff --git a/ceph/qa/suites/rados/rest/mgr-restful.yaml b/ceph/qa/suites/rados/rest/mgr-restful.yaml new file mode 100644 index 000000000..571857c25 --- /dev/null +++ b/ceph/qa/suites/rados/rest/mgr-restful.yaml @@ -0,0 +1,16 @@ +roles: +- [mon.a, mgr.x, osd.0, osd.1, osd.2, mds.a, client.a] +tasks: +- install: +- ceph: +- exec: + mon.a: + - ceph config-key put mgr/restful/x/server_addr 127.0.0.1 + - ceph config-key put mgr/restful/x/server_port 9999 + - ceph tell mgr.x restful create-key admin + - ceph tell mgr.x restful create-self-signed-cert +- ceph.restart: [mgr.x] +- workunit: + clients: + client.a: + - rest/test-restful.sh diff --git a/ceph/qa/suites/rados/singleton-nomsgr/all/admin_socket_output.yaml b/ceph/qa/suites/rados/singleton-nomsgr/all/admin_socket_output.yaml new file mode 100644 index 000000000..969c40902 --- /dev/null +++ b/ceph/qa/suites/rados/singleton-nomsgr/all/admin_socket_output.yaml @@ -0,0 +1,15 @@ +roles: +- [mon.a, mds.a, mgr.x, osd.0, osd.1, client.0] +overrides: + ceph: + log-whitelist: + - MDS in read-only mode + - force file system read-only +tasks: +- install: +- ceph: +- rgw: + - client.0 +- exec: + client.0: + - ceph_test_admin_socket_output --all diff --git a/ceph/qa/suites/rados/singleton-nomsgr/all/full-tiering.yaml b/ceph/qa/suites/rados/singleton-nomsgr/all/full-tiering.yaml index e21086a6b..9dc1fe7dc 100644 --- a/ceph/qa/suites/rados/singleton-nomsgr/all/full-tiering.yaml +++ b/ceph/qa/suites/rados/singleton-nomsgr/all/full-tiering.yaml @@ -24,3 +24,5 @@ tasks: - ceph osd pool set-quota ec max_bytes 20480000 - ceph osd pool set ec-ca target_max_bytes 20480000 - timeout 30 rados -p ec-ca bench 30 write || true + - ceph osd pool set-quota ec-ca max_bytes 0 + - ceph osd pool set-quota ec max_bytes 0 diff --git a/ceph/qa/suites/rados/singleton-nomsgr/all/health-warnings.yaml b/ceph/qa/suites/rados/singleton-nomsgr/all/health-warnings.yaml new file mode 100644 index 000000000..4c8228b0c --- /dev/null +++ b/ceph/qa/suites/rados/singleton-nomsgr/all/health-warnings.yaml @@ -0,0 +1,16 @@ +roles: +- [mon.a, mgr.x, osd.0, osd.1, osd.2, osd.3, osd.4, osd.5, osd.6, osd.7, osd.8, osd.9, client.0] +tasks: +- install: +- ceph: + conf: + osd: +# we may land on ext4 + osd max object name len: 400 + osd max object namespace len: 64 + log-whitelist: + - wrongly marked me down +- workunit: + clients: + all: + - rados/test_health_warnings.sh diff --git a/ceph/qa/suites/rados/singleton-nomsgr/all/multi-backfill-reject.yaml b/ceph/qa/suites/rados/singleton-nomsgr/all/multi-backfill-reject.yaml index 0afc444a7..b73899738 100644 --- a/ceph/qa/suites/rados/singleton-nomsgr/all/multi-backfill-reject.yaml +++ b/ceph/qa/suites/rados/singleton-nomsgr/all/multi-backfill-reject.yaml @@ -31,3 +31,6 @@ tasks: - sudo ceph osd in 0 1 - sleep: duration: 60 +- exec: + client.0: + - sudo ceph osd pool set foo size 2 diff --git a/ceph/qa/suites/rados/singleton-nomsgr/all/pool-access.yaml b/ceph/qa/suites/rados/singleton-nomsgr/all/pool-access.yaml new file mode 100644 index 000000000..d49a59797 --- /dev/null +++ b/ceph/qa/suites/rados/singleton-nomsgr/all/pool-access.yaml @@ -0,0 +1,9 @@ +roles: +- [mon.a, mgr.x, osd.0, osd.1, client.0] +tasks: +- install: +- ceph: +- workunit: + clients: + all: + - rados/test_pool_access.sh diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/ceph.yaml b/ceph/qa/suites/rados/thrash-erasure-code-big/ceph.yaml new file mode 120000 index 000000000..a2fd139cb --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/ceph.yaml @@ -0,0 +1 @@ +../thrash/ceph.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/d-require-luminous b/ceph/qa/suites/rados/thrash-erasure-code-big/d-require-luminous new file mode 120000 index 000000000..737aee824 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/d-require-luminous @@ -0,0 +1 @@ +../thrash/d-require-luminous/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/default.yaml b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/default.yaml index 5acfcc3dd..057a7ecdb 100644 --- a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/default.yaml +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/default.yaml @@ -1,6 +1,5 @@ -tasks: -- install: -- ceph: +overrides: + ceph: log-whitelist: - wrongly marked me down - objects unfound and apparently lost @@ -11,6 +10,7 @@ tasks: osd scrub min interval: 60 osd scrub max interval: 120 osd max backfills: 6 +tasks: - thrashosds: timeout: 1200 chance_pgnum_grow: 1 diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/fastread.yaml b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/fastread.yaml index 5ded6ba71..ec889775e 100644 --- a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/fastread.yaml +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/fastread.yaml @@ -1,6 +1,5 @@ -tasks: -- install: -- ceph: +overrides: + ceph: log-whitelist: - wrongly marked me down - objects unfound and apparently lost @@ -12,6 +11,7 @@ tasks: osd scrub min interval: 60 osd scrub max interval: 120 osd max backfills: 2 +tasks: - thrashosds: timeout: 1200 chance_pgnum_grow: 1 diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/mapgap.yaml b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/mapgap.yaml index 67720febb..5e93ac08f 100644 --- a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/mapgap.yaml +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/mapgap.yaml @@ -1,5 +1,9 @@ overrides: ceph: + log-whitelist: + - wrongly marked me down + - objects unfound and apparently lost + - osd_map_cache_size conf: mon: mon min osdmap epochs: 2 @@ -8,12 +12,6 @@ overrides: osd scrub min interval: 60 osd scrub max interval: 120 tasks: -- install: -- ceph: - log-whitelist: - - wrongly marked me down - - objects unfound and apparently lost - - osd_map_cache_size - thrashosds: timeout: 1800 chance_pgnum_grow: 1 diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/morepggrow.yaml b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/morepggrow.yaml index f09ec08cf..efda9161e 100644 --- a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/morepggrow.yaml +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/morepggrow.yaml @@ -1,6 +1,5 @@ -tasks: -- install: -- ceph: +overrides: + ceph: conf: osd: osd scrub min interval: 60 @@ -9,6 +8,7 @@ tasks: log-whitelist: - wrongly marked me down - objects unfound and apparently lost +tasks: - thrashosds: timeout: 1200 chance_pgnum_grow: 3 diff --git a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/pggrow.yaml b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/pggrow.yaml index 1117cddfc..772f2093c 100644 --- a/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/pggrow.yaml +++ b/ceph/qa/suites/rados/thrash-erasure-code-big/thrashers/pggrow.yaml @@ -1,6 +1,5 @@ -tasks: -- install: -- ceph: +overrides: + ceph: log-whitelist: - wrongly marked me down - objects unfound and apparently lost @@ -8,6 +7,7 @@ tasks: osd: osd scrub min interval: 60 osd scrub max interval: 120 +tasks: - thrashosds: timeout: 1200 chance_pgnum_grow: 2 diff --git a/ceph/qa/suites/rados/thrash-erasure-code-isa/d-require-luminous b/ceph/qa/suites/rados/thrash-erasure-code-isa/d-require-luminous new file mode 120000 index 000000000..737aee824 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-isa/d-require-luminous @@ -0,0 +1 @@ +../thrash/d-require-luminous/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-overwrites/ceph.yaml b/ceph/qa/suites/rados/thrash-erasure-code-overwrites/ceph.yaml new file mode 120000 index 000000000..a2fd139cb --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-overwrites/ceph.yaml @@ -0,0 +1 @@ +../thrash/ceph.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-overwrites/d-require-luminous b/ceph/qa/suites/rados/thrash-erasure-code-overwrites/d-require-luminous new file mode 120000 index 000000000..737aee824 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-overwrites/d-require-luminous @@ -0,0 +1 @@ +../thrash/d-require-luminous/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-shec/ceph.yaml b/ceph/qa/suites/rados/thrash-erasure-code-shec/ceph.yaml new file mode 120000 index 000000000..a2fd139cb --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-shec/ceph.yaml @@ -0,0 +1 @@ +../thrash/ceph.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-shec/d-require-luminous b/ceph/qa/suites/rados/thrash-erasure-code-shec/d-require-luminous new file mode 120000 index 000000000..737aee824 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-erasure-code-shec/d-require-luminous @@ -0,0 +1 @@ +../thrash/d-require-luminous/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-erasure-code-shec/thrashers/default.yaml b/ceph/qa/suites/rados/thrash-erasure-code-shec/thrashers/default.yaml index 2bece1f93..5bff561a9 100644 --- a/ceph/qa/suites/rados/thrash-erasure-code-shec/thrashers/default.yaml +++ b/ceph/qa/suites/rados/thrash-erasure-code-shec/thrashers/default.yaml @@ -1,6 +1,5 @@ -tasks: -- install: -- ceph: +overrides: + ceph: log-whitelist: - wrongly marked me down - objects unfound and apparently lost @@ -11,6 +10,7 @@ tasks: osd scrub min interval: 60 osd scrub max interval: 120 osd max backfills: 3 +tasks: - thrashosds: timeout: 1200 chance_pgnum_grow: 1 diff --git a/ceph/qa/suites/fs/standbyreplay/overrides/+ b/ceph/qa/suites/rados/thrash-luminous/% similarity index 100% rename from ceph/qa/suites/fs/standbyreplay/overrides/+ rename to ceph/qa/suites/rados/thrash-luminous/% diff --git a/ceph/qa/suites/rados/thrash-luminous/0-size-min-size-overrides b/ceph/qa/suites/rados/thrash-luminous/0-size-min-size-overrides new file mode 120000 index 000000000..ce15740e9 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/0-size-min-size-overrides @@ -0,0 +1 @@ +../thrash/0-size-min-size-overrides/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/1-pg-log-overrides b/ceph/qa/suites/rados/thrash-luminous/1-pg-log-overrides new file mode 120000 index 000000000..d68d36c5a --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/1-pg-log-overrides @@ -0,0 +1 @@ +../thrash/1-pg-log-overrides/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/backoff b/ceph/qa/suites/rados/thrash-luminous/backoff new file mode 120000 index 000000000..dc7814b86 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/backoff @@ -0,0 +1 @@ +../thrash/backoff/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/ceph.yaml b/ceph/qa/suites/rados/thrash-luminous/ceph.yaml new file mode 120000 index 000000000..a2fd139cb --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/ceph.yaml @@ -0,0 +1 @@ +../thrash/ceph.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/clusters b/ceph/qa/suites/rados/thrash-luminous/clusters new file mode 120000 index 000000000..729c96f71 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/clusters @@ -0,0 +1 @@ +../thrash/clusters/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/msgr b/ceph/qa/suites/rados/thrash-luminous/msgr new file mode 120000 index 000000000..8113e02da --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/msgr @@ -0,0 +1 @@ +../thrash/msgr \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/objectstore b/ceph/qa/suites/rados/thrash-luminous/objectstore new file mode 120000 index 000000000..38ae00c33 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/objectstore @@ -0,0 +1 @@ +../thrash/objectstore/ \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/rados.yaml b/ceph/qa/suites/rados/thrash-luminous/rados.yaml new file mode 120000 index 000000000..2834d2ed8 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/rados.yaml @@ -0,0 +1 @@ +../thrash/rados.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/rocksdb.yaml b/ceph/qa/suites/rados/thrash-luminous/rocksdb.yaml new file mode 120000 index 000000000..9aaadffd8 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/rocksdb.yaml @@ -0,0 +1 @@ +../thrash/rocksdb.yaml \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/thrashers b/ceph/qa/suites/rados/thrash-luminous/thrashers new file mode 120000 index 000000000..f461dadc3 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/thrashers @@ -0,0 +1 @@ +../thrash/thrashers \ No newline at end of file diff --git a/ceph/qa/suites/rados/thrash-luminous/workloads/redirect.yaml b/ceph/qa/suites/rados/thrash-luminous/workloads/redirect.yaml new file mode 100644 index 000000000..50bd812b4 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/workloads/redirect.yaml @@ -0,0 +1,11 @@ +tasks: +- rados: + clients: [client.0] + ops: 4000 + objects: 500 + set_redirect: true + op_weights: + read: 100 + write: 100 + delete: 50 + copy_from: 50 diff --git a/ceph/qa/suites/rados/thrash-luminous/workloads/redirect_set_object.yaml b/ceph/qa/suites/rados/thrash-luminous/workloads/redirect_set_object.yaml new file mode 100644 index 000000000..74595e2f1 --- /dev/null +++ b/ceph/qa/suites/rados/thrash-luminous/workloads/redirect_set_object.yaml @@ -0,0 +1,9 @@ +tasks: +- rados: + clients: [client.0] + ops: 4000 + objects: 500 + set_redirect: true + op_weights: + set_redirect: 100 + copy_from: 100 diff --git a/ceph/qa/suites/rados/thrash/d-require-luminous/at-end.yaml b/ceph/qa/suites/rados/thrash/d-require-luminous/at-end.yaml index cca854183..bb1d7073c 100644 --- a/ceph/qa/suites/rados/thrash/d-require-luminous/at-end.yaml +++ b/ceph/qa/suites/rados/thrash/d-require-luminous/at-end.yaml @@ -5,7 +5,10 @@ tasks: - full_sequential_finally: - exec: mon.a: - - ceph osd set require_luminous_osds + - ceph osd require-osd-release luminous +# make sure osds have latest map + - rados -p rbd bench 5 write -b 4096 + - ceph.healthy: - ceph.osd_scrub_pgs: cluster: ceph - exec: diff --git a/ceph/qa/suites/rados/thrash/workloads/radosbench.yaml b/ceph/qa/suites/rados/thrash/workloads/radosbench.yaml index 3a0c6b2fb..1b25004a1 100644 --- a/ceph/qa/suites/rados/thrash/workloads/radosbench.yaml +++ b/ceph/qa/suites/rados/thrash/workloads/radosbench.yaml @@ -9,19 +9,25 @@ tasks: - full_sequential: - radosbench: clients: [client.0] - time: 120 + time: 90 - radosbench: clients: [client.0] - time: 120 + time: 90 - radosbench: clients: [client.0] - time: 120 + time: 90 - radosbench: clients: [client.0] - time: 120 + time: 90 - radosbench: clients: [client.0] - time: 120 + time: 90 - radosbench: clients: [client.0] - time: 120 + time: 90 + - radosbench: + clients: [client.0] + time: 90 + - radosbench: + clients: [client.0] + time: 90 diff --git a/ceph/qa/suites/rados/upgrade/jewel-x-singleton/6-finish-upgrade.yaml b/ceph/qa/suites/rados/upgrade/jewel-x-singleton/6-finish-upgrade.yaml index b48d2a0e3..8dff34589 100644 --- a/ceph/qa/suites/rados/upgrade/jewel-x-singleton/6-finish-upgrade.yaml +++ b/ceph/qa/suites/rados/upgrade/jewel-x-singleton/6-finish-upgrade.yaml @@ -9,3 +9,7 @@ tasks: daemons: [osd.3, osd.4, osd.5] wait-for-up: true wait-for-healthy: false +- ceph.restart: + daemons: [mds.a] + wait-for-up: true + wait-for-healthy: false diff --git a/ceph/qa/suites/rados/upgrade/jewel-x-singleton/8-workload/rgw-swift.yaml b/ceph/qa/suites/rados/upgrade/jewel-x-singleton/8-workload/rgw-swift.yaml index ba004ceac..e41f47ad0 100644 --- a/ceph/qa/suites/rados/upgrade/jewel-x-singleton/8-workload/rgw-swift.yaml +++ b/ceph/qa/suites/rados/upgrade/jewel-x-singleton/8-workload/rgw-swift.yaml @@ -4,7 +4,6 @@ meta: tasks: - rgw: client.0: - default_idle_timeout: 300 - print: "**** done rgw 9-workload" - swift: client.0: diff --git a/ceph/qa/suites/rbd/valgrind/validator/memcheck.yaml b/ceph/qa/suites/rbd/valgrind/validator/memcheck.yaml index 4ee49f16e..c5348269a 100644 --- a/ceph/qa/suites/rbd/valgrind/validator/memcheck.yaml +++ b/ceph/qa/suites/rbd/valgrind/validator/memcheck.yaml @@ -8,4 +8,4 @@ overrides: valgrind: ["--tool=memcheck"] workunit: env: - VALGRIND: "memcheck" + VALGRIND: "--tool=memcheck --leak-check=full" diff --git a/ceph/qa/suites/rgw/multifs/frontend/apache.yaml b/ceph/qa/suites/rgw/multifs/frontend/apache.yaml deleted file mode 100644 index 53ebf758e..000000000 --- a/ceph/qa/suites/rgw/multifs/frontend/apache.yaml +++ /dev/null @@ -1,3 +0,0 @@ -overrides: - rgw: - frontend: apache diff --git a/ceph/qa/suites/rgw/multifs/overrides.yaml b/ceph/qa/suites/rgw/multifs/overrides.yaml index 3aaef75af..161e1e378 100644 --- a/ceph/qa/suites/rgw/multifs/overrides.yaml +++ b/ceph/qa/suites/rgw/multifs/overrides.yaml @@ -1,5 +1,6 @@ overrides: ceph: + wait-for-scrub: false conf: client: debug rgw: 20 diff --git a/ceph/src/pybind/mgr/rest/app/__init__.py b/ceph/qa/suites/rgw/multisite/% similarity index 100% rename from ceph/src/pybind/mgr/rest/app/__init__.py rename to ceph/qa/suites/rgw/multisite/% diff --git a/ceph/qa/suites/rgw/multisite/clusters.yaml b/ceph/qa/suites/rgw/multisite/clusters.yaml new file mode 100644 index 000000000..536ef7ca4 --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/clusters.yaml @@ -0,0 +1,3 @@ +roles: +- [c1.mon.a, c1.mgr.x, c1.osd.0, c1.osd.1, c1.osd.2, c1.client.0, c1.client.1] +- [c2.mon.a, c2.mgr.x, c2.osd.0, c2.osd.1, c2.osd.2, c2.client.0, c2.client.1] diff --git a/ceph/qa/suites/rgw/multisite/frontend/civetweb.yaml b/ceph/qa/suites/rgw/multisite/frontend/civetweb.yaml new file mode 100644 index 000000000..5845a0e6c --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/frontend/civetweb.yaml @@ -0,0 +1,3 @@ +overrides: + rgw: + frontend: civetweb diff --git a/ceph/qa/suites/rgw/multisite/overrides.yaml b/ceph/qa/suites/rgw/multisite/overrides.yaml new file mode 100644 index 000000000..c41470d52 --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/overrides.yaml @@ -0,0 +1,8 @@ +overrides: + ceph: + wait-for-scrub: false + conf: + client: + debug rgw: 20 + rgw: + compression type: random diff --git a/ceph/qa/suites/rgw/multisite/realms/three-zone.yaml b/ceph/qa/suites/rgw/multisite/realms/three-zone.yaml new file mode 100644 index 000000000..a8a7ca1d1 --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/realms/three-zone.yaml @@ -0,0 +1,20 @@ +overrides: + rgw-multisite: + realm: + name: test-realm + is default: true + zonegroups: + - name: test-zonegroup + is_master: true + is_default: true + endpoints: [c1.client.0] + zones: + - name: test-zone1 + is_master: true + is_default: true + endpoints: [c1.client.0] + - name: test-zone2 + is_default: true + endpoints: [c2.client.0] + - name: test-zone3 + endpoints: [c1.client.1] diff --git a/ceph/qa/suites/rgw/multisite/realms/two-zonegroup.yaml b/ceph/qa/suites/rgw/multisite/realms/two-zonegroup.yaml new file mode 100644 index 000000000..dc5a786ce --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/realms/two-zonegroup.yaml @@ -0,0 +1,27 @@ +overrides: + rgw-multisite: + realm: + name: test-realm + is default: true + zonegroups: + - name: a + is_master: true + is_default: true + endpoints: [c1.client.0] + zones: + - name: a1 + is_master: true + is_default: true + endpoints: [c1.client.0] + - name: a2 + endpoints: [c1.client.1] + - name: b + is_default: true + endpoints: [c2.client.0] + zones: + - name: b1 + is_master: true + is_default: true + endpoints: [c2.client.0] + - name: b2 + endpoints: [c2.client.1] diff --git a/ceph/qa/suites/rgw/multisite/tasks/test_multi.yaml b/ceph/qa/suites/rgw/multisite/tasks/test_multi.yaml new file mode 100644 index 000000000..508c06a52 --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/tasks/test_multi.yaml @@ -0,0 +1,17 @@ +tasks: +- install: +- ceph: {cluster: c1} +- ceph: {cluster: c2} +- rgw: + c1.client.0: + valgrind: [--tool=memcheck] + c1.client.1: + valgrind: [--tool=memcheck] + c2.client.0: + valgrind: [--tool=memcheck] + c2.client.1: + valgrind: [--tool=memcheck] +- rgw-multisite: +- rgw-multisite-tests: + config: + reconfigure_delay: 60 diff --git a/ceph/qa/suites/rgw/multisite/valgrind.yaml b/ceph/qa/suites/rgw/multisite/valgrind.yaml new file mode 100644 index 000000000..1e17c783a --- /dev/null +++ b/ceph/qa/suites/rgw/multisite/valgrind.yaml @@ -0,0 +1,13 @@ +os_type: centos # xenial valgrind buggy, see http://tracker.ceph.com/issues/18126 +overrides: + install: + ceph: + flavor: notcmalloc + ceph: + conf: + global: + osd heartbeat grace: 40 + valgrind: + mon: [--tool=memcheck, --leak-check=full, --show-reachable=yes] + osd: [--tool=memcheck] + mds: [--tool=memcheck] diff --git a/ceph/qa/suites/rgw/singleton/all/radosgw-admin-data-sync.yaml b/ceph/qa/suites/rgw/singleton/all/radosgw-admin-data-sync.yaml deleted file mode 100644 index 03d7c612c..000000000 --- a/ceph/qa/suites/rgw/singleton/all/radosgw-admin-data-sync.yaml +++ /dev/null @@ -1,65 +0,0 @@ -roles: -- [mon.a, osd.0, client.0] -- [mgr.x, osd.1, osd.2, osd.3, client.1] -openstack: -- volumes: # attached to each instance - count: 3 - size: 10 # GB -tasks: -- install: -- ceph: - conf: - client: - debug ms: 1 - rgw gc obj min wait: 15 - rgw data log window: 30 - osd: - debug ms: 1 - debug objclass : 20 - client.0: - rgw region: region0 - rgw zone: r0z0 - rgw region root pool: .rgw.region.0 - rgw zone root pool: .rgw.zone.0 - rgw gc pool: .rgw.gc.0 - rgw user uid pool: .users.uid.0 - rgw user keys pool: .users.0 - rgw log data: True - rgw log meta: True - client.1: - rgw region: region0 - rgw zone: r0z1 - rgw region root pool: .rgw.region.0 - rgw zone root pool: .rgw.zone.1 - rgw gc pool: .rgw.gc.1 - rgw user uid pool: .users.uid.1 - rgw user keys pool: .users.1 - rgw log data: False - rgw log meta: False -- rgw: - realm: - realm0 - regions: - region0: - api name: api1 - is master: True - master zone: r0z0 - zones: [r0z0, r0z1] - client.0: - system user: - name: client0-system-user - access key: 0te6NH5mcdcq0Tc5i8i2 - secret key: Oy4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXv - client.1: - system user: - name: client1-system-user - access key: 1te6NH5mcdcq0Tc5i8i3 - secret key: Py4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXw -- radosgw-agent: - client.0: - max-entries: 10 - src: client.0 - dest: client.1 -- sleep: - duration: 30 -- radosgw-admin: diff --git a/ceph/qa/suites/rgw/singleton/all/radosgw-admin-multi-region.yaml b/ceph/qa/suites/rgw/singleton/all/radosgw-admin-multi-region.yaml deleted file mode 100644 index d28dec9e7..000000000 --- a/ceph/qa/suites/rgw/singleton/all/radosgw-admin-multi-region.yaml +++ /dev/null @@ -1,67 +0,0 @@ -roles: -- [mon.a, mgr.x, osd.0, osd.1, osd.2, client.0] -- [mon.b, mon.c, osd.3, osd.4, osd.5, client.1] -openstack: -- volumes: # attached to each instance - count: 3 - size: 10 # GB -tasks: -- install: -- ceph: - conf: - client: - debug ms: 1 - rgw gc obj min wait: 15 - osd: - debug ms: 1 - debug objclass : 20 - client.0: - rgw region: region0 - rgw zone: r0z1 - rgw region root pool: .rgw.region.0 - rgw zone root pool: .rgw.zone.0 - rgw gc pool: .rgw.gc.0 - rgw user uid pool: .users.uid.0 - rgw user keys pool: .users.0 - rgw log data: True - rgw log meta: True - client.1: - rgw region: region1 - rgw zone: r1z1 - rgw region root pool: .rgw.region.1 - rgw zone root pool: .rgw.zone.1 - rgw gc pool: .rgw.gc.1 - rgw user uid pool: .users.uid.1 - rgw user keys pool: .users.1 - rgw log data: False - rgw log meta: False -- rgw: - realm: - realm0 - regions: - region0: - api name: api1 - is master: True - master zone: r0z1 - zones: [r0z1] - region1: - api name: api1 - is master: False - master zone: r1z1 - zones: [r1z1] - client.0: - system user: - name: client0-system-user - access key: 0te6NH5mcdcq0Tc5i8i2 - secret key: Oy4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXv - client.1: - system user: - name: client1-system-user - access key: 1te6NH5mcdcq0Tc5i8i3 - secret key: Py4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXw -- radosgw-agent: - client.0: - src: client.0 - dest: client.1 - metadata-only: true -- radosgw-admin: diff --git a/ceph/qa/suites/rgw/singleton/all/radosgw-convert-to-region.yaml b/ceph/qa/suites/rgw/singleton/all/radosgw-convert-to-region.yaml deleted file mode 100644 index 8e81240e2..000000000 --- a/ceph/qa/suites/rgw/singleton/all/radosgw-convert-to-region.yaml +++ /dev/null @@ -1,81 +0,0 @@ -overrides: - s3readwrite: - s3: - user_id: s3readwrite-test-user - display_name: test user for the s3readwrite tests - email: tester@inktank - access_key: 2te6NH5mcdcq0Tc5i8i4 - secret_key: Qy4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXx - readwrite: - deterministic_file_names: True - duration: 30 - bucket: testbucket - files: - num: 10 - size: 2000 - stddev: 500 -roles: -- [mon.a, mgr.x, osd.0, osd.1, osd.2, client.0] -- [mon.b, mon.c, osd.3, osd.4, osd.5, client.1] -openstack: -- volumes: # attached to each instance - count: 3 - size: 10 # GB - -tasks: -- install: -- ceph: - conf: - client: - rgw region: default - rgw zone: r1z1 - rgw region root pool: .rgw - rgw zone root pool: .rgw - rgw domain root: .rgw - rgw gc pool: .rgw.gc - rgw user uid pool: .users.uid - rgw user keys pool: .users -- rgw: - realm: - realm0 - regions: - default: - api name: api1 - is master: true - master zone: r1z1 - zones: [r1z1] - client.0: - system user: - name: nr-system - access key: 0te6NH5mcdcq0Tc5i8i2 - secret key: Oy4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXv -- s3readwrite: - client.0: - extra_args: ['--no-cleanup'] - s3: - delete_user: False - readwrite: - writers: 1 - readers: 0 -- rgw: - realm: - realm0 - regions: - default: - api name: api1 - is master: true - master zone: r1z1 - zones: [r1z1] - client.1: - system user: - name: r2-system - access key: 1te6NH5mcdcq0Tc5i8i3 - secret key: Py4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXw -- s3readwrite: - client.1: - s3: - create_user: False - readwrite: - writers: 0 - readers: 2 - diff --git a/ceph/qa/suites/rgw/singleton/frontend/apache.yaml b/ceph/qa/suites/rgw/singleton/frontend/apache.yaml deleted file mode 100644 index 53ebf758e..000000000 --- a/ceph/qa/suites/rgw/singleton/frontend/apache.yaml +++ /dev/null @@ -1,3 +0,0 @@ -overrides: - rgw: - frontend: apache diff --git a/ceph/qa/suites/rgw/singleton/overrides.yaml b/ceph/qa/suites/rgw/singleton/overrides.yaml index bc1e82e9b..fc35b09f7 100644 --- a/ceph/qa/suites/rgw/singleton/overrides.yaml +++ b/ceph/qa/suites/rgw/singleton/overrides.yaml @@ -1,5 +1,6 @@ overrides: ceph: + wait-for-scrub: false conf: client: debug rgw: 20 diff --git a/ceph/qa/suites/rgw/thrash/workload/rgw_s3tests.yaml b/ceph/qa/suites/rgw/thrash/workload/rgw_s3tests.yaml index 9095e3823..45047ea41 100644 --- a/ceph/qa/suites/rgw/thrash/workload/rgw_s3tests.yaml +++ b/ceph/qa/suites/rgw/thrash/workload/rgw_s3tests.yaml @@ -8,3 +8,5 @@ overrides: conf: client: rgw lc debug interval: 10 + rgw crypt s3 kms encryption keys: testkey-1=YmluCmJvb3N0CmJvb3N0LWJ1aWxkCmNlcGguY29uZgo= testkey-2=aWIKTWFrZWZpbGUKbWFuCm91dApzcmMKVGVzdGluZwo= + rgw crypt require ssl: false diff --git a/ceph/qa/suites/rgw/verify/frontend/apache.yaml b/ceph/qa/suites/rgw/verify/frontend/apache.yaml deleted file mode 100644 index 53ebf758e..000000000 --- a/ceph/qa/suites/rgw/verify/frontend/apache.yaml +++ /dev/null @@ -1,3 +0,0 @@ -overrides: - rgw: - frontend: apache diff --git a/ceph/qa/suites/rgw/verify/overrides.yaml b/ceph/qa/suites/rgw/verify/overrides.yaml index 5611cbfe1..a9ffd29bb 100644 --- a/ceph/qa/suites/rgw/verify/overrides.yaml +++ b/ceph/qa/suites/rgw/verify/overrides.yaml @@ -3,8 +3,8 @@ overrides: conf: client: debug rgw: 20 - rgw compression type: random rgw crypt s3 kms encryption keys: testkey-1=YmluCmJvb3N0CmJvb3N0LWJ1aWxkCmNlcGguY29uZgo= testkey-2=aWIKTWFrZWZpbGUKbWFuCm91dApzcmMKVGVzdGluZwo= rgw crypt require ssl: false rgw: frontend: civetweb + compression type: random diff --git a/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests.yaml b/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests.yaml index 7f5345db0..6d3c1370b 100644 --- a/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests.yaml +++ b/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests.yaml @@ -2,7 +2,6 @@ os_type: centos # xenial valgrind buggy, see http://tracker.ceph.com/issues/18 tasks: - install: flavor: notcmalloc - debuginfo: true - ceph: - rgw: client.0: diff --git a/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests_multiregion.yaml b/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests_multiregion.yaml deleted file mode 100644 index d86b0bbb2..000000000 --- a/ceph/qa/suites/rgw/verify/tasks/rgw_s3tests_multiregion.yaml +++ /dev/null @@ -1,69 +0,0 @@ -os_type: centos # xenial valgrind buggy, see http://tracker.ceph.com/issues/18126 -tasks: -- install: - flavor: notcmalloc - debuginfo: true -- ceph: - conf: - client.0: - rgw region: zero - rgw zone: r0z1 - rgw region root pool: .rgw.region.0 - rgw zone root pool: .rgw.zone.0 - rgw gc pool: .rgw.gc.0 - rgw user uid pool: .users.uid.0 - rgw user keys pool: .users.0 - rgw log data: True - rgw log meta: True - client.1: - rgw region: one - rgw zone: r1z1 - rgw region root pool: .rgw.region.1 - rgw zone root pool: .rgw.zone.1 - rgw gc pool: .rgw.gc.1 - rgw user uid pool: .users.uid.1 - rgw user keys pool: .users.1 - rgw log data: False - rgw log meta: False -- rgw: - default_idle_timeout: 300 - realm: - realm0 - regions: - zero: - api name: api1 - is master: True - master zone: r0z1 - zones: [r0z1] - one: - api name: api1 - is master: False - master zone: r1z1 - zones: [r1z1] - client.0: - valgrind: [--tool=memcheck] - system user: - name: client0-system-user - access key: 1te6NH5mcdcq0Tc5i8i2 - secret key: 1y4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXv - client.1: - valgrind: [--tool=memcheck] - system user: - name: client1-system-user - access key: 0te6NH5mcdcq0Tc5i8i2 - secret key: Oy4IOauQoL18Gp2zM7lC1vLmoawgqcYPbYGcWfXv -- radosgw-agent: - client.0: - src: client.0 - dest: client.1 - metadata-only: true -- s3tests: - client.0: - force-branch: ceph-master - idle_timeout: 300 - rgw_server: client.0 -overrides: - ceph: - conf: - client: - rgw lc debug interval: 10 diff --git a/ceph/qa/suites/rgw/verify/tasks/rgw_swift.yaml b/ceph/qa/suites/rgw/verify/tasks/rgw_swift.yaml index 8abfdfdbd..6e6e9eee6 100644 --- a/ceph/qa/suites/rgw/verify/tasks/rgw_swift.yaml +++ b/ceph/qa/suites/rgw/verify/tasks/rgw_swift.yaml @@ -2,7 +2,6 @@ os_type: centos # xenial valgrind buggy, see http://tracker.ceph.com/issues/18 tasks: - install: flavor: notcmalloc - debuginfo: true - ceph: - rgw: client.0: diff --git a/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/1-hammer-jewel-install/hammer-jewel.yaml b/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/1-hammer-jewel-install/hammer-jewel.yaml index 01dc9fa6d..d743c89a5 100644 --- a/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/1-hammer-jewel-install/hammer-jewel.yaml +++ b/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/1-hammer-jewel-install/hammer-jewel.yaml @@ -5,6 +5,7 @@ tasks: - print: "**** done hammer" - ceph: fs: xfs + skip_mgr_daemons: true - install.upgrade: exclude_packages: ['ceph-mgr','libcephfs2','libcephfs-devel','libcephfs-dev'] osd.0: diff --git a/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-all.yaml b/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-all.yaml index ec1a88c76..1aaeac807 100644 --- a/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-all.yaml +++ b/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-all.yaml @@ -12,6 +12,7 @@ upgrade-sequence: - exec: mon.a: - sleep 300 # http://tracker.ceph.com/issues/17808 + - ceph osd set sortbitwise - ceph osd set require_jewel_osds - ceph.healthy: - print: "**** done ceph.healthy" diff --git a/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-osd-mds-mon.yaml b/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-osd-mds-mon.yaml index a185cd5cc..f2093da6e 100644 --- a/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-osd-mds-mon.yaml +++ b/ceph/qa/suites/upgrade/hammer-jewel-x/parallel/3-upgrade-sequence/upgrade-osd-mds-mon.yaml @@ -29,6 +29,7 @@ upgrade-sequence: - exec: osd.0: - sleep 300 # http://tracker.ceph.com/issues/17808 + - ceph osd set sortbitwise - ceph osd set require_jewel_osds - ceph.healthy: - sleep: diff --git a/ceph/qa/suites/upgrade/hammer-jewel-x/stress-split/1-hammer-install-and-upgrade-to-jewel/hammer-to-jewel.yaml b/ceph/qa/suites/upgrade/hammer-jewel-x/stress-split/1-hammer-install-and-upgrade-to-jewel/hammer-to-jewel.yaml index 0ed59c5e0..b69da11c5 100644 --- a/ceph/qa/suites/upgrade/hammer-jewel-x/stress-split/1-hammer-install-and-upgrade-to-jewel/hammer-to-jewel.yaml +++ b/ceph/qa/suites/upgrade/hammer-jewel-x/stress-split/1-hammer-install-and-upgrade-to-jewel/hammer-to-jewel.yaml @@ -9,6 +9,7 @@ tasks: - print: '**** done hammer' - ceph: fs: xfs + skip_mgr_daemons: true - install.upgrade: exclude_packages: - ceph-mgr @@ -38,14 +39,6 @@ tasks: - ceph osd set require_jewel_osds - for p in `ceph osd pool ls` ; do ceph osd pool set $p use_gmt_hitset true ; done -- install.upgrade: - client.0: - branch: jewel - exclude_packages: - - ceph-mgr - - libcephfs2 - - libcephfs-devel - - libcephfs-dev - print: '**** done install.upgrade client.0 to jewel' upgrade-sequence-h-j: sequential: diff --git a/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/1-install-hammer-and-upgrade-to-jewel/hammer-to-jewel.yaml b/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/1-install-hammer-and-upgrade-to-jewel/hammer-to-jewel.yaml index f04be6929..4c58e5f0d 100644 --- a/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/1-install-hammer-and-upgrade-to-jewel/hammer-to-jewel.yaml +++ b/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/1-install-hammer-and-upgrade-to-jewel/hammer-to-jewel.yaml @@ -9,3 +9,4 @@ tasks: - print: '**** done hammer' - ceph: fs: xfs + skip_mgr_daemons: true diff --git a/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/3-upgrade.yaml b/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/3-upgrade.yaml index c58c62c2b..3af3cfd72 100644 --- a/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/3-upgrade.yaml +++ b/ceph/qa/suites/upgrade/hammer-jewel-x/tiering/3-upgrade.yaml @@ -46,6 +46,7 @@ upgrade-sequence: - exec: mon.a: - sleep 300 # http://tracker.ceph.com/issues/17808 + - ceph osd set sortbitwise - ceph osd set require_jewel_osds - ceph.healthy: - print: "**** done ceph.healthy" diff --git a/ceph/qa/suites/upgrade/jewel-x/point-to-point-x/point-to-point-upgrade.yaml b/ceph/qa/suites/upgrade/jewel-x/point-to-point-x/point-to-point-upgrade.yaml index 736ba19e6..fd4a1d8f6 100644 --- a/ceph/qa/suites/upgrade/jewel-x/point-to-point-x/point-to-point-upgrade.yaml +++ b/ceph/qa/suites/upgrade/jewel-x/point-to-point-x/point-to-point-upgrade.yaml @@ -28,6 +28,7 @@ roles: - osd.0 - osd.1 - osd.2 + - mgr.x - - mon.b - mon.c - osd.3 @@ -47,6 +48,7 @@ tasks: - print: "**** done v10.2.0 install" - ceph: fs: xfs + skip_mgr_daemons: true - print: "**** done ceph xfs" - sequential: - workload @@ -207,4 +209,17 @@ upgrade-sequence_x: daemons: [osd.5] wait-for-healthy: false wait-for-up-osds: true + - exec: + mgr.x: + - mkdir -p /var/lib/ceph/mgr/ceph-x + - ceph auth get-or-create-key mgr.x mon 'allow profile mgr' + - ceph auth export mgr.x > /var/lib/ceph/mgr/ceph-x/keyring + - ceph.restart: + daemons: [mgr.x] + wait-for-healthy: false + - exec: + osd.0: + - ceph osd require-osd-release luminous + - ceph osd set-require-min-compat-client luminous + - ceph.healthy: - print: "**** done ceph.restart all -x branch mds/osd/mon" diff --git a/ceph/qa/suites/upgrade/jewel-x/stress-split/7-final-workload/rgw-swift.yaml b/ceph/qa/suites/upgrade/jewel-x/stress-split/7-final-workload/rgw-swift.yaml index a3bf03b1f..76e5d6fc2 100644 --- a/ceph/qa/suites/upgrade/jewel-x/stress-split/7-final-workload/rgw-swift.yaml +++ b/ceph/qa/suites/upgrade/jewel-x/stress-split/7-final-workload/rgw-swift.yaml @@ -4,7 +4,6 @@ meta: tasks: - rgw: client.0: - default_idle_timeout: 300 - print: "**** done rgw 9-workload" - swift: client.0: diff --git a/ceph/qa/suites/upgrade/kraken-x/parallel/0-cluster/start.yaml b/ceph/qa/suites/upgrade/kraken-x/parallel/0-cluster/start.yaml index eb5d185e5..e51ea8f8e 100644 --- a/ceph/qa/suites/upgrade/kraken-x/parallel/0-cluster/start.yaml +++ b/ceph/qa/suites/upgrade/kraken-x/parallel/0-cluster/start.yaml @@ -25,4 +25,6 @@ overrides: - ScrubResult - wrongly marked conf: + global: + enable experimental unrecoverable data corrupting features: "*" fs: xfs diff --git a/ceph/qa/suites/upgrade/kraken-x/stress-split/0-cluster/start.yaml b/ceph/qa/suites/upgrade/kraken-x/stress-split/0-cluster/start.yaml index 4f40219b5..dbb03ec82 100644 --- a/ceph/qa/suites/upgrade/kraken-x/stress-split/0-cluster/start.yaml +++ b/ceph/qa/suites/upgrade/kraken-x/stress-split/0-cluster/start.yaml @@ -6,6 +6,9 @@ meta: overrides: ceph: fs: xfs + conf: + global: + enable experimental unrecoverable data corrupting features: "*" roles: - - mon.a - mon.b diff --git a/ceph/qa/suites/upgrade/kraken-x/stress-split/7-final-workload/rgw-swift.yaml b/ceph/qa/suites/upgrade/kraken-x/stress-split/7-final-workload/rgw-swift.yaml index a3bf03b1f..76e5d6fc2 100644 --- a/ceph/qa/suites/upgrade/kraken-x/stress-split/7-final-workload/rgw-swift.yaml +++ b/ceph/qa/suites/upgrade/kraken-x/stress-split/7-final-workload/rgw-swift.yaml @@ -4,7 +4,6 @@ meta: tasks: - rgw: client.0: - default_idle_timeout: 300 - print: "**** done rgw 9-workload" - swift: client.0: diff --git a/ceph/qa/tasks/apache.conf.template b/ceph/qa/tasks/apache.conf.template deleted file mode 100644 index d164571f8..000000000 --- a/ceph/qa/tasks/apache.conf.template +++ /dev/null @@ -1,48 +0,0 @@ - - LoadModule version_module {mod_path}/mod_version.so - - - LoadModule env_module {mod_path}/mod_env.so - - - LoadModule rewrite_module {mod_path}/mod_rewrite.so - - - LoadModule log_config_module {mod_path}/mod_log_config.so - - -Listen {port} -ServerName {host} - -= 2.4> - - LoadModule unixd_module {mod_path}/mod_unixd.so - - - LoadModule authz_core_module {mod_path}/mod_authz_core.so - - - LoadModule mpm_worker_module {mod_path}/mod_mpm_worker.so - - User {user} - Group {group} - - -ServerRoot {testdir}/apache -ErrorLog {testdir}/archive/apache.{client}/error.log -LogFormat "%h l %u %t \"%r\" %>s %b \"{{Referer}}i\" \"%{{User-agent}}i\"" combined -CustomLog {testdir}/archive/apache.{client}/access.log combined -PidFile {testdir}/apache/tmp.{client}/apache.pid -DocumentRoot {testdir}/apache/htdocs.{client} - - - - Options +ExecCGI - AllowOverride All - SetHandler fastcgi-script - - -AllowEncodedSlashes On -ServerSignature Off -MaxRequestsPerChild 0 - diff --git a/ceph/qa/tasks/ceph.py b/ceph/qa/tasks/ceph.py index 181429b07..fa43530a6 100644 --- a/ceph/qa/tasks/ceph.py +++ b/ceph/qa/tasks/ceph.py @@ -1030,29 +1030,34 @@ def osd_scrub_pgs(ctx, config): indicate the last scrub completed. Time out if no progess is made here after two minutes. """ - retries = 12 + retries = 20 delays = 10 cluster_name = config['cluster'] manager = ctx.managers[cluster_name] all_clean = False for _ in range(0, retries): stats = manager.get_pg_stats() - states = [stat['state'] for stat in stats] - if len(set(states)) == 1 and states[0] == 'active+clean': + bad = [stat['pgid'] for stat in stats if 'active+clean' not in stat['state']] + if not bad: all_clean = True break - log.info("Waiting for all osds to be active and clean.") + log.info( + "Waiting for all osds to be active and clean, waiting on %s" % bad) time.sleep(delays) if not all_clean: - log.info("Scrubbing terminated -- not all pgs were active and clean.") - return + raise RuntimeError("Scrubbing terminated -- not all pgs were active and clean.") check_time_now = time.localtime() time.sleep(1) all_roles = teuthology.all_roles(ctx.cluster) for role in teuthology.cluster_roles_of_type(all_roles, 'osd', cluster_name): log.info("Scrubbing {osd}".format(osd=role)) _, _, id_ = teuthology.split_role(role) - manager.raw_cluster_cmd('osd', 'deep-scrub', id_) + # allow this to fail; in certain cases the OSD might not be up + # at this point. we will catch all pgs below. + try: + manager.raw_cluster_cmd('osd', 'deep-scrub', id_) + except run.CommandFailedError: + pass prev_good = 0 gap_cnt = 0 loop = True @@ -1073,9 +1078,15 @@ def osd_scrub_pgs(ctx, config): gap_cnt = 0 else: gap_cnt += 1 + if gap_cnt % 6 == 0: + for (pgid, tmval) in timez: + # re-request scrub every so often in case the earlier + # request was missed. do not do it everytime because + # the scrub may be in progress or not reported yet and + # we will starve progress. + manager.raw_cluster_cmd('pg', 'deep-scrub', pgid) if gap_cnt > retries: - log.info('Exiting scrub checking -- not all pgs scrubbed.') - return + raise RuntimeError('Exiting scrub checking -- not all pgs scrubbed.') if loop: log.info('Still waiting for all pgs to be scrubbed.') time.sleep(delays) diff --git a/ceph/qa/tasks/ceph_manager.py b/ceph/qa/tasks/ceph_manager.py index a40bd6c7b..465da73d2 100644 --- a/ceph/qa/tasks/ceph_manager.py +++ b/ceph/qa/tasks/ceph_manager.py @@ -183,14 +183,9 @@ class Thrasher: def _set_config(self, service_type, service_id, name, value): opt_arg = '--{name} {value}'.format(name=name, value=value) - try: - whom = '.'.join([service_type, service_id]) - self.ceph_manager.raw_cluster_cmd('--', 'tell', whom, - 'injectargs', opt_arg) - except Exception: - self.ceph_manager.raw_cluster_cmd('--', service_type, - 'tell', service_id, - 'injectargs', opt_arg) + whom = '.'.join([service_type, service_id]) + self.ceph_manager.raw_cluster_cmd('--', 'tell', whom, + 'injectargs', opt_arg) def cmd_exists_on_osds(self, cmd): @@ -612,6 +607,17 @@ class Thrasher: self.log("inning osd") self.in_osd() + def all_up_in(self): + """ + Make sure all osds are up and fully in. + """ + self.all_up(); + for osd in self.live_osds: + self.ceph_manager.raw_cluster_cmd('osd', 'reweight', + str(osd), str(1)) + self.ceph_manager.raw_cluster_cmd('osd', 'primary-affinity', + str(osd), str(1)) + def do_join(self): """ Break out of this Ceph loop @@ -983,7 +989,7 @@ class Thrasher: for service, opt, saved_value in self.saved_options: self._set_config(service, '*', opt, saved_value) self.saved_options = [] - self.all_up() + self.all_up_in() class ObjectStoreTool: @@ -1153,6 +1159,47 @@ class CephManager: "-w"], wait=False, stdout=StringIO(), stdin=run.PIPE) + def flush_pg_stats(self, osds, no_wait=None, wait_for_mon=3*5): + """ + Flush pg stats from a list of OSD ids, ensuring they are reflected + all the way to the monitor. Luminous and later only. + + :param osds: list of OSDs to flush + :param no_wait: list of OSDs not to wait for seq id. by default, we + wait for all specified osds, but some of them could be + moved out of osdmap, so we cannot get their updated + stat seq from monitor anymore. in that case, you need + to pass a blacklist. + :param wait_for_mon: wait for mon to be synced with mgr. 0 to disable + it. (3 * mon_mgr_digest_period, by default) + """ + seq = {osd: self.raw_cluster_cmd('tell', 'osd.%d' % osd, 'flush_pg_stats') + for osd in osds} + if not wait_for_mon: + return + if no_wait is None: + no_wait = [] + for osd, need in seq.iteritems(): + if osd in no_wait: + continue + got = 0 + while wait_for_mon > 0: + got = self.raw_cluster_cmd('osd', 'last-stat-seq', 'osd.%d' % osd) + self.log('need seq {need} got {got} for osd.{osd}'.format( + need=need, got=got, osd=osd)) + if got >= need: + break + A_WHILE = 1 + time.sleep(A_WHILE) + wait_for_mon -= A_WHILE + else: + raise Exception('timed out waiting for mon to be updated with ' + 'osd.{osd}: {got} < {need}'. + format(osd=osd, got=got, need=need)) + + def flush_all_pg_stats(self): + self.flush_pg_stats(range(len(self.get_osd_dump()))) + def do_rados(self, remote, cmd, check_status=True): """ Execute a remote rados command. @@ -2273,6 +2320,20 @@ class CephManager: self.make_admin_daemon_dir(remote) self.ctx.daemons.get_daemon('mon', mon, self.cluster).restart() + def revive_mgr(self, mgr): + """ + Restart by either power cycling (if the config says so), + or by doing a normal restart. + """ + if self.config.get('powercycle'): + remote = self.find_remote('mgr', mgr) + self.log('revive_mgr on mgr.{m} doing powercycle of {s}'. + format(m=mgr, s=remote.name)) + self._assert_ipmi(remote) + remote.console.power_on() + self.make_admin_daemon_dir(remote) + self.ctx.daemons.get_daemon('mgr', mgr, self.cluster).restart() + def get_mon_status(self, mon): """ Extract all the monitor status information from the cluster diff --git a/ceph/qa/tasks/cephfs/cephfs_test_case.py b/ceph/qa/tasks/cephfs/cephfs_test_case.py index ce21fab0d..72e8e9f03 100644 --- a/ceph/qa/tasks/cephfs/cephfs_test_case.py +++ b/ceph/qa/tasks/cephfs/cephfs_test_case.py @@ -102,6 +102,7 @@ class CephFSTestCase(CephTestCase): # To avoid any issues with e.g. unlink bugs, we destroy and recreate # the filesystem rather than just doing a rm -rf of files self.mds_cluster.mds_stop() + self.mds_cluster.mds_fail() self.mds_cluster.delete_all_filesystems() self.fs = None # is now invalid! @@ -193,8 +194,10 @@ class CephFSTestCase(CephTestCase): if ls_data is None: ls_data = self.fs.mds_asok(['session', 'ls'], mds_id=mds_id) - self.assertEqual(expected, len(ls_data), "Expected {0} sessions, found {1}".format( - expected, len(ls_data) + alive_count = len([s for s in ls_data if s['state'] != 'killing']) + + self.assertEqual(expected, alive_count, "Expected {0} sessions, found {1}".format( + expected, alive_count )) def assert_session_state(self, client_id, expected_state): diff --git a/ceph/qa/tasks/cephfs/filesystem.py b/ceph/qa/tasks/cephfs/filesystem.py index 8efd05e9e..01e1ca588 100644 --- a/ceph/qa/tasks/cephfs/filesystem.py +++ b/ceph/qa/tasks/cephfs/filesystem.py @@ -457,7 +457,14 @@ class Filesystem(MDSCluster): self.mon_manager.raw_cluster_cmd('fs', 'new', self.name, self.metadata_pool_name, data_pool_name) # Turn off spurious standby count warnings from modifying max_mds in tests. - self.mon_manager.raw_cluster_cmd('fs', 'set', self.name, 'standby_count_wanted', '0') + try: + self.mon_manager.raw_cluster_cmd('fs', 'set', self.name, 'standby_count_wanted', '0') + except CommandFailedError as e: + if e.exitstatus == 22: + # standby_count_wanted not available prior to luminous (upgrade tests would fail otherwise) + pass + else: + raise self.getinfo(refresh = True) diff --git a/ceph/qa/tasks/cephfs/mount.py b/ceph/qa/tasks/cephfs/mount.py index 5bef25ca6..4f96e6cdc 100644 --- a/ceph/qa/tasks/cephfs/mount.py +++ b/ceph/qa/tasks/cephfs/mount.py @@ -230,11 +230,31 @@ class CephFSMount(object): pyscript = dedent(script_builder).format(path=path) - log.info("lock file {0}".format(basename)) + log.info("lock_background file {0}".format(basename)) rproc = self._run_python(pyscript) self.background_procs.append(rproc) return rproc + def lock_and_release(self, basename="background_file"): + assert(self.is_mounted()) + + path = os.path.join(self.mountpoint, basename) + + script = """ + import time + import fcntl + import struct + f1 = open("{path}-1", 'w') + fcntl.flock(f1, fcntl.LOCK_EX) + f2 = open("{path}-2", 'w') + lockdata = struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0) + fcntl.fcntl(f2, fcntl.F_SETLK, lockdata) + """ + pyscript = dedent(script).format(path=path) + + log.info("lock_and_release file {0}".format(basename)) + return self._run_python(pyscript) + def check_filelock(self, basename="background_file", do_flock=True): assert(self.is_mounted()) @@ -436,36 +456,6 @@ class CephFSMount(object): self._kill_background(p) self.background_procs.remove(p) - def spam_dir_background(self, path): - """ - Create directory `path` and do lots of metadata operations - in it until further notice. - """ - assert(self.is_mounted()) - abs_path = os.path.join(self.mountpoint, path) - - pyscript = dedent(""" - import sys - import time - import os - - abs_path = "{abs_path}" - - if not os.path.exists(abs_path): - os.makedirs(abs_path) - - n = 0 - while True: - file_path = os.path.join(abs_path, "tmp%d" % n) - f = open(file_path, 'w') - f.close() - n = n + 1 - """).format(abs_path=abs_path) - - rproc = self._run_python(pyscript) - self.background_procs.append(rproc) - return rproc - def get_global_id(self): raise NotImplementedError() diff --git a/ceph/qa/tasks/cephfs/test_client_recovery.py b/ceph/qa/tasks/cephfs/test_client_recovery.py index 4b4085a91..4940ab89b 100644 --- a/ceph/qa/tasks/cephfs/test_client_recovery.py +++ b/ceph/qa/tasks/cephfs/test_client_recovery.py @@ -315,7 +315,7 @@ class TestClientRecovery(CephFSTestCase): self.mount_a.run_shell(["touch", "f{0}".format(i)]) # Populate mount_b's cache - self.mount_b.run_shell(["ls"]) + self.mount_b.run_shell(["ls", "-l"]) client_id = self.mount_b.get_global_id() num_caps = self._session_num_caps(client_id) @@ -331,10 +331,7 @@ class TestClientRecovery(CephFSTestCase): count, num_caps )) - def test_filelock(self): - """ - Check that file lock doesn't get lost after an MDS restart - """ + def _is_flockable(self): a_version_str = get_package_version(self.mount_a.client_remote, "fuse") b_version_str = get_package_version(self.mount_b.client_remote, "fuse") flock_version_str = "2.9" @@ -348,14 +345,20 @@ class TestClientRecovery(CephFSTestCase): b_version = version.StrictVersion(b_result.group()) flock_version=version.StrictVersion(flock_version_str) - flockable = False if (a_version >= flock_version and b_version >= flock_version): - log.info("testing flock locks") - flockable = True + log.info("flock locks are available") + return True else: log.info("not testing flock locks, machines have versions {av} and {bv}".format( av=a_version_str,bv=b_version_str)) + return False + + def test_filelock(self): + """ + Check that file lock doesn't get lost after an MDS restart + """ + flockable = self._is_flockable() lock_holder = self.mount_a.lock_background(do_flock=flockable) self.mount_b.wait_for_visible("background_file-2") @@ -374,6 +377,33 @@ class TestClientRecovery(CephFSTestCase): # We killed it, so it raises an error pass + def test_filelock_eviction(self): + """ + Check that file lock held by evicted client is given to + waiting client. + """ + if not self._is_flockable(): + self.skipTest("flock is not available") + + lock_holder = self.mount_a.lock_background() + self.mount_b.wait_for_visible("background_file-2") + self.mount_b.check_filelock() + + lock_taker = self.mount_b.lock_and_release() + # Check the taker is waiting (doesn't get it immediately) + time.sleep(2) + self.assertFalse(lock_holder.finished) + self.assertFalse(lock_taker.finished) + + mount_a_client_id = self.mount_a.get_global_id() + self.fs.mds_asok(['session', 'evict', "%s" % mount_a_client_id]) + + # Evicting mount_a should let mount_b's attepmt to take the lock + # suceed + self.wait_until_true( + lambda: lock_taker.finished, + timeout=10) + def test_dir_fsync(self): self._test_fsync(True); diff --git a/ceph/qa/tasks/cephfs/test_exports.py b/ceph/qa/tasks/cephfs/test_exports.py index 7cbf464a9..80f876ebc 100644 --- a/ceph/qa/tasks/cephfs/test_exports.py +++ b/ceph/qa/tasks/cephfs/test_exports.py @@ -6,6 +6,8 @@ from tasks.cephfs.cephfs_test_case import CephFSTestCase log = logging.getLogger(__name__) class TestExports(CephFSTestCase): + MDSS_REQUIRED = 2 + def _wait_subtrees(self, status, rank, test): timeout = 30 pause = 2 @@ -13,9 +15,8 @@ class TestExports(CephFSTestCase): for i in range(timeout/pause): subtrees = self.fs.mds_asok(["get", "subtrees"], mds_id=status.get_rank(self.fs.id, rank)['name']) subtrees = filter(lambda s: s['dir']['path'].startswith('/'), subtrees) - log.info(subtrees) filtered = sorted([(s['dir']['path'], s['auth_first']) for s in subtrees]) - log.info(filtered) + log.info("%s =?= %s", filtered, test) if filtered == test: return subtrees time.sleep(pause) @@ -31,15 +32,15 @@ class TestExports(CephFSTestCase): self._wait_subtrees(status, 0, []) # NOP - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "-1", "1"]) + self.mount_a.setfattr("1", "ceph.dir.pin", "-1") self._wait_subtrees(status, 0, []) # NOP (rank < -1) - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "-2341", "1"]) + self.mount_a.setfattr("1", "ceph.dir.pin", "-2341") self._wait_subtrees(status, 0, []) # pin /1 to rank 1 - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "1", "1"]) + self.mount_a.setfattr("1", "ceph.dir.pin", "1") self._wait_subtrees(status, 1, [('/1', 1)]) # Check export_targets is set properly @@ -49,34 +50,34 @@ class TestExports(CephFSTestCase): self.assertTrue(sorted(r0['export_targets']) == [1]) # redundant pin /1/2 to rank 1 - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "1", "1/2"]) + self.mount_a.setfattr("1/2", "ceph.dir.pin", "1") self._wait_subtrees(status, 1, [('/1', 1), ('/1/2', 1)]) # change pin /1/2 to rank 0 - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "0", "1/2"]) + self.mount_a.setfattr("1/2", "ceph.dir.pin", "0") self._wait_subtrees(status, 1, [('/1', 1), ('/1/2', 0)]) self._wait_subtrees(status, 0, [('/1', 1), ('/1/2', 0)]) # change pin /1/2/3 to (presently) non-existent rank 2 - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "2", "1/2/3"]) + self.mount_a.setfattr("1/2/3", "ceph.dir.pin", "2") self._wait_subtrees(status, 0, [('/1', 1), ('/1/2', 0)]) self._wait_subtrees(status, 1, [('/1', 1), ('/1/2', 0)]) # change pin /1/2 back to rank 1 - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "1", "1/2"]) + self.mount_a.setfattr("1/2", "ceph.dir.pin", "1") self._wait_subtrees(status, 1, [('/1', 1), ('/1/2', 1)]) # add another directory pinned to 1 self.mount_a.run_shell(["mkdir", "-p", "1/4/5"]) - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "1", "1/4/5"]) + self.mount_a.setfattr("1/4/5", "ceph.dir.pin", "1") self._wait_subtrees(status, 1, [('/1', 1), ('/1/2', 1), ('/1/4/5', 1)]) # change pin /1 to 0 - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "0", "1"]) + self.mount_a.setfattr("1", "ceph.dir.pin", "0") self._wait_subtrees(status, 0, [('/1', 0), ('/1/2', 1), ('/1/4/5', 1)]) # change pin /1/2 to default (-1); does the subtree root properly respect it's parent pin? - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "-1", "1/2"]) + self.mount_a.setfattr("1/2", "ceph.dir.pin", "-1") self._wait_subtrees(status, 0, [('/1', 0), ('/1/4/5', 1)]) if len(list(status.get_standbys())): @@ -96,8 +97,8 @@ class TestExports(CephFSTestCase): # Test rename self.mount_a.run_shell(["mkdir", "-p", "a/b", "aa/bb"]) - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "1", "a"]) - self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "0", "aa/bb"]) + self.mount_a.setfattr("a", "ceph.dir.pin", "1") + self.mount_a.setfattr("aa/bb", "ceph.dir.pin", "0") self._wait_subtrees(status, 0, [('/1', 0), ('/1/4/5', 1), ('/1/2/3', 2), ('/a', 1), ('/aa/bb', 0)]) self.mount_a.run_shell(["mv", "aa", "a/b/"]) self._wait_subtrees(status, 0, [('/1', 0), ('/1/4/5', 1), ('/1/2/3', 2), ('/a', 1), ('/a/b/aa/bb', 0)]) diff --git a/ceph/qa/tasks/cephfs/test_fragment.py b/ceph/qa/tasks/cephfs/test_fragment.py index 81b7ec630..f2486a063 100644 --- a/ceph/qa/tasks/cephfs/test_fragment.py +++ b/ceph/qa/tasks/cephfs/test_fragment.py @@ -99,7 +99,7 @@ class TestFragmentation(CephFSTestCase): mds_bal_split_size=split_size, mds_bal_merge_size=merge_size, mds_bal_split_bits=3, - mds_bal_fragment_size_max=(split_size * 1.5 + 2) + mds_bal_fragment_size_max=int(split_size * 1.5 + 2) ) # We test this only at a single split level. If a client was sending diff --git a/ceph/qa/tasks/cephfs/test_journal_migration.py b/ceph/qa/tasks/cephfs/test_journal_migration.py index 873603f7a..64fe93980 100644 --- a/ceph/qa/tasks/cephfs/test_journal_migration.py +++ b/ceph/qa/tasks/cephfs/test_journal_migration.py @@ -9,19 +9,41 @@ JOURNAL_FORMAT_RESILIENT = 1 class TestJournalMigration(CephFSTestCase): CLIENTS_REQUIRED = 1 + MDSS_REQUIRED = 2 def test_journal_migration(self): old_journal_version = JOURNAL_FORMAT_LEGACY new_journal_version = JOURNAL_FORMAT_RESILIENT - self.fs.set_ceph_conf('mds', 'mds journal format', old_journal_version) + # Pick out two daemons to use + mds_a, mds_b = sorted(self.mds_cluster.mds_ids[0:2]) - # Create a filesystem using the older journal format. self.mount_a.umount_wait() self.fs.mds_stop() + + # Enable standby replay, to cover the bug case #8811 where + # a standby replay might mistakenly end up trying to rewrite + # the journal at the same time as an active daemon. + self.fs.set_ceph_conf('mds', 'mds standby replay', "true") + self.fs.set_ceph_conf('mds', 'mds standby for rank', "0") + + # Create a filesystem using the older journal format. + self.fs.set_ceph_conf('mds', 'mds journal format', old_journal_version) self.fs.recreate() - self.fs.mds_restart() + self.fs.mds_restart(mds_id=mds_a) self.fs.wait_for_daemons() + self.assertEqual(self.fs.get_active_names(), [mds_a]) + + def replay_names(): + return [s['name'] + for s in self.fs.status().get_replays(fscid = self.fs.id)] + + # Start the standby and wait for it to come up + self.fs.mds_restart(mds_id=mds_b) + self.wait_until_equal( + replay_names, + [mds_b], + timeout = 30) # Do some client work so that the log is populated with something. with self.mount_a.mounted(): @@ -41,8 +63,8 @@ class TestJournalMigration(CephFSTestCase): self.fs.set_ceph_conf('mds', 'mds journal format', new_journal_version) # Restart the MDS. - self.fs.mds_fail_restart() - self.fs.wait_for_daemons() + self.fs.mds_fail_restart(mds_id=mds_a) + self.fs.mds_fail_restart(mds_id=mds_b) # This ensures that all daemons come up into a valid state self.fs.wait_for_daemons() @@ -79,7 +101,7 @@ class TestJournalMigration(CephFSTestCase): # Approximate value of "lots", expected from having run fsstress raise RuntimeError("Unexpectedly few journal events: {0}".format(event_count)) - # Do some client work so that the log is populated with something. + # Do some client work to check that writing the log is still working with self.mount_a.mounted(): workunit(self.ctx, { 'clients': { @@ -87,3 +109,10 @@ class TestJournalMigration(CephFSTestCase): }, "timeout": "3h" }) + + # Check that both an active and a standby replay are still up + self.assertEqual(len(replay_names()), 1) + self.assertEqual(len(self.fs.get_active_names()), 1) + self.assertTrue(self.mds_cluster.mds_daemons[mds_a].running()) + self.assertTrue(self.mds_cluster.mds_daemons[mds_b].running()) + diff --git a/ceph/qa/tasks/cephfs/test_journal_repair.py b/ceph/qa/tasks/cephfs/test_journal_repair.py index 8496b144e..1b03afc0f 100644 --- a/ceph/qa/tasks/cephfs/test_journal_repair.py +++ b/ceph/qa/tasks/cephfs/test_journal_repair.py @@ -173,26 +173,33 @@ class TestJournalRepair(CephFSTestCase): self.mds_cluster.mds_stop(unneeded_mds) self.mds_cluster.mds_fail(unneeded_mds) - # Do a bunch of I/O such that at least some will hit the second MDS: create - # lots of directories so that the balancer should find it easy to make a decision - # to allocate some of them to the second mds. - spammers = [] - for n in range(0, 16): - dir_name = "spam_{0}".format(n) - spammers.append(self.mount_a.spam_dir_background(dir_name)) + # Create a dir on each rank + self.mount_a.run_shell(["mkdir", "alpha"]) + self.mount_a.run_shell(["mkdir", "bravo"]) + self.mount_a.setfattr("alpha/", "ceph.dir.pin", "0") + self.mount_a.setfattr("bravo/", "ceph.dir.pin", "1") def subtrees_assigned(): got_subtrees = self.fs.mds_asok(["get", "subtrees"], mds_id=active_mds_names[0]) - rank_1_count = len([s for s in got_subtrees if s['auth_first'] == 1]) - # Greater than 1, because there is typically 1 for ~mds1, and once it - # has been assigned something in addition to that it means it has been - # assigned a "real" subtree. - return rank_1_count > 1 + for s in got_subtrees: + if s['dir']['path'] == '/bravo': + if s['auth_first'] == 1: + return True + else: + # Should not happen + raise RuntimeError("/bravo is subtree but not rank 1!") - # We are waiting for the MDS to respond to hot directories, which - # is not guaranteed to happen at a particular time, so a lengthy timeout here. - self.wait_until_true(subtrees_assigned, 600) + return False + + # Ensure the pinning has taken effect and the /bravo dir is now + # migrated to rank 1. + self.wait_until_true(subtrees_assigned, 30) + + # Do some IO (this should be split across ranks according to + # the rank-pinned dirs) + self.mount_a.create_n_files("alpha/file", 1000) + self.mount_a.create_n_files("bravo/file", 1000) # Flush the journals so that we have some backing store data # belonging to one MDS, and some to the other MDS. @@ -229,16 +236,6 @@ class TestJournalRepair(CephFSTestCase): # killing the mount also means killing the node. pass - log.info("Terminating spammer processes...") - for spammer_proc in spammers: - spammer_proc.stdin.close() - try: - spammer_proc.wait() - except (CommandFailedError, ConnectionLostError): - # The ConnectionLostError case is for kernel client, where - # killing the mount also means killing the node. - pass - # See that the second MDS will crash when it starts and tries to # acquire rank 1 damaged_id = active_mds_names[1] diff --git a/ceph/qa/tasks/cephfs/test_misc.py b/ceph/qa/tasks/cephfs/test_misc.py index a48e0a2a6..beb3ab844 100644 --- a/ceph/qa/tasks/cephfs/test_misc.py +++ b/ceph/qa/tasks/cephfs/test_misc.py @@ -6,6 +6,7 @@ from teuthology.orchestra.run import CommandFailedError import errno import time + class TestMisc(CephFSTestCase): CLIENTS_REQUIRED = 2 @@ -101,12 +102,12 @@ class TestMisc(CephFSTestCase): only session """ - self.mount_b.umount_wait(); + self.mount_b.umount_wait() ls_data = self.fs.mds_asok(['session', 'ls']) self.assert_session_count(1, ls_data) - self.mount_a.kill(); - self.mount_a.kill_cleanup(); + self.mount_a.kill() + self.mount_a.kill_cleanup() time.sleep(self.mds_session_autoclose * 1.5) ls_data = self.fs.mds_asok(['session', 'ls']) diff --git a/ceph/qa/tasks/cephfs/test_strays.py b/ceph/qa/tasks/cephfs/test_strays.py index a38f2b820..3335d89dd 100644 --- a/ceph/qa/tasks/cephfs/test_strays.py +++ b/ceph/qa/tasks/cephfs/test_strays.py @@ -347,12 +347,14 @@ class TestStrays(CephFSTestCase): """ # Write some bytes to file_a size_mb = 8 - self.mount_a.write_n_mb("file_a", size_mb) - ino = self.mount_a.path_to_ino("file_a") + self.mount_a.run_shell(["mkdir", "dir_1"]) + self.mount_a.write_n_mb("dir_1/file_a", size_mb) + ino = self.mount_a.path_to_ino("dir_1/file_a") # Create a hardlink named file_b - self.mount_a.run_shell(["ln", "file_a", "file_b"]) - self.assertEqual(self.mount_a.path_to_ino("file_b"), ino) + self.mount_a.run_shell(["mkdir", "dir_2"]) + self.mount_a.run_shell(["ln", "dir_1/file_a", "dir_2/file_b"]) + self.assertEqual(self.mount_a.path_to_ino("dir_2/file_b"), ino) # Flush journal self.fs.mds_asok(['flush', 'journal']) @@ -361,8 +363,15 @@ class TestStrays(CephFSTestCase): pre_unlink_bt = self.fs.read_backtrace(ino) self.assertEqual(pre_unlink_bt['ancestors'][0]['dname'], "file_a") + # empty mds cache. otherwise mds reintegrates stray when unlink finishes + self.mount_a.umount_wait() + self.fs.mds_asok(['flush', 'journal']) + self.fs.mds_fail_restart() + self.fs.wait_for_daemons() + self.mount_a.mount() + # Unlink file_a - self.mount_a.run_shell(["rm", "-f", "file_a"]) + self.mount_a.run_shell(["rm", "-f", "dir_1/file_a"]) # See that a stray was created self.assertEqual(self.get_mdc_stat("num_strays"), 1) @@ -378,14 +387,24 @@ class TestStrays(CephFSTestCase): self.fs.mds_asok(['flush', 'journal']) self.assertTrue(self.get_backtrace_path(ino).startswith("stray")) + last_reintegrated = self.get_mdc_stat("strays_reintegrated") + # Do a metadata operation on the remaining link (mv is heavy handed, but # others like touch may be satisfied from caps without poking MDS) - self.mount_a.run_shell(["mv", "file_b", "file_c"]) + self.mount_a.run_shell(["mv", "dir_2/file_b", "dir_2/file_c"]) + + # Stray reintegration should happen as a result of the eval_remote call + # on responding to a client request. + self.wait_until_equal( + lambda: self.get_mdc_stat("num_strays"), + expect_val=0, + timeout=60 + ) # See the reintegration counter increment - # This should happen as a result of the eval_remote call on - # responding to a client request. - self._wait_for_counter("mds_cache", "strays_reintegrated", 1) + curr_reintegrated = self.get_mdc_stat("strays_reintegrated") + self.assertGreater(curr_reintegrated, last_reintegrated) + last_reintegrated = curr_reintegrated # Flush the journal self.fs.mds_asok(['flush', 'journal']) @@ -394,22 +413,41 @@ class TestStrays(CephFSTestCase): post_reint_bt = self.fs.read_backtrace(ino) self.assertEqual(post_reint_bt['ancestors'][0]['dname'], "file_c") - # See that the number of strays in existence is zero - self.assertEqual(self.get_mdc_stat("num_strays"), 0) + # mds should reintegrates stray when unlink finishes + self.mount_a.run_shell(["ln", "dir_2/file_c", "dir_2/file_d"]) + self.mount_a.run_shell(["rm", "-f", "dir_2/file_c"]) + + # Stray reintegration should happen as a result of the notify_stray call + # on completion of unlink + self.wait_until_equal( + lambda: self.get_mdc_stat("num_strays"), + expect_val=0, + timeout=60 + ) + + # See the reintegration counter increment + curr_reintegrated = self.get_mdc_stat("strays_reintegrated") + self.assertGreater(curr_reintegrated, last_reintegrated) + last_reintegrated = curr_reintegrated + + # Flush the journal + self.fs.mds_asok(['flush', 'journal']) + + # See that the backtrace for the file points to the newest link's path + post_reint_bt = self.fs.read_backtrace(ino) + self.assertEqual(post_reint_bt['ancestors'][0]['dname'], "file_d") # Now really delete it - self.mount_a.run_shell(["rm", "-f", "file_c"]) + self.mount_a.run_shell(["rm", "-f", "dir_2/file_d"]) self._wait_for_counter("mds_cache", "strays_enqueued", 1) self._wait_for_counter("purge_queue", "pq_executed", 1) self.assert_purge_idle() self.assertTrue(self.fs.data_objects_absent(ino, size_mb * 1024 * 1024)) - # We caused the inode to go stray twice - self.assertEqual(self.get_mdc_stat("strays_created"), 2) - # One time we reintegrated it - self.assertEqual(self.get_mdc_stat("strays_reintegrated"), 1) - # Then the second time we purged it + # We caused the inode to go stray 3 times + self.assertEqual(self.get_mdc_stat("strays_created"), 3) + # We purged it at the last self.assertEqual(self.get_mdc_stat("strays_enqueued"), 1) def test_mv_hardlink_cleanup(self): @@ -432,27 +470,25 @@ class TestStrays(CephFSTestCase): # mv file_a file_b self.mount_a.run_shell(["mv", "file_a", "file_b"]) - self.fs.mds_asok(['flush', 'journal']) + # Stray reintegration should happen as a result of the notify_stray call on + # completion of rename + self.wait_until_equal( + lambda: self.get_mdc_stat("num_strays"), + expect_val=0, + timeout=60 + ) - # Initially, linkto_b will still be a remote inode pointing to a newly created - # stray from when file_b was unlinked due to the 'mv'. No data objects should - # have been deleted, as both files still have linkage. - self.assertEqual(self.get_mdc_stat("num_strays"), 1) self.assertEqual(self.get_mdc_stat("strays_created"), 1) - self.assertTrue(self.get_backtrace_path(file_b_ino).startswith("stray")) + self.assertGreaterEqual(self.get_mdc_stat("strays_reintegrated"), 1) + + # No data objects should have been deleted, as both files still have linkage. self.assertTrue(self.fs.data_objects_present(file_a_ino, size_mb * 1024 * 1024)) self.assertTrue(self.fs.data_objects_present(file_b_ino, size_mb * 1024 * 1024)) - # Trigger reintegration and wait for it to happen - self.assertEqual(self.get_mdc_stat("strays_reintegrated"), 0) - self.mount_a.run_shell(["mv", "linkto_b", "file_c"]) - self._wait_for_counter("mds_cache", "strays_reintegrated", 1) - self.fs.mds_asok(['flush', 'journal']) post_reint_bt = self.fs.read_backtrace(file_b_ino) - self.assertEqual(post_reint_bt['ancestors'][0]['dname'], "file_c") - self.assertEqual(self.get_mdc_stat("num_strays"), 0) + self.assertEqual(post_reint_bt['ancestors'][0]['dname'], "linkto_b") def _setup_two_ranks(self): # Set up two MDSs @@ -477,16 +513,14 @@ class TestStrays(CephFSTestCase): return rank_0_id, rank_1_id - def _force_migrate(self, from_id, to_id, path, watch_ino): + def _force_migrate(self, to_id, path, watch_ino): """ - :param from_id: MDS id currently containing metadata :param to_id: MDS id to move it to :param path: Filesystem path (string) to move :param watch_ino: Inode number to look for at destination to confirm move :return: None """ - result = self.fs.mds_asok(["export", "dir", path, "1"], from_id) - self.assertEqual(result["return_code"], 0) + self.mount_a.run_shell(["setfattr", "-n", "ceph.dir.pin", "-v", "1", path]) # Poll the MDS cache dump to watch for the export completing migrated = False @@ -527,7 +561,7 @@ class TestStrays(CephFSTestCase): self.mount_a.create_n_files("delete_me/file", file_count) - self._force_migrate(rank_0_id, rank_1_id, "/delete_me", + self._force_migrate(rank_1_id, "delete_me", self.mount_a.path_to_ino("delete_me/file_0")) self.mount_a.run_shell(["rm", "-rf", Raw("delete_me/*")]) @@ -576,14 +610,27 @@ class TestStrays(CephFSTestCase): # Create a non-purgeable stray in a ~mds1 stray directory # by doing a hard link and deleting the original file - self.mount_a.run_shell(["mkdir", "mydir"]) - self.mount_a.run_shell(["touch", "mydir/original"]) - self.mount_a.run_shell(["ln", "mydir/original", "mydir/linkto"]) + self.mount_a.run_shell(["mkdir", "dir_1", "dir_2"]) + self.mount_a.run_shell(["touch", "dir_1/original"]) + self.mount_a.run_shell(["ln", "dir_1/original", "dir_2/linkto"]) + + self._force_migrate(rank_1_id, "dir_1", + self.mount_a.path_to_ino("dir_1/original")) + + # empty mds cache. otherwise mds reintegrates stray when unlink finishes + self.mount_a.umount_wait() + self.fs.mds_asok(['flush', 'journal'], rank_0_id) + self.fs.mds_asok(['flush', 'journal'], rank_1_id) + self.fs.mds_fail_restart() + self.fs.wait_for_daemons() - self._force_migrate(rank_0_id, rank_1_id, "/mydir", - self.mount_a.path_to_ino("mydir/original")) + active_mds_names = self.fs.get_active_names() + rank_0_id = active_mds_names[0] + rank_1_id = active_mds_names[1] + + self.mount_a.mount() - self.mount_a.run_shell(["rm", "-f", "mydir/original"]) + self.mount_a.run_shell(["rm", "-f", "dir_1/original"]) self.mount_a.umount_wait() self._wait_for_counter("mds_cache", "strays_created", 1, @@ -910,6 +957,7 @@ class TestStrays(CephFSTestCase): max_purge_files = 2 + self.set_conf('mds', 'mds_bal_frag', 'false') self.set_conf('mds', 'mds_max_purge_files', "%d" % max_purge_files) self.fs.mds_fail_restart() self.fs.wait_for_daemons() diff --git a/ceph/qa/tasks/cephfs/test_volume_client.py b/ceph/qa/tasks/cephfs/test_volume_client.py index f67b7f941..3c639bbfc 100644 --- a/ceph/qa/tasks/cephfs/test_volume_client.py +++ b/ceph/qa/tasks/cephfs/test_volume_client.py @@ -11,10 +11,6 @@ log = logging.getLogger(__name__) class TestVolumeClient(CephFSTestCase): - # - # TODO: Test that VolumeClient can recover from partial auth updates. - # - # One for looking at the global filesystem, one for being # the VolumeClient, two for mounting the created shares CLIENTS_REQUIRED = 4 @@ -494,12 +490,17 @@ vc.disconnect() ))) # Evicted guest client, guest_mounts[0], should not be able to do - # anymore metadata ops. It behaves as if it has lost network - # connection. - background = guest_mounts[0].write_n_mb("rogue.bin", 1, wait=False) - # Approximate check for 'stuck' as 'still running after 10s'. - time.sleep(10) - self.assertFalse(background.finished) + # anymore metadata ops. It should start failing all operations + # when it sees that its own address is in the blacklist. + try: + guest_mounts[0].write_n_mb("rogue.bin", 1) + except CommandFailedError: + pass + else: + raise RuntimeError("post-eviction write should have failed!") + + # The blacklisted guest client should now be unmountable + guest_mounts[0].umount_wait() # Guest client, guest_mounts[1], using the same auth ID 'guest', but # has mounted the other volume, should be able to use its volume @@ -519,8 +520,6 @@ vc.disconnect() guest_entity=guest_entity ))) - # We must hard-umount the one that we evicted - guest_mounts[0].umount_wait(force=True) def test_purge(self): """ diff --git a/ceph/qa/tasks/divergent_priors.py b/ceph/qa/tasks/divergent_priors.py index 6ee376d0a..12ea93365 100644 --- a/ceph/qa/tasks/divergent_priors.py +++ b/ceph/qa/tasks/divergent_priors.py @@ -33,9 +33,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.raw_cluster_cmd('osd', 'set', 'noout') manager.raw_cluster_cmd('osd', 'set', 'noin') manager.raw_cluster_cmd('osd', 'set', 'nodown') diff --git a/ceph/qa/tasks/divergent_priors2.py b/ceph/qa/tasks/divergent_priors2.py index 51a8a68f2..26b8120f0 100644 --- a/ceph/qa/tasks/divergent_priors2.py +++ b/ceph/qa/tasks/divergent_priors2.py @@ -35,9 +35,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.raw_cluster_cmd('osd', 'set', 'noout') manager.raw_cluster_cmd('osd', 'set', 'noin') manager.raw_cluster_cmd('osd', 'set', 'nodown') diff --git a/ceph/qa/tasks/dnsmasq.py b/ceph/qa/tasks/dnsmasq.py new file mode 100644 index 000000000..ee01b1795 --- /dev/null +++ b/ceph/qa/tasks/dnsmasq.py @@ -0,0 +1,102 @@ +""" +Task for dnsmasq configuration +""" +import contextlib +import logging + +from teuthology import misc +from teuthology.exceptions import ConfigError +from teuthology import contextutil +from util import get_remote_for_role + +log = logging.getLogger(__name__) + +@contextlib.contextmanager +def setup_dnsmasq(remote, cnames): + """ configure dnsmasq on the given remote, adding each cname given """ + log.info('Configuring dnsmasq on remote %s..', remote.name) + + # back up existing resolv.conf + resolv_conf = misc.get_file(remote, '/etc/resolv.conf') + # point resolv.conf to local dnsmasq + misc.sudo_write_file(remote, '/etc/resolv.conf', + "nameserver 127.0.0.1\n") + + # add address entries to /etc/dnsmasq.d/ceph + dnsmasq = "server=8.8.8.8\nserver=8.8.4.4\n" + address_template = "address=/{cname}/{ip_address}\n" + for cname, ip_address in cnames.iteritems(): + dnsmasq += address_template.format(cname=cname, ip_address=ip_address) + misc.sudo_write_file(remote, '/etc/dnsmasq.d/ceph', dnsmasq) + + remote.run(args=['cat', '/etc/dnsmasq.d/ceph']) + # restart dnsmasq + remote.run(args=['sudo', 'systemctl', 'restart', 'dnsmasq']) + remote.run(args=['sudo', 'systemctl', 'status', 'dnsmasq']) + # verify dns name is set + remote.run(args=['ping', '-c', '4', cnames.keys()[0]]) + + yield + + log.info('Removing dnsmasq configuration from remote %s..', remote.name) + # restore resolv.conf + misc.sudo_write_file(remote, '/etc/resolv.conf', resolv_conf) + # restart dnsmasq + remote.run(args=['sudo', 'systemctl', 'restart', 'dnsmasq']) + +@contextlib.contextmanager +def task(ctx, config): + """ + Configures dnsmasq to add cnames for teuthology remotes. The task expects a + dictionary, where each key is a role. If all cnames for that role use the + same address as that role, the cnames can be given as a list. For example, + this entry configures dnsmasq on the remote associated with client.0, adding + two cnames for the ip address associated with client.0: + + - dnsmasq: + client.0: + - client0.example.com + - c0.example.com + + If the addresses do not all match the given role, a dictionary can be given + to specify the ip address by its target role. For example: + + - dnsmasq: + client.0: + client.0.example.com: client.0 + client.1.example.com: client.1 + """ + # apply overrides + overrides = config.get('overrides', {}) + misc.deep_merge(config, overrides.get('dnsmasq', {})) + + # multiple roles may map to the same remote, so collect names by remote + remote_names = {} + for role, cnames in config.iteritems(): + remote = get_remote_for_role(ctx, role) + if remote is None: + raise ConfigError('no remote for role %s' % role) + + names = remote_names.get(remote, {}) + + if isinstance(cnames, list): + # when given a list of cnames, point to local ip + for cname in cnames: + names[cname] = remote.ip_address + elif isinstance(cnames, dict): + # when given a dict, look up the remote ip for each + for cname, client in cnames.iteritems(): + r = get_remote_for_role(ctx, client) + if r is None: + raise ConfigError('no remote for role %s' % client) + names[cname] = r.ip_address + + remote_names[remote] = names + + # run a subtask for each unique remote + subtasks = [] + for remote, cnames in remote_names.iteritems(): + subtasks.extend([ lambda r=remote, cn=cnames: setup_dnsmasq(r, cn) ]) + + with contextutil.nested(*subtasks): + yield diff --git a/ceph/qa/tasks/dump_stuck.py b/ceph/qa/tasks/dump_stuck.py index 86e04a9ca..8da634b5d 100644 --- a/ceph/qa/tasks/dump_stuck.py +++ b/ceph/qa/tasks/dump_stuck.py @@ -56,8 +56,7 @@ def task(ctx, config): logger=log.getChild('ceph_manager'), ) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_clean(timeout) manager.raw_cluster_cmd('tell', 'mon.0', 'injectargs', '--', @@ -74,7 +73,7 @@ def task(ctx, config): manager.mark_out_osd(0) time.sleep(timeout) - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([1]) manager.wait_for_recovery(timeout) check_stuck( @@ -85,8 +84,7 @@ def task(ctx, config): ) manager.mark_in_osd(0) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_clean(timeout) check_stuck( @@ -145,8 +143,7 @@ def task(ctx, config): manager.mark_in_osd(id_) while True: try: - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) break except Exception: log.exception('osds must not be started yet, waiting...') diff --git a/ceph/qa/tasks/ec_lost_unfound.py b/ceph/qa/tasks/ec_lost_unfound.py index 0dd4edcd7..d7a55fcab 100644 --- a/ceph/qa/tasks/ec_lost_unfound.py +++ b/ceph/qa/tasks/ec_lost_unfound.py @@ -48,8 +48,7 @@ def task(ctx, config): # kludge to make sure they get a map rados(ctx, mon, ['-p', pool, 'put', 'dummy', dummyfile]) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_recovery() # create old objects @@ -84,13 +83,9 @@ def task(ctx, config): manager.revive_osd(3) manager.wait_till_osd_is_up(3) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.3', 'flush_pg_stats') + manager.flush_pg_stats([0, 2, 3]) manager.wait_till_active() - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.3', 'flush_pg_stats') + manager.flush_pg_stats([0, 2, 3]) # verify that there are unfound objects unfound = manager.get_num_unfound_objects() @@ -141,9 +136,7 @@ def task(ctx, config): manager.raw_cluster_cmd('tell', 'osd.0', 'debug', 'kick_recovery_wq', '5') manager.raw_cluster_cmd('tell', 'osd.2', 'debug', 'kick_recovery_wq', '5') manager.raw_cluster_cmd('tell', 'osd.3', 'debug', 'kick_recovery_wq', '5') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.3', 'flush_pg_stats') + manager.flush_pg_stats([0, 2, 3]) manager.wait_for_recovery() if not config.get('parallel_bench', True): diff --git a/ceph/qa/tasks/lost_unfound.py b/ceph/qa/tasks/lost_unfound.py index 713688fa7..1cc588b40 100644 --- a/ceph/qa/tasks/lost_unfound.py +++ b/ceph/qa/tasks/lost_unfound.py @@ -48,8 +48,7 @@ def task(ctx, config): # kludge to make sure they get a map rados(ctx, mon, ['-p', POOL, 'put', 'dummy', dummyfile]) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_recovery() # create old objects @@ -84,8 +83,7 @@ def task(ctx, config): manager.mark_in_osd(0) manager.wait_till_osd_is_up(0) - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') + manager.flush_pg_stats([1, 0]) manager.wait_till_active() # take out osd.1 and the only copy of those objects. @@ -99,11 +97,9 @@ def task(ctx, config): manager.mark_in_osd(2) manager.wait_till_osd_is_up(2) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) manager.wait_till_active() - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) # verify that there are unfound objects unfound = manager.get_num_unfound_objects() @@ -160,8 +156,7 @@ def task(ctx, config): manager.raw_cluster_cmd('tell', 'osd.0', 'debug', 'kick_recovery_wq', '5') manager.raw_cluster_cmd('tell', 'osd.2', 'debug', 'kick_recovery_wq', '5') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) manager.wait_for_recovery() # verify result diff --git a/ceph/qa/tasks/mod_fastcgi.conf.template b/ceph/qa/tasks/mod_fastcgi.conf.template deleted file mode 100644 index d0efdc883..000000000 --- a/ceph/qa/tasks/mod_fastcgi.conf.template +++ /dev/null @@ -1,17 +0,0 @@ -# mod_fastcgi config goes here - -# Set fastcgi environment variables. -# Note that this is separate from Unix environment variables! -SetEnv RGW_LOG_LEVEL 20 -SetEnv RGW_SHOULD_LOG yes -SetEnv RGW_PRINT_CONTINUE {print_continue} - - - LoadModule fastcgi_module {mod_path}/mod_fastcgi.so - - -FastCgiIPCDir {testdir}/apache/tmp.{client}/fastcgi_sock -FastCgiExternalServer {testdir}/apache/htdocs.{client}/rgw.fcgi -socket rgw_sock -idle-timeout {idle_timeout} -RewriteEngine On - -RewriteRule ^/([a-zA-Z0-9-_.]*)([/]?.*) /rgw.fcgi?page=$1¶ms=$2&%{{QUERY_STRING}} [E=HTTP_AUTHORIZATION:%{{HTTP:Authorization}},L] diff --git a/ceph/qa/tasks/mod_proxy_fcgi.tcp.conf.template b/ceph/qa/tasks/mod_proxy_fcgi.tcp.conf.template deleted file mode 100644 index b47fb5cb4..000000000 --- a/ceph/qa/tasks/mod_proxy_fcgi.tcp.conf.template +++ /dev/null @@ -1,16 +0,0 @@ -# mod_proxy_fcgi config, using TCP - - - LoadModule proxy_module {mod_path}/mod_proxy.so - - - LoadModule proxy_fcgi_module {mod_path}/mod_proxy_fcgi.so - - -RewriteEngine On - -RewriteRule .* - [E=HTTP_AUTHORIZATION:%{{HTTP:Authorization}},L] - -SetEnv proxy-nokeepalive 1 - -ProxyPass / fcgi://0.0.0.0:9000/ diff --git a/ceph/qa/tasks/mod_proxy_fcgi.uds.conf.template b/ceph/qa/tasks/mod_proxy_fcgi.uds.conf.template deleted file mode 100644 index 8649aa728..000000000 --- a/ceph/qa/tasks/mod_proxy_fcgi.uds.conf.template +++ /dev/null @@ -1,14 +0,0 @@ -# mod_proxy_fcgi config, using UDS - - - LoadModule proxy_module {mod_path}/mod_proxy.so - - - LoadModule proxy_fcgi_module {mod_path}/mod_proxy_fcgi.so - - -RewriteEngine On - -RewriteRule .* - [E=HTTP_AUTHORIZATION:%{{HTTP:Authorization}},L] - -ProxyPass / unix://{testdir}/apache/tmp.{client}/fastcgi_sock/rgw_sock|fcgi://localhost:9000/ disablereuse=On diff --git a/ceph/qa/tasks/object_source_down.py b/ceph/qa/tasks/object_source_down.py index bea3d18c8..9705d7c73 100644 --- a/ceph/qa/tasks/object_source_down.py +++ b/ceph/qa/tasks/object_source_down.py @@ -76,8 +76,7 @@ def task(ctx, config): manager.mark_in_osd(0) manager.wait_till_active() - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') + manager.flush_pg_stats([2, 0]) manager.mark_out_osd(2) manager.wait_till_active() @@ -86,8 +85,7 @@ def task(ctx, config): manager.mark_in_osd(1) manager.wait_till_active() - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) log.info("Getting unfound objects") unfound = manager.get_num_unfound_objects() assert not unfound @@ -97,8 +95,7 @@ def task(ctx, config): manager.kill_osd(3) manager.mark_down_osd(3) - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) log.info("Getting unfound objects") unfound = manager.get_num_unfound_objects() assert unfound diff --git a/ceph/qa/tasks/osd_backfill.py b/ceph/qa/tasks/osd_backfill.py index dbed30fd4..04658d205 100644 --- a/ceph/qa/tasks/osd_backfill.py +++ b/ceph/qa/tasks/osd_backfill.py @@ -52,9 +52,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.wait_for_clean() # write some data @@ -71,8 +69,7 @@ def task(ctx, config): manager.mark_down_osd(0) # wait for everything to peer and be happy... - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([1, 2]) manager.wait_for_recovery() # write some new data @@ -96,14 +93,12 @@ def task(ctx, config): manager.wait_till_osd_is_up(2) # cluster must recover - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([1, 2]) manager.wait_for_recovery() # re-add osd.0 manager.revive_osd(0) - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([1, 2]) manager.wait_for_clean() diff --git a/ceph/qa/tasks/osd_recovery.py b/ceph/qa/tasks/osd_recovery.py index db46ade99..41e86d655 100644 --- a/ceph/qa/tasks/osd_recovery.py +++ b/ceph/qa/tasks/osd_recovery.py @@ -52,9 +52,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.wait_for_clean() # test some osdmap flags @@ -86,8 +84,7 @@ def task(ctx, config): log.info('err is %d' % err) # cluster must repeer - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_active_or_down() # write some more (make sure osd.2 really is divergent) @@ -103,9 +100,7 @@ def task(ctx, config): log.info('3 are up!') # cluster must recover - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.wait_for_clean() @@ -134,10 +129,7 @@ def test_incomplete_pgs(ctx, config): while len(manager.get_osd_status()['up']) < 4: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.3', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2, 3]) manager.wait_for_clean() log.info('Testing incomplete pgs...') @@ -149,10 +141,7 @@ def test_incomplete_pgs(ctx, config): # move data off of osd.0, osd.1 manager.raw_cluster_cmd('osd', 'out', '0', '1') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.3', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2, 3], [0, 1]) manager.wait_for_clean() # lots of objects in rbd (no pg log, will backfill) @@ -171,10 +160,7 @@ def test_incomplete_pgs(ctx, config): manager.raw_cluster_cmd('osd', 'in', '0', '1') manager.raw_cluster_cmd('osd', 'out', '2', '3') time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.3', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2, 3], [2, 3]) time.sleep(10) manager.wait_for_active() @@ -187,8 +173,7 @@ def test_incomplete_pgs(ctx, config): manager.kill_osd(3) log.info('...') manager.raw_cluster_cmd('osd', 'down', '2', '3') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_active_or_down() assert manager.get_num_down() > 0 diff --git a/ceph/qa/tasks/peer.py b/ceph/qa/tasks/peer.py index f2279d75b..9850da18e 100644 --- a/ceph/qa/tasks/peer.py +++ b/ceph/qa/tasks/peer.py @@ -30,9 +30,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.wait_for_clean() for i in range(3): @@ -47,8 +45,7 @@ def task(ctx, config): # kludge to make sure they get a map rados(ctx, mon, ['-p', 'data', 'get', 'dummy', '-']) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_recovery() # kill another and revive 2, so that some pgs can't peer. @@ -57,13 +54,11 @@ def task(ctx, config): manager.revive_osd(2) manager.wait_till_osd_is_up(2) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) manager.wait_for_active_or_down() - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) # look for down pgs num_down_pgs = 0 @@ -91,7 +86,5 @@ def task(ctx, config): # bring it all back manager.revive_osd(1) manager.wait_till_osd_is_up(1) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.wait_for_clean() diff --git a/ceph/qa/tasks/rados.py b/ceph/qa/tasks/rados.py index eceff9038..0732c0705 100644 --- a/ceph/qa/tasks/rados.py +++ b/ceph/qa/tasks/rados.py @@ -143,6 +143,8 @@ def task(ctx, config): args.extend(['--ec-pool']) if config.get('write_fadvise_dontneed', False): args.extend(['--write-fadvise-dontneed']) + if config.get('set_redirect', False): + args.extend(['--set_redirect']) if config.get('pool_snaps', False): args.extend(['--pool-snaps']) args.extend([ diff --git a/ceph/qa/tasks/radosgw_admin.py b/ceph/qa/tasks/radosgw_admin.py index 033d4d298..869034764 100644 --- a/ceph/qa/tasks/radosgw_admin.py +++ b/ceph/qa/tasks/radosgw_admin.py @@ -68,12 +68,6 @@ def task(ctx, config): """ global log - # regions and config found from rgw task - assert ctx.rgw.regions is not None, \ - "radosgw_admin task needs region(s) declared from the rgw task" - regions = ctx.rgw.regions - log.debug('regions are: %r', regions) - assert ctx.rgw.config, \ "radosgw_admin task needs a config passed from the rgw task" config = ctx.rgw.config @@ -84,20 +78,10 @@ def task(ctx, config): # choose first client as default client = clients_from_config[0] - multi_region_run = rgw_utils.multi_region_enabled(ctx) - if multi_region_run: - client = rgw_utils.get_config_master_client(ctx, config, regions) - - log.debug('multi_region_run is: %r', multi_region_run) - log.debug('master_client is: %r', client) - # once the client is chosen, pull the host name and assigned port out of # the role_endpoints that were assigned by the rgw task (remote_host, remote_port) = ctx.rgw.role_endpoints[client] - realm = ctx.rgw.realm - log.debug('radosgw-admin: realm %r', realm) - ## user1='foo' user2='fud' @@ -172,374 +156,6 @@ def task(ctx, config): assert out['keys'][0]['secret_key'] == secret_key assert not out['suspended'] - # this whole block should only be run if regions have been configured - if multi_region_run: - rgw_utils.radosgw_agent_sync_all(ctx) - # post-sync, validate that user1 exists on the sync destination host - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - dest_client = c_config['dest'] - (err, out) = rgwadmin(ctx, dest_client, ['metadata', 'list', 'user']) - (err, out) = rgwadmin(ctx, dest_client, ['user', 'info', '--uid', user1], check_status=True) - assert out['user_id'] == user1 - assert out['email'] == email - assert out['display_name'] == display_name1 - assert len(out['keys']) == 1 - assert out['keys'][0]['access_key'] == access_key - assert out['keys'][0]['secret_key'] == secret_key - assert not out['suspended'] - - # compare the metadata between different regions, make sure it matches - log.debug('compare the metadata between different regions, make sure it matches') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err1, out1) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'user:{uid}'.format(uid=user1)], check_status=True) - (err2, out2) = rgwadmin(ctx, dest_client, - ['metadata', 'get', 'user:{uid}'.format(uid=user1)], check_status=True) - assert out1 == out2 - - # suspend a user on the master, then check the status on the destination - log.debug('suspend a user on the master, then check the status on the destination') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err, out) = rgwadmin(ctx, source_client, ['user', 'suspend', '--uid', user1]) - rgw_utils.radosgw_agent_sync_all(ctx) - (err, out) = rgwadmin(ctx, dest_client, ['user', 'info', '--uid', user1], check_status=True) - assert out['suspended'] - - # delete a user on the master, then check that it's gone on the destination - log.debug('delete a user on the master, then check that it\'s gone on the destination') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err, out) = rgwadmin(ctx, source_client, ['user', 'rm', '--uid', user1], check_status=True) - rgw_utils.radosgw_agent_sync_all(ctx) - (err, out) = rgwadmin(ctx, source_client, ['user', 'info', '--uid', user1]) - assert out is None - (err, out) = rgwadmin(ctx, dest_client, ['user', 'info', '--uid', user1]) - assert out is None - - # then recreate it so later tests pass - (err, out) = rgwadmin(ctx, client, [ - 'user', 'create', - '--uid', user1, - '--display-name', display_name1, - '--email', email, - '--access-key', access_key, - '--secret', secret_key, - '--max-buckets', '4' - ], - check_status=True) - - # now do the multi-region bucket tests - log.debug('now do the multi-region bucket tests') - - # Create a second user for the following tests - log.debug('Create a second user for the following tests') - (err, out) = rgwadmin(ctx, client, [ - 'user', 'create', - '--uid', user2, - '--display-name', display_name2, - '--email', email2, - '--access-key', access_key2, - '--secret', secret_key2, - '--max-buckets', '4' - ], - check_status=True) - (err, out) = rgwadmin(ctx, client, ['user', 'info', '--uid', user2], check_status=True) - assert out is not None - - # create a bucket and do a sync - log.debug('create a bucket and do a sync') - bucket = connection.create_bucket(bucket_name2) - rgw_utils.radosgw_agent_sync_all(ctx) - - # compare the metadata for the bucket between different regions, make sure it matches - log.debug('compare the metadata for the bucket between different regions, make sure it matches') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err1, out1) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - (err2, out2) = rgwadmin(ctx, dest_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - log.debug('metadata 1 %r', out1) - log.debug('metadata 2 %r', out2) - assert out1 == out2 - - # get the bucket.instance info and compare that - src_bucket_id = out1['data']['bucket']['bucket_id'] - dest_bucket_id = out2['data']['bucket']['bucket_id'] - (err1, out1) = rgwadmin(ctx, source_client, ['metadata', 'get', - 'bucket.instance:{bucket_name}:{bucket_instance}'.format( - bucket_name=bucket_name2,bucket_instance=src_bucket_id)], - check_status=True) - (err2, out2) = rgwadmin(ctx, dest_client, ['metadata', 'get', - 'bucket.instance:{bucket_name}:{bucket_instance}'.format( - bucket_name=bucket_name2,bucket_instance=dest_bucket_id)], - check_status=True) - assert out1 == out2 - - same_region = 0 - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - - source_region = rgw_utils.region_for_client(ctx, source_client) - dest_region = rgw_utils.region_for_client(ctx, dest_client) - - # 301 is only returned for requests to something in a different region - if source_region == dest_region: - log.debug('301 is only returned for requests to something in a different region') - same_region += 1 - continue - - # Attempt to create a new connection with user1 to the destination RGW - log.debug('Attempt to create a new connection with user1 to the destination RGW') - # and use that to attempt a delete (that should fail) - - (dest_remote_host, dest_remote_port) = ctx.rgw.role_endpoints[dest_client] - connection_dest = boto.s3.connection.S3Connection( - aws_access_key_id=access_key, - aws_secret_access_key=secret_key, - is_secure=False, - port=dest_remote_port, - host=dest_remote_host, - calling_format=boto.s3.connection.OrdinaryCallingFormat(), - ) - - # this should fail - r, content = send_raw_http_request(connection_dest, 'DELETE', bucket_name2, '', follow_redirects = False) - assert r.status == 301 - - # now delete the bucket on the source RGW and do another sync - log.debug('now delete the bucket on the source RGW and do another sync') - bucket.delete() - rgw_utils.radosgw_agent_sync_all(ctx) - - if same_region == len(ctx.radosgw_agent.config): - bucket.delete() - rgw_utils.radosgw_agent_sync_all(ctx) - - # make sure that the bucket no longer exists in either region - log.debug('make sure that the bucket no longer exists in either region') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err1, out1) = rgwadmin(ctx, source_client, ['metadata', 'get', - 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)]) - (err2, out2) = rgwadmin(ctx, dest_client, ['metadata', 'get', - 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)]) - # Both of the previous calls should have errors due to requesting - # metadata for non-existent buckets - assert err1 - assert err2 - - # create a bucket and then sync it - log.debug('create a bucket and then sync it') - bucket = connection.create_bucket(bucket_name2) - rgw_utils.radosgw_agent_sync_all(ctx) - - # compare the metadata for the bucket between different regions, make sure it matches - log.debug('compare the metadata for the bucket between different regions, make sure it matches') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err1, out1) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - (err2, out2) = rgwadmin(ctx, dest_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - assert out1 == out2 - - # Now delete the bucket and recreate it with a different user - log.debug('Now delete the bucket and recreate it with a different user') - # within the same window of time and then sync. - bucket.delete() - bucket = connection2.create_bucket(bucket_name2) - rgw_utils.radosgw_agent_sync_all(ctx) - - # compare the metadata for the bucket between different regions, make sure it matches - log.debug('compare the metadata for the bucket between different regions, make sure it matches') - # user2 should own the bucket in both regions - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err1, out1) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - (err2, out2) = rgwadmin(ctx, dest_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - assert out1 == out2 - assert out1['data']['owner'] == user2 - assert out1['data']['owner'] != user1 - - # now we're going to use this bucket to test meta-data update propagation - log.debug('now we\'re going to use this bucket to test meta-data update propagation') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - - # get the metadata so we can tweak it - log.debug('get the metadata so we can tweak it') - (err, orig_data) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - - # manually edit mtime for this bucket to be 300 seconds in the past - log.debug('manually edit mtime for this bucket to be 300 seconds in the past') - new_data = copy.deepcopy(orig_data) - mtime = datetime.datetime.strptime(orig_data['mtime'], "%Y-%m-%d %H:%M:%S.%fZ") - datetime.timedelta(300) - new_data['mtime'] = unicode(mtime.strftime("%Y-%m-%d %H:%M:%S.%fZ")) - log.debug("new mtime ", mtime) - assert new_data != orig_data - (err, out) = rgwadmin(ctx, source_client, - ['metadata', 'put', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - stdin=StringIO(json.dumps(new_data)), - check_status=True) - - # get the metadata and make sure that the 'put' worked - log.debug('get the metadata and make sure that the \'put\' worked') - (err, out) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - assert out == new_data - - # sync to propagate the new metadata - log.debug('sync to propagate the new metadata') - rgw_utils.radosgw_agent_sync_all(ctx) - - # get the metadata from the dest and compare it to what we just set - log.debug('get the metadata from the dest and compare it to what we just set') - # and what the source region has. - (err1, out1) = rgwadmin(ctx, source_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - (err2, out2) = rgwadmin(ctx, dest_client, - ['metadata', 'get', 'bucket:{bucket_name}'.format(bucket_name=bucket_name2)], - check_status=True) - # yeah for the transitive property - assert out1 == out2 - assert out1 == new_data - - # now we delete the bucket - log.debug('now we delete the bucket') - bucket.delete() - - log.debug('sync to propagate the deleted bucket') - rgw_utils.radosgw_agent_sync_all(ctx) - - # Delete user2 as later tests do not expect it to exist. - # Verify that it is gone on both regions - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - source_client = c_config['src'] - dest_client = c_config['dest'] - (err, out) = rgwadmin(ctx, source_client, - ['user', 'rm', '--uid', user2], check_status=True) - rgw_utils.radosgw_agent_sync_all(ctx) - # The two 'user info' calls should fail and not return any data - # since we just deleted this user. - (err, out) = rgwadmin(ctx, source_client, ['user', 'info', '--uid', user2]) - assert out is None - (err, out) = rgwadmin(ctx, dest_client, ['user', 'info', '--uid', user2]) - assert out is None - - # Test data sync - - # First create a bucket for data sync test purpose - bucket = connection.create_bucket(bucket_name + 'data') - - # Create a tiny file and check if in sync - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - if c_config.get('metadata-only'): - continue - - for full in (True, False): - source_client = c_config['src'] - dest_client = c_config['dest'] - k = boto.s3.key.Key(bucket) - k.key = 'tiny_file' - k.set_contents_from_string("123456789") - safety_window = rgw_utils.radosgw_data_log_window(ctx, source_client) - time.sleep(safety_window) - rgw_utils.radosgw_agent_sync_all(ctx, data=True, full=full) - (dest_host, dest_port) = ctx.rgw.role_endpoints[dest_client] - dest_connection = boto.s3.connection.S3Connection( - aws_access_key_id=access_key, - aws_secret_access_key=secret_key, - is_secure=False, - port=dest_port, - host=dest_host, - calling_format=boto.s3.connection.OrdinaryCallingFormat(), - ) - dest_k = dest_connection.get_bucket(bucket_name + 'data').get_key('tiny_file') - assert k.get_contents_as_string() == dest_k.get_contents_as_string() - - # check that deleting it removes it from the dest zone - k.delete() - time.sleep(safety_window) - # full sync doesn't handle deleted objects yet - rgw_utils.radosgw_agent_sync_all(ctx, data=True, full=False) - - dest_bucket = dest_connection.get_bucket(bucket_name + 'data') - dest_k = dest_bucket.get_key('tiny_file') - assert dest_k == None, 'object not deleted from destination zone' - - # finally we delete the bucket - bucket.delete() - - bucket = connection.create_bucket(bucket_name + 'data2') - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - if c_config.get('metadata-only'): - continue - - for full in (True, False): - source_client = c_config['src'] - dest_client = c_config['dest'] - (dest_host, dest_port) = ctx.rgw.role_endpoints[dest_client] - dest_connection = boto.s3.connection.S3Connection( - aws_access_key_id=access_key, - aws_secret_access_key=secret_key, - is_secure=False, - port=dest_port, - host=dest_host, - calling_format=boto.s3.connection.OrdinaryCallingFormat(), - ) - for i in range(20): - k = boto.s3.key.Key(bucket) - k.key = 'tiny_file_' + str(i) - k.set_contents_from_string(str(i) * 100) - - safety_window = rgw_utils.radosgw_data_log_window(ctx, source_client) - time.sleep(safety_window) - rgw_utils.radosgw_agent_sync_all(ctx, data=True, full=full) - - for i in range(20): - dest_k = dest_connection.get_bucket(bucket_name + 'data2').get_key('tiny_file_' + str(i)) - assert (str(i) * 100) == dest_k.get_contents_as_string() - k = boto.s3.key.Key(bucket) - k.key = 'tiny_file_' + str(i) - k.delete() - - # check that deleting removes the objects from the dest zone - time.sleep(safety_window) - # full sync doesn't delete deleted objects yet - rgw_utils.radosgw_agent_sync_all(ctx, data=True, full=False) - - for i in range(20): - dest_bucket = dest_connection.get_bucket(bucket_name + 'data2') - dest_k = dest_bucket.get_key('tiny_file_' + str(i)) - assert dest_k == None, 'object %d not deleted from destination zone' % i - bucket.delete() - - # end of 'if multi_region_run:' - # TESTCASE 'suspend-ok','user','suspend','active user','succeeds' (err, out) = rgwadmin(ctx, client, ['user', 'suspend', '--uid', user1], check_status=True) @@ -643,9 +259,6 @@ def task(ctx, config): check_status=True) assert len(out) == 0 - if multi_region_run: - rgw_utils.radosgw_agent_sync_all(ctx) - # TESTCASE 'bucket-stats2','bucket','stats','no buckets','succeeds, empty list' (err, out) = rgwadmin(ctx, client, ['bucket', 'list', '--uid', user1], check_status=True) assert len(out) == 0 @@ -1002,10 +615,7 @@ def task(ctx, config): # TESTCASE 'zone-info', 'zone', 'get', 'get zone info', 'succeeds, has default placement rule' # - if realm is None: - (err, out) = rgwadmin(ctx, client, ['zone', 'get','--rgw-zone','default']) - else: - (err, out) = rgwadmin(ctx, client, ['zone', 'get']) + (err, out) = rgwadmin(ctx, client, ['zone', 'get','--rgw-zone','default']) orig_placement_pools = len(out['placement_pools']) # removed this test, it is not correct to assume that zone has default placement, it really @@ -1025,9 +635,6 @@ def task(ctx, config): stdin=StringIO(json.dumps(out)), check_status=True) - if realm is None: - (err, out) = rgwadmin(ctx, client, ['zone', 'get','--rgw-zone','default']) - else: - (err, out) = rgwadmin(ctx, client, ['zone', 'get']) + (err, out) = rgwadmin(ctx, client, ['zone', 'get','--rgw-zone','default']) assert len(out) > 0 assert len(out['placement_pools']) == orig_placement_pools + 1 diff --git a/ceph/qa/tasks/radosgw_agent.py b/ceph/qa/tasks/radosgw_agent.py deleted file mode 100644 index d6c7f77e7..000000000 --- a/ceph/qa/tasks/radosgw_agent.py +++ /dev/null @@ -1,212 +0,0 @@ -""" -Run rados gateway agent in test mode -""" -import contextlib -import logging -import argparse - -from teuthology.orchestra import run -from teuthology import misc as teuthology -import util.rgw as rgw_utils - -log = logging.getLogger(__name__) - -def run_radosgw_agent(ctx, config): - """ - Run a single radosgw-agent. See task() for config format. - """ - return_list = list() - for (client, cconf) in config.items(): - # don't process entries that are not clients - log.debug("client is %r", client) - if not 'client.' in client: - log.debug('key {data} does not contain \'client.\', moving on'.format( - data=client)) - continue - - src_client = cconf['src'] - dest_client = cconf['dest'] - - src_zone = rgw_utils.zone_for_client(ctx, src_client) - dest_zone = rgw_utils.zone_for_client(ctx, dest_client) - - log.info("source is %s", src_zone) - log.info("dest is %s", dest_zone) - - testdir = teuthology.get_testdir(ctx) - (remote,) = ctx.cluster.only(client).remotes.keys() - # figure out which branch to pull from - branch = cconf.get('force-branch', None) - if not branch: - branch = cconf.get('branch', 'master') - sha1 = cconf.get('sha1') - remote.run( - args=[ - 'cd', testdir, run.Raw('&&'), - 'git', 'clone', - '-b', branch, -# 'https://github.com/ceph/radosgw-agent.git', - 'git://git.ceph.com/radosgw-agent.git', - 'radosgw-agent.{client}'.format(client=client), - ] - ) - if sha1 is not None: - remote.run( - args=[ - 'cd', testdir, run.Raw('&&'), - run.Raw('&&'), - 'git', 'reset', '--hard', sha1, - ] - ) - remote.run( - args=[ - 'cd', testdir, run.Raw('&&'), - 'cd', 'radosgw-agent.{client}'.format(client=client), - run.Raw('&&'), - './bootstrap', - ] - ) - - src_host, src_port = rgw_utils.get_zone_host_and_port(ctx, src_client, - src_zone) - dest_host, dest_port = rgw_utils.get_zone_host_and_port(ctx, dest_client, - dest_zone) - src_access, src_secret = rgw_utils.get_zone_system_keys(ctx, src_client, - src_zone) - dest_access, dest_secret = rgw_utils.get_zone_system_keys(ctx, dest_client, - dest_zone) - sync_scope = cconf.get('sync-scope', None) - port = cconf.get('port', 8000) - daemon_name = '{host}.{port}.syncdaemon'.format(host=remote.name, port=port) - in_args=[ - 'daemon-helper', - 'kill', - '{tdir}/radosgw-agent.{client}/radosgw-agent'.format(tdir=testdir, - client=client), - '-v', - '--src-access-key', src_access, - '--src-secret-key', src_secret, - '--source', "http://{addr}:{port}".format(addr=src_host, port=src_port), - '--dest-access-key', dest_access, - '--dest-secret-key', dest_secret, - '--max-entries', str(cconf.get('max-entries', 1000)), - '--log-file', '{tdir}/archive/rgw_sync_agent.{client}.log'.format( - tdir=testdir, - client=client), - '--object-sync-timeout', '30', - ] - - if cconf.get('metadata-only', False): - in_args.append('--metadata-only') - - # the test server and full/incremental flags are mutually exclusive - if sync_scope is None: - in_args.append('--test-server-host') - in_args.append('0.0.0.0') - in_args.append('--test-server-port') - in_args.append(str(port)) - log.debug('Starting a sync test server on {client}'.format(client=client)) - # Stash the radosgw-agent server / port # for use by subsequent tasks - ctx.radosgw_agent.endpoint = (client, str(port)) - else: - in_args.append('--sync-scope') - in_args.append(sync_scope) - log.debug('Starting a {scope} sync on {client}'.format(scope=sync_scope,client=client)) - - # positional arg for destination must come last - in_args.append("http://{addr}:{port}".format(addr=dest_host, - port=dest_port)) - - return_list.append((client, remote.run( - args=in_args, - wait=False, - stdin=run.PIPE, - logger=log.getChild(daemon_name), - ))) - return return_list - - -@contextlib.contextmanager -def task(ctx, config): - """ - Run radosgw-agents in test mode. - - Configuration is clients to run the agents on, with settings for - source client, destination client, and port to listen on. Binds - to 0.0.0.0. Port defaults to 8000. This must be run on clients - that have the correct zone root pools and rgw zone set in - ceph.conf, or the task cannot read the region information from the - cluster. - - By default, this task will start an HTTP server that will trigger full - or incremental syncs based on requests made to it. - Alternatively, a single full sync can be triggered by - specifying 'sync-scope: full' or a loop of incremental syncs can be triggered - by specifying 'sync-scope: incremental' (the loop will sleep - '--incremental-sync-delay' seconds between each sync, default is 30 seconds). - - By default, both data and metadata are synced. To only sync - metadata, for example because you want to sync between regions, - set metadata-only: true. - - An example:: - - tasks: - - ceph: - conf: - client.0: - rgw zone = foo - rgw zone root pool = .root.pool - client.1: - rgw zone = bar - rgw zone root pool = .root.pool2 - - rgw: # region configuration omitted for brevity - - radosgw-agent: - client.0: - branch: wip-next-feature-branch - src: client.0 - dest: client.1 - sync-scope: full - metadata-only: true - # port: 8000 (default) - client.1: - src: client.1 - dest: client.0 - port: 8001 - """ - assert isinstance(config, dict), 'rgw_sync_agent requires a dictionary config' - log.debug("config is %s", config) - - overrides = ctx.config.get('overrides', {}) - # merge each client section, but only if it exists in config since there isn't - # a sensible default action for this task - for client in config.iterkeys(): - if config[client]: - log.debug('config[{client}]: {data}'.format(client=client, data=config[client])) - teuthology.deep_merge(config[client], overrides.get('radosgw-agent', {})) - - ctx.radosgw_agent = argparse.Namespace() - ctx.radosgw_agent.config = config - - procs = run_radosgw_agent(ctx, config) - - ctx.radosgw_agent.procs = procs - - try: - yield - finally: - testdir = teuthology.get_testdir(ctx) - try: - for client, proc in procs: - log.info("shutting down sync agent on %s", client) - proc.stdin.close() - proc.wait() - finally: - for client, proc in procs: - ctx.cluster.only(client).run( - args=[ - 'rm', '-rf', - '{tdir}/radosgw-agent.{client}'.format(tdir=testdir, - client=client) - ] - ) diff --git a/ceph/qa/tasks/rebuild_mondb.py b/ceph/qa/tasks/rebuild_mondb.py index fe70c641d..900bd16a4 100644 --- a/ceph/qa/tasks/rebuild_mondb.py +++ b/ceph/qa/tasks/rebuild_mondb.py @@ -14,7 +14,7 @@ from teuthology import misc as teuthology log = logging.getLogger(__name__) -def push_directory(path, remote, remote_dir): +def _push_directory(path, remote, remote_dir): """ local_temp_path=`mktemp` tar czf $local_temp_path $path @@ -46,45 +46,20 @@ def push_directory(path, remote, remote_dir): remote.run(args=['sudo', 'rm', '-fr', remote_temp_path]) -def task(ctx, config): - """ - Test monitor recovery from OSD - """ - if config is None: - config = {} - assert isinstance(config, dict), \ - 'task only accepts a dict for configuration' - - first_mon = teuthology.get_first_mon(ctx, config) - (mon,) = ctx.cluster.only(first_mon).remotes.iterkeys() - - manager = ceph_manager.CephManager( - mon, - ctx=ctx, - logger=log.getChild('ceph_manager')) - - mons = ctx.cluster.only(teuthology.is_type('mon')) +def _nuke_mons(manager, mons, mon_id): assert mons - # note down the first cluster_name and mon_id - # we will recover it later on - cluster_name = None - mon_id = None + is_mon = teuthology.is_type('mon') for remote, roles in mons.remotes.iteritems(): - is_mon = teuthology.is_type('mon') for role in roles: if not is_mon(role): continue cluster, _, m = teuthology.split_role(role) - if cluster_name is None: - cluster_name = cluster - mon_id = m - assert cluster_name == cluster log.info('killing {cluster}:mon.{mon}'.format( cluster=cluster, mon=m)) manager.kill_mon(m) mon_data = os.path.join('/var/lib/ceph/mon/', - '{0}-{1}'.format(cluster_name, m)) + '{0}-{1}'.format(cluster, m)) if m == mon_id: # so we will only need to recreate the store.db for the # first mon, would be easier than mkfs on it then replace @@ -94,13 +69,15 @@ def task(ctx, config): else: remote.run(args=['sudo', 'rm', '-r', mon_data]) + +def _rebuild_db(ctx, manager, cluster_name, mon, mon_id, keyring_path): local_mstore = tempfile.mkdtemp() # collect the maps from all OSDs - osds = ctx.cluster.only(teuthology.is_type('osd')) + is_osd = teuthology.is_type('osd') + osds = ctx.cluster.only(is_osd) assert osds for osd, roles in osds.remotes.iteritems(): - is_osd = teuthology.is_type('osd') for role in roles: if not is_osd(role): continue @@ -113,7 +90,7 @@ def task(ctx, config): osd_mstore = os.path.join(teuthology.get_testdir(ctx), 'mon-store') osd.run(args=['sudo', 'mkdir', '-m', 'o+x', '-p', osd_mstore]) - push_directory(local_mstore, osd, osd_mstore) + _push_directory(local_mstore, osd, osd_mstore) log.info('rm -rf {0}'.format(local_mstore)) shutil.rmtree(local_mstore) # update leveldb with OSD data @@ -135,12 +112,10 @@ def task(ctx, config): # pull from recovered leveldb from client mon_store_dir = os.path.join('/var/lib/ceph/mon', '{0}-{1}'.format(cluster_name, mon_id)) - push_directory(local_mstore, mon, mon_store_dir) + _push_directory(local_mstore, mon, mon_store_dir) mon.run(args=['sudo', 'chown', '-R', 'ceph:ceph', mon_store_dir]) shutil.rmtree(local_mstore) - default_keyring = '/etc/ceph/{cluster}.keyring'.format( - cluster=cluster_name) - keyring_path = config.get('keyring_path', default_keyring) + # fill up the caps in the keyring file mon.run(args=['sudo', 'ceph-authtool', keyring_path, @@ -151,23 +126,25 @@ def task(ctx, config): '-n', 'client.admin', '--cap', 'mon', 'allow *', '--cap', 'osd', 'allow *', - '--cap', 'mds', 'allow *']) + '--cap', 'mds', 'allow *', + '--cap', 'mgr', 'allow *']) mon.run(args=['sudo', '-u', 'ceph', 'ceph-monstore-tool', mon_store_dir, 'rebuild', '--', '--keyring', keyring_path]) + +def _revive_mons(manager, mons, recovered, keyring_path): # revive monitors # the initial monmap is in the ceph.conf, so we are good. n_mons = 0 + is_mon = teuthology.is_type('mon') for remote, roles in mons.remotes.iteritems(): - is_mon = teuthology.is_type('mon') for role in roles: if not is_mon(role): continue cluster, _, m = teuthology.split_role(role) - assert cluster_name == cluster - if mon_id != m: + if recovered != m: log.info('running mkfs on {cluster}:mon.{mon}'.format( cluster=cluster, mon=m)) @@ -179,15 +156,61 @@ def task(ctx, config): '--mkfs', '-i', m, '--keyring', keyring_path]) + log.info('reviving mon.{0}'.format(m)) manager.revive_mon(m) n_mons += 1 - manager.wait_for_mon_quorum_size(n_mons, timeout=30) - for osd, roles in osds.remotes.iteritems(): - is_osd = teuthology.is_type('osd') + + +def _revive_mgrs(ctx, manager): + is_mgr = teuthology.is_type('mgr') + mgrs = ctx.cluster.only(is_mgr) + for _, roles in mgrs.remotes.iteritems(): + for role in roles: + if not is_mgr(role): + continue + _, _, mgr_id = teuthology.split_role(role) + log.info('reviving mgr.{0}'.format(mgr_id)) + manager.revive_mgr(mgr_id) + + +def _revive_osds(ctx, manager): + is_osd = teuthology.is_type('osd') + osds = ctx.cluster.only(is_osd) + for _, roles in osds.remotes.iteritems(): for role in roles: if not is_osd(role): continue _, _, osd_id = teuthology.split_role(role) log.info('reviving osd.{0}'.format(osd_id)) manager.revive_osd(osd_id) + + +def task(ctx, config): + """ + Test monitor recovery from OSD + """ + if config is None: + config = {} + assert isinstance(config, dict), \ + 'task only accepts a dict for configuration' + + first_mon = teuthology.get_first_mon(ctx, config) + (mon,) = ctx.cluster.only(first_mon).remotes.iterkeys() + manager = ceph_manager.CephManager( + mon, + ctx=ctx, + logger=log.getChild('ceph_manager')) + + mons = ctx.cluster.only(teuthology.is_type('mon')) + # note down the first cluster_name and mon_id + # we will recover it later on + cluster_name, _, mon_id = teuthology.split_role(first_mon) + _nuke_mons(manager, mons, mon_id) + default_keyring = '/etc/ceph/{cluster}.keyring'.format( + cluster=cluster_name) + keyring_path = config.get('keyring_path', default_keyring) + _rebuild_db(ctx, manager, cluster_name, mon, mon_id, keyring_path) + _revive_mons(manager, mons, mon_id, keyring_path) + _revive_mgrs(ctx, manager) + _revive_osds(ctx, manager) diff --git a/ceph/qa/tasks/reg11184.py b/ceph/qa/tasks/reg11184.py index ebddcc3bd..03db1b064 100644 --- a/ceph/qa/tasks/reg11184.py +++ b/ceph/qa/tasks/reg11184.py @@ -40,9 +40,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.raw_cluster_cmd('osd', 'set', 'noout') manager.raw_cluster_cmd('osd', 'set', 'noin') manager.raw_cluster_cmd('osd', 'set', 'nodown') diff --git a/ceph/qa/tasks/rep_lost_unfound_delete.py b/ceph/qa/tasks/rep_lost_unfound_delete.py index b0ba3dc0e..4e5678d08 100644 --- a/ceph/qa/tasks/rep_lost_unfound_delete.py +++ b/ceph/qa/tasks/rep_lost_unfound_delete.py @@ -32,9 +32,7 @@ def task(ctx, config): while len(manager.get_osd_status()['up']) < 3: time.sleep(10) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 1, 2]) manager.wait_for_clean() manager.create_pool(POOL) @@ -50,8 +48,7 @@ def task(ctx, config): # kludge to make sure they get a map rados(ctx, mon, ['-p', POOL, 'put', 'dummy', dummyfile]) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_for_recovery() # create old objects @@ -86,8 +83,7 @@ def task(ctx, config): manager.mark_in_osd(0) manager.wait_till_osd_is_up(0) - manager.raw_cluster_cmd('tell', 'osd.1', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') + manager.flush_pg_stats([0, 1]) manager.wait_till_active() # take out osd.1 and the only copy of those objects. @@ -101,11 +97,9 @@ def task(ctx, config): manager.mark_in_osd(2) manager.wait_till_osd_is_up(2) - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) manager.wait_till_active() - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) # verify that there are unfound objects unfound = manager.get_num_unfound_objects() @@ -162,8 +156,7 @@ def task(ctx, config): manager.raw_cluster_cmd('tell', 'osd.0', 'debug', 'kick_recovery_wq', '5') manager.raw_cluster_cmd('tell', 'osd.2', 'debug', 'kick_recovery_wq', '5') - manager.raw_cluster_cmd('tell', 'osd.0', 'flush_pg_stats') - manager.raw_cluster_cmd('tell', 'osd.2', 'flush_pg_stats') + manager.flush_pg_stats([0, 2]) manager.wait_for_recovery() # verify result diff --git a/ceph/qa/tasks/repair_test.py b/ceph/qa/tasks/repair_test.py index b05ea3748..26851e25e 100644 --- a/ceph/qa/tasks/repair_test.py +++ b/ceph/qa/tasks/repair_test.py @@ -303,3 +303,6 @@ def task(ctx, config): repair_test_2(ctx, manager, config, choose_replica) repair_test_erasure_code(manager, hinfoerr, 'primary', "deep-scrub") + + manager.raw_cluster_cmd('osd', 'unset', 'noscrub') + manager.raw_cluster_cmd('osd', 'unset', 'nodeep-scrub') diff --git a/ceph/qa/tasks/resolve_stuck_peering.py b/ceph/qa/tasks/resolve_stuck_peering.py index 3c7bb9eca..bdf86e924 100644 --- a/ceph/qa/tasks/resolve_stuck_peering.py +++ b/ceph/qa/tasks/resolve_stuck_peering.py @@ -108,3 +108,5 @@ def task(ctx, config): while manager.get_num_down(): assert time.time() - start < timeout, \ 'failed to recover before timeout expired' + + manager.revive_osd(primary) diff --git a/ceph/qa/tasks/rgw.py b/ceph/qa/tasks/rgw.py index 6e73a182b..3656c673d 100644 --- a/ceph/qa/tasks/rgw.py +++ b/ceph/qa/tasks/rgw.py @@ -9,16 +9,11 @@ import os import errno import util.rgw as rgw_utils -from requests.packages.urllib3 import PoolManager -from requests.packages.urllib3.util import Retry - -from cStringIO import StringIO - from teuthology.orchestra import run from teuthology import misc as teuthology from teuthology import contextutil from teuthology.orchestra.run import CommandFailedError -from util.rgw import rgwadmin, get_config_master_client, extract_zone_info, extract_region_info +from util.rgw import rgwadmin, wait_for_radosgw from util.rados import (rados, create_ec_pool, create_replicated_pool, create_cache_pool) @@ -26,245 +21,22 @@ from util.rados import (rados, create_ec_pool, log = logging.getLogger(__name__) @contextlib.contextmanager -def create_apache_dirs(ctx, config, on_client = None, except_client = None): - """ - Remotely create apache directories. Delete when finished. - """ - log.info('Creating apache directories...') - log.debug('client is %r', on_client) - testdir = teuthology.get_testdir(ctx) - clients_to_create_as = [on_client] - if on_client is None: - clients_to_create_as = config.keys() - for client in clients_to_create_as: - if client == except_client: - continue - cluster_name, daemon_type, client_id = teuthology.split_role(client) - client_with_cluster = cluster_name + '.' + daemon_type + '.' + client_id - ctx.cluster.only(client).run( - args=[ - 'mkdir', - '-p', - '{tdir}/apache/htdocs.{client_with_cluster}'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - '{tdir}/apache/tmp.{client_with_cluster}/fastcgi_sock'.format( - tdir=testdir, - client_with_cluster=client_with_cluster), - run.Raw('&&'), - 'mkdir', - '{tdir}/archive/apache.{client_with_cluster}'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - ], - ) - try: - yield - finally: - log.info('Cleaning up apache directories...') - for client in clients_to_create_as: - ctx.cluster.only(client).run( - args=[ - 'rm', - '-rf', - '{tdir}/apache/tmp.{client_with_cluster}'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - run.Raw('&&'), - 'rmdir', - '{tdir}/apache/htdocs.{client_with_cluster}'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - ], - ) - for client in clients_to_create_as: - ctx.cluster.only(client).run( - args=[ - 'rmdir', - '{tdir}/apache'.format(tdir=testdir), - ], - check_status=False, # only need to remove once per host - ) - - -def _use_uds_with_fcgi(remote): - """ - Returns true if this node supports the usage of - unix domain sockets with mod_proxy_fcgi. - - FIXME: returns False always for now until we know for - sure what distros will support UDS. RHEL 7.0 is the only one - currently I know of, but we can't install that version of apache - yet in the labs. - """ - return False - - -@contextlib.contextmanager -def ship_apache_configs(ctx, config, role_endpoints, on_client = None, - except_client = None): - """ - Ship apache config and rgw.fgci to all clients. Clean up on termination - """ - assert isinstance(config, dict) - assert isinstance(role_endpoints, dict) - testdir = teuthology.get_testdir(ctx) - log.info('Shipping apache config and rgw.fcgi...') - src = os.path.join(os.path.dirname(__file__), 'apache.conf.template') - clients_to_create_as = [on_client] - if on_client is None: - clients_to_create_as = config.keys() - for client in clients_to_create_as: - if client == except_client: - continue - cluster_name, daemon_type, client_id = teuthology.split_role(client) - client_with_id = daemon_type + '.' + client_id - client_with_cluster = cluster_name + '.' + client_with_id - (remote,) = ctx.cluster.only(client).remotes.keys() - system_type = teuthology.get_system_type(remote) - conf = config.get(client) - if not conf: - conf = {} - idle_timeout = conf.get('idle_timeout', ctx.rgw.default_idle_timeout) - if system_type == 'deb': - mod_path = '/usr/lib/apache2/modules' - print_continue = 'on' - user = 'www-data' - group = 'www-data' - apache24_modconfig = ''' - IncludeOptional /etc/apache2/mods-available/mpm_event.conf - IncludeOptional /etc/apache2/mods-available/mpm_event.load -''' - else: - mod_path = '/usr/lib64/httpd/modules' - print_continue = 'off' - user = 'apache' - group = 'apache' - apache24_modconfig = \ - 'IncludeOptional /etc/httpd/conf.modules.d/00-mpm.conf' - host, port = role_endpoints[client] - - # decide if we want to use mod_fastcgi or mod_proxy_fcgi - template_dir = os.path.dirname(__file__) - fcgi_config = os.path.join(template_dir, - 'mod_proxy_fcgi.tcp.conf.template') - if ctx.rgw.use_fastcgi: - log.info("Apache is configured to use mod_fastcgi") - fcgi_config = os.path.join(template_dir, - 'mod_fastcgi.conf.template') - elif _use_uds_with_fcgi(remote): - log.info("Apache is configured to use mod_proxy_fcgi with UDS") - fcgi_config = os.path.join(template_dir, - 'mod_proxy_fcgi.uds.conf.template') - else: - log.info("Apache is configured to use mod_proxy_fcgi with TCP") - - with file(fcgi_config, 'rb') as f: - fcgi_config = f.read() - with file(src, 'rb') as f: - conf = f.read() + fcgi_config - conf = conf.format( - testdir=testdir, - mod_path=mod_path, - print_continue=print_continue, - host=host, - port=port, - client=client_with_cluster, - idle_timeout=idle_timeout, - user=user, - group=group, - apache24_modconfig=apache24_modconfig, - ) - teuthology.write_file( - remote=remote, - path='{tdir}/apache/apache.{client_with_cluster}.conf'.format( - tdir=testdir, - client_with_cluster=client_with_cluster), - data=conf, - ) - rgw_options = [] - if ctx.rgw.use_fastcgi or _use_uds_with_fcgi(remote): - rgw_options = [ - '--rgw-socket-path', - '{tdir}/apache/tmp.{client_with_cluster}/fastcgi_sock/rgw_sock'.format( - tdir=testdir, - client_with_cluster=client_with_cluster - ), - '--rgw-frontends', - 'fastcgi', - ] - else: - rgw_options = [ - '--rgw-socket-path', '""', - '--rgw-print-continue', 'false', - '--rgw-frontends', - 'fastcgi socket_port=9000 socket_host=0.0.0.0', - ] - - teuthology.write_file( - remote=remote, - path='{tdir}/apache/htdocs.{client_with_cluster}/rgw.fcgi'.format( - tdir=testdir, - client_with_cluster=client_with_cluster), - data="""#!/bin/sh -ulimit -c unlimited -exec radosgw -f -n {client_with_id} --cluster {cluster_name} -k /etc/ceph/{client_with_cluster}.keyring {rgw_options} - -""".format(tdir=testdir, client_with_id=client_with_id, client_with_cluster=client_with_cluster, cluster_name=cluster_name, rgw_options=" ".join(rgw_options)) - ) - remote.run( - args=[ - 'chmod', - 'a=rx', - '{tdir}/apache/htdocs.{client_with_cluster}/rgw.fcgi'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - ], - ) - try: - yield - finally: - log.info('Removing apache config...') - for client in clients_to_create_as: - ctx.cluster.only(client).run( - args=[ - 'rm', - '-f', - '{tdir}/apache/apache.{client_with_cluster}.conf'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - run.Raw('&&'), - 'rm', - '-f', - '{tdir}/apache/htdocs.{client_with_cluster}/rgw.fcgi'.format( - tdir=testdir, - client_with_cluster=client_with_cluster), - ], - ) - - -@contextlib.contextmanager -def start_rgw(ctx, config, on_client = None, except_client = None): +def start_rgw(ctx, config): """ Start rgw on remote sites. """ log.info('Starting rgw...') - log.debug('client %r', on_client) - clients_to_run = [on_client] - if on_client is None: - clients_to_run = config.keys() - log.debug('client %r', clients_to_run) testdir = teuthology.get_testdir(ctx) - for client in clients_to_run: - if client == except_client: - continue + for client in config.keys(): (remote,) = ctx.cluster.only(client).remotes.iterkeys() cluster_name, daemon_type, client_id = teuthology.split_role(client) client_with_id = daemon_type + '.' + client_id client_with_cluster = cluster_name + '.' + client_with_id - zone = rgw_utils.zone_for_client(ctx, client) - log.debug('zone %s', zone) client_config = config.get(client) if client_config is None: client_config = {} log.info("rgw %s config is %s", client, client_config) - id_ = client.split('.', 1)[1] - log.info('client {client} is id {id}'.format(client=client, id=id_)) cmd_prefix = [ 'sudo', 'adjust-ulimits', @@ -276,37 +48,12 @@ def start_rgw(ctx, config, on_client = None, except_client = None): rgw_cmd = ['radosgw'] - if ctx.rgw.frontend == 'apache': - if ctx.rgw.use_fastcgi or _use_uds_with_fcgi(remote): - rgw_cmd.extend([ - '--rgw-socket-path', - '{tdir}/apache/tmp.{client_with_cluster}/fastcgi_sock/rgw_sock'.format( - tdir=testdir, - client_with_cluster=client_with_cluster, - ), - '--rgw-frontends', - 'fastcgi', - ]) - else: - # for mod_proxy_fcgi, using tcp - rgw_cmd.extend([ - '--rgw-socket-path', '', - '--rgw-print-continue', 'false', - '--rgw-frontends', - 'fastcgi socket_port=9000 socket_host=0.0.0.0', - ]) - - elif ctx.rgw.frontend == 'civetweb': - host, port = ctx.rgw.role_endpoints[client] - rgw_cmd.extend([ - '--rgw-frontends', - 'civetweb port={port}'.format(port=port), - ]) - - if zone is not None: - rgw_cmd.extend(['--rgw-zone', zone]) + log.info("Using %s as radosgw frontend", ctx.rgw.frontend) + host, port = ctx.rgw.role_endpoints[client] rgw_cmd.extend([ + '--rgw-frontends', + '{frontend} port={port}'.format(frontend=ctx.rgw.frontend, port=port), '-n', client_with_id, '--cluster', cluster_name, '-k', '/etc/ceph/{client_with_cluster}.keyring'.format(client_with_cluster=client_with_cluster), @@ -327,7 +74,7 @@ def start_rgw(ctx, config, on_client = None, except_client = None): if client_config.get('valgrind'): cmd_prefix = teuthology.get_valgrind_args( testdir, - client, + client_with_cluster, cmd_prefix, client_config.get('valgrind') ) @@ -336,7 +83,7 @@ def start_rgw(ctx, config, on_client = None, except_client = None): run_cmd.extend(rgw_cmd) ctx.daemons.add_daemon( - remote, 'rgw', client, + remote, 'rgw', client_with_id, cluster=cluster_name, args=run_cmd, logger=log.getChild(client), @@ -345,109 +92,29 @@ def start_rgw(ctx, config, on_client = None, except_client = None): ) # XXX: add_daemon() doesn't let us wait until radosgw finishes startup - # use a connection pool with retry/backoff to poll each gateway until it starts listening - http = PoolManager(retries=Retry(connect=8, backoff_factor=1)) - for client in clients_to_run: - if client == except_client: - continue + for client in config.keys(): host, port = ctx.rgw.role_endpoints[client] endpoint = 'http://{host}:{port}/'.format(host=host, port=port) log.info('Polling {client} until it starts accepting connections on {endpoint}'.format(client=client, endpoint=endpoint)) - http.request('GET', endpoint) + wait_for_radosgw(endpoint) try: yield finally: - teuthology.stop_daemons_of_type(ctx, 'rgw') for client in config.iterkeys(): + cluster_name, daemon_type, client_id = teuthology.split_role(client) + client_with_id = daemon_type + '.' + client_id + client_with_cluster = cluster_name + '.' + client_with_id + ctx.daemons.get_daemon('rgw', client_with_id, cluster_name).stop() ctx.cluster.only(client).run( args=[ 'rm', '-f', - '{tdir}/rgw.opslog.{client_with_cluster}.sock'.format(tdir=testdir, - client_with_cluster=client_with_cluster), + '{tdir}/rgw.opslog.{client}.sock'.format(tdir=testdir, + client=client_with_cluster), ], ) - -@contextlib.contextmanager -def start_apache(ctx, config, on_client = None, except_client = None): - """ - Start apache on remote sites. - """ - log.info('Starting apache...') - testdir = teuthology.get_testdir(ctx) - apaches = {} - clients_to_run = [on_client] - if on_client is None: - clients_to_run = config.keys() - for client in clients_to_run: - cluster_name, daemon_type, client_id = teuthology.split_role(client) - client_with_cluster = cluster_name + '.' + daemon_type + '.' + client_id - if client == except_client: - continue - (remote,) = ctx.cluster.only(client).remotes.keys() - system_type = teuthology.get_system_type(remote) - if system_type == 'deb': - apache_name = 'apache2' - else: - try: - remote.run( - args=[ - 'stat', - '/usr/sbin/httpd.worker', - ], - ) - apache_name = '/usr/sbin/httpd.worker' - except CommandFailedError: - apache_name = '/usr/sbin/httpd' - - proc = remote.run( - args=[ - 'adjust-ulimits', - 'daemon-helper', - 'kill', - apache_name, - '-X', - '-f', - '{tdir}/apache/apache.{client_with_cluster}.conf'.format(tdir=testdir, - client_with_cluster=client_with_cluster), - ], - logger=log.getChild(client), - stdin=run.PIPE, - wait=False, - ) - apaches[client_with_cluster] = proc - - try: - yield - finally: - log.info('Stopping apache...') - for client, proc in apaches.iteritems(): - proc.stdin.close() - - run.wait(apaches.itervalues()) - -def extract_user_info(client_config): - """ - Extract user info from the client config specified. Returns a dict - that includes system key information. - """ - # test if there isn't a system user or if there isn't a name for that - # user, return None - if ('system user' not in client_config or - 'name' not in client_config['system user']): - return None - - user_info = dict() - user_info['system_key'] = dict( - user=client_config['system user']['name'], - access_key=client_config['system user']['access key'], - secret_key=client_config['system user']['secret key'], - ) - return user_info - - def assign_ports(ctx, config): """ Assign port numberst starting with port 7280. @@ -462,145 +129,11 @@ def assign_ports(ctx, config): return role_endpoints - -def fill_in_endpoints(region_info, role_zones, role_endpoints): - """ - Iterate through the list of role_endpoints, filling in zone information - - :param region_info: region data - :param role_zones: region and zone information. - :param role_endpoints: endpoints being used - """ - for role, (host, port) in role_endpoints.iteritems(): - region, zone, zone_info, _ = role_zones[role] - host, port = role_endpoints[role] - endpoint = 'http://{host}:{port}/'.format(host=host, port=port) - # check if the region specified under client actually exists - # in region_info (it should, if properly configured). - # If not, throw a reasonable error - if region not in region_info: - raise Exception( - 'Region: {region} was specified but no corresponding' - ' entry was found under \'regions\''.format(region=region)) - - region_conf = region_info[region] - region_conf.setdefault('endpoints', []) - region_conf['endpoints'].append(endpoint) - - # this is the payload for the 'zones' field in the region field - zone_payload = dict() - zone_payload['endpoints'] = [endpoint] - zone_payload['name'] = zone - - # Pull the log meta and log data settings out of zone_info, if they - # exist, then pop them as they don't actually belong in the zone info - for key in ['rgw log meta', 'rgw log data']: - new_key = key.split(' ', 1)[1] - new_key = new_key.replace(' ', '_') - - if key in zone_info: - value = zone_info.pop(key) - else: - value = 'false' - - zone_payload[new_key] = value - - region_conf.setdefault('zones', []) - region_conf['zones'].append(zone_payload) - - -@contextlib.contextmanager -def configure_users_for_client(ctx, config, client, everywhere=False): - """ - Create users by remotely running rgwadmin commands using extracted - user information. - """ - log.info('Configuring users...') - log.info('for client %s', client) - log.info('everywhere %s', everywhere) - - # For data sync the master zones and regions must have the - # system users of the secondary zones. To keep this simple, - # just create the system users on every client if regions are - # configured. - clients_to_create_as = [client] - if everywhere: - clients_to_create_as = config.keys() - - # extract the user info and append it to the payload tuple for the given - # client - for client, c_config in config.iteritems(): - if not c_config: - continue - user_info = extract_user_info(c_config) - if not user_info: - continue - - for client_name in clients_to_create_as: - log.debug('Creating user {user} on {client}'.format( - user=user_info['system_key']['user'], client=client_name)) - rgwadmin(ctx, client_name, - cmd=[ - 'user', 'create', - '--uid', user_info['system_key']['user'], - '--access-key', user_info['system_key']['access_key'], - '--secret', user_info['system_key']['secret_key'], - '--display-name', user_info['system_key']['user'], - '--system', - ], - check_status=True, - ) - yield - -@contextlib.contextmanager -def configure_users(ctx, config, everywhere=False): - """ - Create users by remotely running rgwadmin commands using extracted - user information. - """ - log.info('Configuring users...') - - # extract the user info and append it to the payload tuple for the given - # client - for client, c_config in config.iteritems(): - if not c_config: - continue - user_info = extract_user_info(c_config) - if not user_info: - continue - - # For data sync the master zones and regions must have the - # system users of the secondary zones. To keep this simple, - # just create the system users on every client if regions are - # configured. - clients_to_create_as = [client] - if everywhere: - clients_to_create_as = config.keys() - for client_name in clients_to_create_as: - log.debug('Creating user {user} on {client}'.format( - user=user_info['system_key']['user'], client=client)) - rgwadmin(ctx, client_name, - cmd=[ - 'user', 'create', - '--uid', user_info['system_key']['user'], - '--access-key', user_info['system_key']['access_key'], - '--secret', user_info['system_key']['secret_key'], - '--display-name', user_info['system_key']['user'], - '--system', - ], - check_status=True, - ) - - yield - @contextlib.contextmanager -def create_nonregion_pools(ctx, config, regions): +def create_pools(ctx, config): """Create replicated or erasure coded data pools for rgw.""" - if regions: - yield - return - log.info('creating data pools') + log.info('Creating data pools') for client in config.keys(): (remote,) = ctx.cluster.only(client).remotes.iterkeys() data_pool = '.rgw.buckets' @@ -614,374 +147,28 @@ def create_nonregion_pools(ctx, config, regions): if ctx.rgw.cache_pools: create_cache_pool(remote, data_pool, data_pool + '.cache', 64, 64*1024*1024, cluster_name) + log.debug('Pools created') yield @contextlib.contextmanager -def configure_multisite_regions_and_zones(ctx, config, regions, role_endpoints, realm, master_client): - """ - Configure multisite regions and zones from rados and rgw. - """ - if not regions: - log.debug( - 'In rgw.configure_multisite_regions_and_zones() and regions is None. ' - 'Bailing') - yield - return - - if not realm: - log.debug( - 'In rgw.configure_multisite_regions_and_zones() and realm is None. ' - 'Bailing') - yield - return - - log.info('Configuring multisite regions and zones...') - - log.debug('config is %r', config) - log.debug('regions are %r', regions) - log.debug('role_endpoints = %r', role_endpoints) - log.debug('realm is %r', realm) - - # extract the zone info - role_zones = dict([(client, extract_zone_info(ctx, client, c_config)) - for client, c_config in config.iteritems()]) - log.debug('role_zones = %r', role_zones) - - # extract the user info and append it to the payload tuple for the given - # client +def configure_compression(ctx, config, compression): + """ set a compression type in the default zone placement """ + log.info('Configuring compression type = %s', compression) for client, c_config in config.iteritems(): - if not c_config: - user_info = None - else: - user_info = extract_user_info(c_config) - - (region, zone, zone_info) = role_zones[client] - role_zones[client] = (region, zone, zone_info, user_info) - - region_info = dict([ - (region_name, extract_region_info(region_name, r_config)) - for region_name, r_config in regions.iteritems()]) - - fill_in_endpoints(region_info, role_zones, role_endpoints) - - # clear out the old defaults - cluster_name, daemon_type, client_id = teuthology.split_role(master_client) - first_mon = teuthology.get_first_mon(ctx, config, cluster_name) - (mon,) = ctx.cluster.only(first_mon).remotes.iterkeys() - - # read master zonegroup and master_zone - for zonegroup, zg_info in region_info.iteritems(): - if zg_info['is_master']: - master_zonegroup = zonegroup - master_zone = zg_info['master_zone'] - break - - log.debug('master zonegroup =%r', master_zonegroup) - log.debug('master zone = %r', master_zone) - log.debug('master client = %r', master_client) - - rgwadmin(ctx, master_client, - cmd=['realm', 'create', '--rgw-realm', realm, '--default'], - check_status=True) - - for region, info in region_info.iteritems(): - region_json = json.dumps(info) - log.debug('region info is: %s', region_json) - rgwadmin(ctx, master_client, - cmd=['zonegroup', 'set'], - stdin=StringIO(region_json), - check_status=True) - - rgwadmin(ctx, master_client, - cmd=['zonegroup', 'default', '--rgw-zonegroup', master_zonegroup], - check_status=True) - - for role, (zonegroup, zone, zone_info, user_info) in role_zones.iteritems(): - (remote,) = ctx.cluster.only(role).remotes.keys() - for pool_info in zone_info['placement_pools']: - remote.run(args=['sudo', 'ceph', 'osd', 'pool', 'create', - pool_info['val']['index_pool'], '64', '64', '--cluster', cluster_name]) - if ctx.rgw.ec_data_pool: - create_ec_pool(remote, pool_info['val']['data_pool'], - zone, 64, ctx.rgw.erasure_code_profile, cluster_name) - else: - create_replicated_pool(remote, pool_info['val']['data_pool'], 64, cluster_name) - - (zonegroup, zone, zone_info, user_info) = role_zones[master_client] - zone_json = json.dumps(dict(zone_info.items() + user_info.items())) - log.debug("zone info is: %r", zone_json) - rgwadmin(ctx, master_client, - cmd=['zone', 'set', '--rgw-zonegroup', zonegroup, - '--rgw-zone', zone], - stdin=StringIO(zone_json), - check_status=True) - - rgwadmin(ctx, master_client, - cmd=['zone', 'default', '--rgw-zone', zone], - check_status=True) - - rgwadmin(ctx, master_client, - cmd=['period', 'update', '--commit'], - check_status=True) - - yield - -def configure_compression_in_default_zone(ctx, config): - ceph_config = ctx.ceph['ceph'].conf.get('global', {}) - ceph_config.update(ctx.ceph['ceph'].conf.get('client', {})) - for client, c_config in config.iteritems(): - ceph_config.update(ctx.ceph['ceph'].conf.get(client, {})) - key = 'rgw compression type' - if not key in ceph_config: - log.debug('No compression setting to enable') - break - compression = ceph_config[key] - log.debug('Configuring compression type = %s', compression) - # XXX: the 'default' zone and zonegroup aren't created until we run RGWRados::init_complete(). # issue a 'radosgw-admin user list' command to trigger this rgwadmin(ctx, client, cmd=['user', 'list'], check_status=True) rgwadmin(ctx, client, cmd=['zone', 'placement', 'modify', '--rgw-zone', 'default', - '--placement-id', 'default-placement', '--compression', compression], + '--placement-id', 'default-placement', + '--compression', compression], check_status=True) - break # only the first client - -@contextlib.contextmanager -def configure_regions_and_zones(ctx, config, regions, role_endpoints, realm): - """ - Configure regions and zones from rados and rgw. - """ - if not regions: - log.debug( - 'In rgw.configure_regions_and_zones() and regions is None. ' - 'Bailing') - configure_compression_in_default_zone(ctx, config) - yield - return - - if not realm: - log.debug( - 'In rgw.configure_regions_and_zones() and realm is None. ' - 'Bailing') - configure_compression_in_default_zone(ctx, config) - yield - return - - log.info('Configuring regions and zones...') - - log.debug('config is %r', config) - log.debug('regions are %r', regions) - log.debug('role_endpoints = %r', role_endpoints) - log.debug('realm is %r', realm) - - # extract the zone info - role_zones = dict([(client, extract_zone_info(ctx, client, c_config)) - for client, c_config in config.iteritems()]) - log.debug('roles_zones = %r', role_zones) - - # extract the user info and append it to the payload tuple for the given - # client - for client, c_config in config.iteritems(): - if not c_config: - user_info = None - else: - user_info = extract_user_info(c_config) - - (region, zone, zone_info) = role_zones[client] - role_zones[client] = (region, zone, zone_info, user_info) - - region_info = dict([ - (region_name, extract_region_info(region_name, r_config)) - for region_name, r_config in regions.iteritems()]) - - fill_in_endpoints(region_info, role_zones, role_endpoints) - - # clear out the old defaults - cluster_name, daemon_type, client_id = teuthology.split_role(client) - first_mon = teuthology.get_first_mon(ctx, config, cluster_name) - (mon,) = ctx.cluster.only(first_mon).remotes.iterkeys() - # removing these objects from .rgw.root and the per-zone root pools - # may or may not matter - rados(ctx, mon, - cmd=['-p', '.rgw.root', 'rm', 'region_info.default', '--cluster', cluster_name]) - rados(ctx, mon, - cmd=['-p', '.rgw.root', 'rm', 'zone_info.default', '--cluster', cluster_name]) - - # read master zonegroup and master_zone - for zonegroup, zg_info in region_info.iteritems(): - if zg_info['is_master']: - master_zonegroup = zonegroup - master_zone = zg_info['master_zone'] - break - - for client in config.iterkeys(): - (zonegroup, zone, zone_info, user_info) = role_zones[client] - if zonegroup == master_zonegroup and zone == master_zone: - master_client = client - break - - log.debug('master zonegroup =%r', master_zonegroup) - log.debug('master zone = %r', master_zone) - log.debug('master client = %r', master_client) - log.debug('config %r ', config) - - (ret, out)=rgwadmin(ctx, client, - cmd=['realm', 'create', '--rgw-realm', realm, '--default']) - log.debug('realm create ret %r exists %r', -ret, errno.EEXIST) - assert ret == 0 or ret != -errno.EEXIST - if ret is -errno.EEXIST: - log.debug('realm %r exists', realm) - - for client in config.iterkeys(): - for role, (zonegroup, zone, zone_info, user_info) in role_zones.iteritems(): - rados(ctx, mon, - cmd=['-p', zone_info['domain_root'], - 'rm', 'region_info.default', '--cluster', cluster_name]) - rados(ctx, mon, - cmd=['-p', zone_info['domain_root'], - 'rm', 'zone_info.default', '--cluster', cluster_name]) - - (remote,) = ctx.cluster.only(role).remotes.keys() - for pool_info in zone_info['placement_pools']: - remote.run(args=['sudo', 'ceph', 'osd', 'pool', 'create', - pool_info['val']['index_pool'], '64', '64', '--cluster', cluster_name]) - if ctx.rgw.ec_data_pool: - create_ec_pool(remote, pool_info['val']['data_pool'], - zone, 64, ctx.rgw.erasure_code_profile, cluster_name) - else: - create_replicated_pool( - remote, pool_info['val']['data_pool'], - 64, cluster_name) - zone_json = json.dumps(dict(zone_info.items() + user_info.items())) - log.debug('zone info is: %r', zone_json) - rgwadmin(ctx, client, - cmd=['zone', 'set', '--rgw-zonegroup', zonegroup, - '--rgw-zone', zone], - stdin=StringIO(zone_json), - check_status=True) - - for region, info in region_info.iteritems(): - region_json = json.dumps(info) - log.debug('region info is: %s', region_json) - rgwadmin(ctx, client, - cmd=['zonegroup', 'set'], - stdin=StringIO(region_json), - check_status=True) - if info['is_master']: - rgwadmin(ctx, client, - cmd=['zonegroup', 'default', '--rgw-zonegroup', master_zonegroup], - check_status=True) - - (zonegroup, zone, zone_info, user_info) = role_zones[client] - rgwadmin(ctx, client, - cmd=['zone', 'default', '--rgw-zone', zone], - check_status=True) - - #this used to take master_client, need to edit that accordingly - rgwadmin(ctx, client, - cmd=['period', 'update', '--commit'], - check_status=True) - - yield - -@contextlib.contextmanager -def pull_configuration(ctx, config, regions, role_endpoints, realm, master_client): - """ - Configure regions and zones from rados and rgw. - """ - if not regions: - log.debug( - 'In rgw.pull_confguration() and regions is None. ' - 'Bailing') - yield - return - - if not realm: - log.debug( - 'In rgw.pull_configuration() and realm is None. ' - 'Bailing') - yield - return - - log.info('Pulling configuration...') - - log.debug('config is %r', config) - log.debug('regions are %r', regions) - log.debug('role_endpoints = %r', role_endpoints) - log.debug('realm is %r', realm) - log.debug('master client = %r', master_client) - - # extract the zone info - role_zones = dict([(client, extract_zone_info(ctx, client, c_config)) - for client, c_config in config.iteritems()]) - log.debug('roles_zones = %r', role_zones) - - # extract the user info and append it to the payload tuple for the given - # client - for client, c_config in config.iteritems(): - if not c_config: - user_info = None - else: - user_info = extract_user_info(c_config) - - (region, zone, zone_info) = role_zones[client] - role_zones[client] = (region, zone, zone_info, user_info) - - region_info = dict([ - (region_name, extract_region_info(region_name, r_config)) - for region_name, r_config in regions.iteritems()]) - - fill_in_endpoints(region_info, role_zones, role_endpoints) - - for client in config.iterkeys(): - if client != master_client: - cluster_name, daemon_type, client_id = teuthology.split_role(client) - host, port = role_endpoints[master_client] - endpoint = 'http://{host}:{port}/'.format(host=host, port=port) - log.debug("endpoint: %s", endpoint) - rgwadmin(ctx, client, - cmd=['realm', 'pull', '--rgw-realm', realm, '--default', '--url', - endpoint, '--access_key', - user_info['system_key']['access_key'], '--secret', - user_info['system_key']['secret_key']], - check_status=True) - - (zonegroup, zone, zone_info, zone_user_info) = role_zones[client] - zone_json = json.dumps(dict(zone_info.items() + zone_user_info.items())) - log.debug("zone info is: %r", zone_json) - rgwadmin(ctx, client, - cmd=['zone', 'set', '--default', - '--rgw-zone', zone], - stdin=StringIO(zone_json), - check_status=True) - - rgwadmin(ctx, client, - cmd=['zonegroup', 'add', '--rgw-zonegroup', zonegroup, '--rgw-zone', zone], - check_status=True) - - rgwadmin(ctx, client, - cmd=['zonegroup', 'default', '--rgw-zonegroup', zonegroup], - check_status=True) - - rgwadmin(ctx, client, - cmd=['period', 'update', '--commit', '--url', - endpoint, '--access_key', - user_info['system_key']['access_key'], '--secret', - user_info['system_key']['secret_key']], - check_status=True) - yield @contextlib.contextmanager def task(ctx, config): """ - Either use configure apache to run a rados gateway, or use the built-in - civetweb server. - Only one should be run per machine, since it uses a hard-coded port for - now. - For example, to run rgw on all clients:: tasks: @@ -1002,14 +189,6 @@ def task(ctx, config): client.0: client.3: - You can adjust the idle timeout for fastcgi (default is 30 seconds): - - tasks: - - ceph: - - rgw: - client.0: - idle_timeout: 90 - To run radosgw through valgrind: tasks: @@ -1019,97 +198,6 @@ def task(ctx, config): valgrind: [--tool=memcheck] client.3: valgrind: [--tool=memcheck] - - To use civetweb instead of apache: - - tasks: - - ceph: - - rgw: - - client.0 - overrides: - rgw: - frontend: civetweb - - Note that without a modified fastcgi module e.g. with the default - one on CentOS, you must have rgw print continue = false in ceph.conf:: - - tasks: - - ceph: - conf: - global: - rgw print continue: false - - rgw: [client.0] - - To use mod_proxy_fcgi instead of mod_fastcgi: - - overrides: - rgw: - use_fcgi: true - - To run rgws for multiple regions or zones, describe the regions - and their zones in a regions section. The endpoints will be - generated by this task. Each client must have a region, zone, - and pools assigned in ceph.conf:: - - tasks: - - install: - - ceph: - conf: - client.0: - rgw region: foo - rgw zone: foo-1 - rgw region root pool: .rgw.rroot.foo - rgw zone root pool: .rgw.zroot.foo - rgw log meta: true - rgw log data: true - client.1: - rgw region: bar - rgw zone: bar-master - rgw region root pool: .rgw.rroot.bar - rgw zone root pool: .rgw.zroot.bar - rgw log meta: true - rgw log data: true - client.2: - rgw region: bar - rgw zone: bar-secondary - rgw region root pool: .rgw.rroot.bar - rgw zone root pool: .rgw.zroot.bar-secondary - - rgw: - default_idle_timeout: 30 - ec-data-pool: true - erasure_code_profile: - k: 2 - m: 1 - ruleset-failure-domain: osd - realm: foo - regions: - foo: - api name: api_name # default: region name - is master: true # default: false - master zone: foo-1 # default: first zone - zones: [foo-1] - log meta: true - log data: true - placement targets: [target1, target2] # default: [] - default placement: target2 # default: '' - bar: - api name: bar-api - zones: [bar-master, bar-secondary] - client.0: - system user: - name: foo-system - access key: X2IYPSTY1072DDY1SJMC - secret key: YIMHICpPvT+MhLTbSsiBJ1jQF15IFvJA8tgwJEcm - client.1: - system user: - name: bar1 - access key: Y2IYPSTY1072DDY1SJMC - secret key: XIMHICpPvT+MhLTbSsiBJ1jQF15IFvJA8tgwJEcm - client.2: - system user: - name: bar2 - access key: Z2IYPSTY1072DDY1SJMC - secret key: ZIMHICpPvT+MhLTbSsiBJ1jQF15IFvJA8tgwJEcm """ if config is None: config = dict(('client.{id}'.format(id=id_), None) @@ -1121,217 +209,28 @@ def task(ctx, config): overrides = ctx.config.get('overrides', {}) teuthology.deep_merge(config, overrides.get('rgw', {})) - regions = {} - if 'regions' in config: - # separate region info so only clients are keys in config - regions = config['regions'] - del config['regions'] - role_endpoints = assign_ports(ctx, config) ctx.rgw = argparse.Namespace() ctx.rgw.role_endpoints = role_endpoints - # stash the region info for later, since it was deleted from the config - # structure - ctx.rgw.regions = regions - - realm = None - if 'realm' in config: - # separate region info so only clients are keys in config - realm = config['realm'] - del config['realm'] - ctx.rgw.realm = realm - - ctx.rgw.ec_data_pool = False - if 'ec-data-pool' in config: - ctx.rgw.ec_data_pool = bool(config['ec-data-pool']) - del config['ec-data-pool'] - ctx.rgw.erasure_code_profile = {} - if 'erasure_code_profile' in config: - ctx.rgw.erasure_code_profile = config['erasure_code_profile'] - del config['erasure_code_profile'] - ctx.rgw.default_idle_timeout = 30 - if 'default_idle_timeout' in config: - ctx.rgw.default_idle_timeout = int(config['default_idle_timeout']) - del config['default_idle_timeout'] - ctx.rgw.cache_pools = False - if 'cache-pools' in config: - ctx.rgw.cache_pools = bool(config['cache-pools']) - del config['cache-pools'] - ctx.rgw.frontend = 'civetweb' - if 'frontend' in config: - ctx.rgw.frontend = config['frontend'] - del config['frontend'] - - ctx.rgw.use_fastcgi = True - if "use_fcgi" in config: - ctx.rgw.use_fastcgi = False - log.info("Using mod_proxy_fcgi instead of mod_fastcgi...") - del config['use_fcgi'] - - subtasks = [ - lambda: create_nonregion_pools( - ctx=ctx, config=config, regions=regions), - ] - log.debug('Nonregion pools created') - - multisite = len(regions) > 1 - - if not multisite: - for zonegroup, zonegroup_info in regions.iteritems(): - log.debug("zonegroup_info =%r", zonegroup_info) - if len(zonegroup_info['zones']) > 1: - multisite = True - break - - log.debug('multisite %s', multisite) - - multi_cluster = False - if multisite: - prev_cluster_name = None - roles = ctx.config['roles'] - #check if any roles have a different cluster_name from eachother - for lst in roles: - for role in lst: - cluster_name, daemon_type, client_id = teuthology.split_role(role) - if cluster_name != prev_cluster_name and prev_cluster_name != None: - multi_cluster = True - break - prev_cluster_name = cluster_name - if multi_cluster: - break - - log.debug('multi_cluster %s', multi_cluster) + ctx.rgw.ec_data_pool = bool(config.pop('ec-data-pool', False)) + ctx.rgw.erasure_code_profile = config.pop('erasure_code_profile', {}) + ctx.rgw.cache_pools = bool(config.pop('cache-pools', False)) + ctx.rgw.frontend = config.pop('frontend', 'civetweb') + ctx.rgw.compression_type = config.pop('compression type', None) ctx.rgw.config = config - master_client = None - - if multi_cluster: - log.debug('multi cluster run') - - master_client = get_config_master_client(ctx=ctx, - config=config, - regions=regions) - log.debug('master_client %r', master_client) - subtasks.extend([ - lambda: configure_multisite_regions_and_zones( - ctx=ctx, - config=config, - regions=regions, - role_endpoints=role_endpoints, - realm=realm, - master_client = master_client, - ) - ]) - - subtasks.extend([ - lambda: configure_users_for_client( - ctx=ctx, - config=config, - client=master_client, - everywhere=False, - ), - ]) - if ctx.rgw.frontend == 'apache': - subtasks.insert(0, - lambda: create_apache_dirs(ctx=ctx, config=config, - on_client=master_client)) - subtasks.extend([ - lambda: ship_apache_configs(ctx=ctx, config=config, - role_endpoints=role_endpoints, on_client=master_client), - lambda: start_apache(ctx=ctx, config=config, on_client=master_client), - lambda: start_rgw(ctx=ctx, config=config, on_client=master_client), - ]) - elif ctx.rgw.frontend == 'civetweb': - subtasks.extend([ - lambda: start_rgw(ctx=ctx, config=config, on_client=master_client), - ]) - else: - raise ValueError("frontend must be 'apache' or 'civetweb'") - - subtasks.extend([ - lambda: pull_configuration(ctx=ctx, - config=config, - regions=regions, - role_endpoints=role_endpoints, - realm=realm, - master_client=master_client - ), - ]) - - subtasks.extend([ - lambda: configure_users_for_client( - ctx=ctx, - config=config, - client=master_client, - everywhere=True - ), - ]) - - if ctx.rgw.frontend == 'apache': - subtasks.insert(0, - lambda: create_apache_dirs(ctx=ctx, config=config, - on_client=None, - except_client = master_client)) - subtasks.extend([ - lambda: ship_apache_configs(ctx=ctx, config=config, - role_endpoints=role_endpoints, - on_client=None, - except_client = master_client, - ), - lambda: start_apache(ctx=ctx, - config = config, - on_client=None, - except_client = master_client, - ), - lambda: start_rgw(ctx=ctx, - config=config, - on_client=None, - except_client = master_client), - ]) - elif ctx.rgw.frontend == 'civetweb': - subtasks.extend([ - lambda: start_rgw(ctx=ctx, - config=config, - on_client=None, - except_client = master_client), - ]) - else: - raise ValueError("frontend must be 'apache' or 'civetweb'") - - else: - log.debug('single cluster run') + subtasks = [ + lambda: create_pools(ctx=ctx, config=config), + ] + if ctx.rgw.compression_type: subtasks.extend([ - lambda: configure_regions_and_zones( - ctx=ctx, - config=config, - regions=regions, - role_endpoints=role_endpoints, - realm=realm, - ), - lambda: configure_users( - ctx=ctx, - config=config, - everywhere=True, - ), + lambda: configure_compression(ctx=ctx, config=config, + compression=ctx.rgw.compression_type), ]) - if ctx.rgw.frontend == 'apache': - subtasks.insert(0, lambda: create_apache_dirs(ctx=ctx, config=config)) - subtasks.extend([ - lambda: ship_apache_configs(ctx=ctx, config=config, - role_endpoints=role_endpoints), - lambda: start_apache(ctx=ctx, config=config), - lambda: start_rgw(ctx=ctx, - config=config), - ]) - elif ctx.rgw.frontend == 'civetweb': - subtasks.extend([ - lambda: start_rgw(ctx=ctx, - config=config), - ]) - else: - raise ValueError("frontend must be 'apache' or 'civetweb'") + subtasks.extend([ + lambda: start_rgw(ctx=ctx, config=config), + ]) - log.info("Using %s as radosgw frontend", ctx.rgw.frontend) with contextutil.nested(*subtasks): yield diff --git a/ceph/qa/tasks/rgw_multi b/ceph/qa/tasks/rgw_multi new file mode 120000 index 000000000..abfc703b9 --- /dev/null +++ b/ceph/qa/tasks/rgw_multi @@ -0,0 +1 @@ +../../src/test/rgw/rgw_multi \ No newline at end of file diff --git a/ceph/qa/tasks/rgw_multisite.py b/ceph/qa/tasks/rgw_multisite.py new file mode 100644 index 000000000..cd120c441 --- /dev/null +++ b/ceph/qa/tasks/rgw_multisite.py @@ -0,0 +1,427 @@ +""" +rgw multisite configuration routines +""" +import argparse +import contextlib +import logging +import random +import string +from copy import deepcopy +from util.rgw import rgwadmin, wait_for_radosgw +from util.rados import create_ec_pool, create_replicated_pool +from rgw_multi import multisite +from rgw_multi.zone_rados import RadosZone as RadosZone + +from teuthology.orchestra import run +from teuthology import misc +from teuthology.exceptions import ConfigError +from teuthology.task import Task + +log = logging.getLogger(__name__) + +class RGWMultisite(Task): + """ + Performs rgw multisite configuration to match the given realm definition. + + - rgw-multisite: + realm: + name: test-realm + is_default: true + + List one or more zonegroup definitions. These are provided as json + input to `radosgw-admin zonegroup set`, with the exception of these keys: + + * 'is_master' is passed on the command line as --master + * 'is_default' is passed on the command line as --default + * 'endpoints' given as client names are replaced with actual endpoints + + zonegroups: + - name: test-zonegroup + api_name: test-api + is_master: true + is_default: true + endpoints: [c1.client.0] + + List each of the zones to be created in this zonegroup. + + zones: + - name: test-zone1 + is_master: true + is_default: true + endpoints: [c1.client.0] + - name: test-zone2 + is_default: true + endpoints: [c2.client.0] + + A complete example: + + tasks: + - install: + - ceph: {cluster: c1} + - ceph: {cluster: c2} + - rgw: + c1.client.0: + c2.client.0: + - rgw-multisite: + realm: + name: test-realm + is_default: true + zonegroups: + - name: test-zonegroup + is_master: true + is_default: true + zones: + - name: test-zone1 + is_master: true + is_default: true + endpoints: [c1.client.0] + - name: test-zone2 + is_default: true + endpoints: [c2.client.0] + + """ + def __init__(self, ctx, config): + super(RGWMultisite, self).__init__(ctx, config) + + def setup(self): + super(RGWMultisite, self).setup() + + overrides = self.ctx.config.get('overrides', {}) + misc.deep_merge(self.config, overrides.get('rgw-multisite', {})) + + if not self.ctx.rgw: + raise ConfigError('rgw-multisite must run after the rgw task') + role_endpoints = self.ctx.rgw.role_endpoints + + # construct Clusters and Gateways for each client in the rgw task + clusters, gateways = extract_clusters_and_gateways(self.ctx, + role_endpoints) + + # get the master zone and zonegroup configuration + mz, mzg = extract_master_zone_zonegroup(self.config['zonegroups']) + cluster1 = cluster_for_zone(clusters, mz) + + # create the realm and period on the master zone's cluster + log.info('creating realm..') + realm = create_realm(cluster1, self.config['realm']) + period = realm.current_period + + creds = gen_credentials() + + # create the master zonegroup and its master zone + log.info('creating master zonegroup..') + master_zonegroup = create_zonegroup(cluster1, gateways, period, + deepcopy(mzg)) + period.master_zonegroup = master_zonegroup + + log.info('creating master zone..') + master_zone = create_zone(self.ctx, cluster1, gateways, creds, + master_zonegroup, deepcopy(mz)) + master_zonegroup.master_zone = master_zone + + period.update(master_zone, commit=True) + restart_zone_gateways(master_zone) # restart with --rgw-zone + + # create the admin user on the master zone + log.info('creating admin user..') + user_args = ['--display-name', 'Realm Admin', '--system'] + user_args += creds.credential_args() + admin_user = multisite.User('realm-admin') + admin_user.create(master_zone, user_args) + + # process 'zonegroups' + for zg_config in self.config['zonegroups']: + zones_config = zg_config.pop('zones') + + zonegroup = None + for zone_config in zones_config: + # get the cluster for this zone + cluster = cluster_for_zone(clusters, zone_config) + + if cluster != cluster1: # already created on master cluster + log.info('pulling realm configuration to %s', cluster.name) + realm.pull(cluster, master_zone.gateways[0], creds) + + # use the first zone's cluster to create the zonegroup + if not zonegroup: + if zg_config['name'] == master_zonegroup.name: + zonegroup = master_zonegroup + else: + log.info('creating zonegroup..') + zonegroup = create_zonegroup(cluster, gateways, + period, zg_config) + + if zone_config['name'] == master_zone.name: + # master zone was already created + zone = master_zone + else: + # create the zone and commit the period + log.info('creating zone..') + zone = create_zone(self.ctx, cluster, gateways, creds, + zonegroup, zone_config) + period.update(zone, commit=True) + + restart_zone_gateways(zone) # restart with --rgw-zone + + # attach configuration to the ctx for other tasks + self.ctx.rgw_multisite = argparse.Namespace() + self.ctx.rgw_multisite.clusters = clusters + self.ctx.rgw_multisite.gateways = gateways + self.ctx.rgw_multisite.realm = realm + self.ctx.rgw_multisite.admin_user = admin_user + + log.info('rgw multisite configuration completed') + + def end(self): + del self.ctx.rgw_multisite + +class Cluster(multisite.Cluster): + """ Issues 'radosgw-admin' commands with the rgwadmin() helper """ + def __init__(self, ctx, name, client): + super(Cluster, self).__init__() + self.ctx = ctx + self.name = name + self.client = client + + def admin(self, args = None, **kwargs): + """ radosgw-admin command """ + args = args or [] + args += ['--cluster', self.name] + args += ['--debug-rgw', '0'] + if kwargs.pop('read_only', False): + args += ['--rgw-cache-enabled', 'false'] + kwargs['decode'] = False + check_retcode = kwargs.pop('check_retcode', True) + r, s = rgwadmin(self.ctx, self.client, args, **kwargs) + if check_retcode: + assert r == 0 + return s, r + +class Gateway(multisite.Gateway): + """ Controls a radosgw instance using its daemon """ + def __init__(self, role, remote, daemon, *args, **kwargs): + super(Gateway, self).__init__(*args, **kwargs) + self.role = role + self.remote = remote + self.daemon = daemon + + def set_zone(self, zone): + """ set the zone and add its args to the daemon's command line """ + assert self.zone is None, 'zone can only be set once' + self.zone = zone + # daemon.restart_with_args() would be perfect for this, except that + # radosgw args likely include a pipe and redirect. zone arguments at + # the end won't actually apply to radosgw + args = self.daemon.command_kwargs.get('args', []) + try: + # insert zone args before the first | + pipe = args.index(run.Raw('|')) + args = args[0:pipe] + zone.zone_args() + args[pipe:] + except ValueError, e: + args += zone.zone_args() + self.daemon.command_kwargs['args'] = args + + def start(self, args = None): + """ (re)start the daemon """ + self.daemon.restart() + # wait until startup completes + wait_for_radosgw(self.endpoint()) + + def stop(self): + """ stop the daemon """ + self.daemon.stop() + +def extract_clusters_and_gateways(ctx, role_endpoints): + """ create cluster and gateway instances for all of the radosgw roles """ + clusters = {} + gateways = {} + for role, (host, port) in role_endpoints.iteritems(): + cluster_name, daemon_type, client_id = misc.split_role(role) + # find or create the cluster by name + cluster = clusters.get(cluster_name) + if not cluster: + clusters[cluster_name] = cluster = Cluster(ctx, cluster_name, role) + # create a gateway for this daemon + client_with_id = daemon_type + '.' + client_id # match format from rgw.py + daemon = ctx.daemons.get_daemon('rgw', client_with_id, cluster_name) + if not daemon: + raise ConfigError('no daemon for role=%s cluster=%s type=rgw id=%s' % \ + (role, cluster_name, client_id)) + (remote,) = ctx.cluster.only(role).remotes.keys() + gateways[role] = Gateway(role, remote, daemon, host, port, cluster) + return clusters, gateways + +def create_realm(cluster, config): + """ create a realm from configuration and initialize its first period """ + realm = multisite.Realm(config['name']) + args = [] + if config.get('is_default', False): + args += ['--default'] + realm.create(cluster, args) + realm.current_period = multisite.Period(realm) + return realm + +def extract_user_credentials(config): + """ extract keys from configuration """ + return multisite.Credentials(config['access_key'], config['secret_key']) + +def extract_master_zone(zonegroup_config): + """ find and return the master zone definition """ + master = None + for zone in zonegroup_config['zones']: + if not zone.get('is_master', False): + continue + if master: + raise ConfigError('zones %s and %s cannot both set \'is_master\'' % \ + (master['name'], zone['name'])) + master = zone + # continue the loop so we can detect duplicates + if not master: + raise ConfigError('one zone must set \'is_master\' in zonegroup %s' % \ + zonegroup_config['name']) + return master + +def extract_master_zone_zonegroup(zonegroups_config): + """ find and return the master zone and zonegroup definitions """ + master_zone, master_zonegroup = (None, None) + for zonegroup in zonegroups_config: + # verify that all zonegroups have a master zone set, even if they + # aren't in the master zonegroup + zone = extract_master_zone(zonegroup) + if not zonegroup.get('is_master', False): + continue + if master_zonegroup: + raise ConfigError('zonegroups %s and %s cannot both set \'is_master\'' % \ + (master_zonegroup['name'], zonegroup['name'])) + master_zonegroup = zonegroup + master_zone = zone + # continue the loop so we can detect duplicates + if not master_zonegroup: + raise ConfigError('one zonegroup must set \'is_master\'') + return master_zone, master_zonegroup + +def extract_zone_cluster_name(zone_config): + """ return the cluster (must be common to all zone endpoints) """ + cluster_name = None + endpoints = zone_config.get('endpoints') + if not endpoints: + raise ConfigError('zone %s missing \'endpoints\' list' % \ + zone_config['name']) + for role in endpoints: + name, _, _ = misc.split_role(role) + if not cluster_name: + cluster_name = name + elif cluster_name != name: + raise ConfigError('all zone %s endpoints must be in the same cluster' % \ + zone_config['name']) + return cluster_name + +def cluster_for_zone(clusters, zone_config): + """ return the cluster entry for the given zone """ + name = extract_zone_cluster_name(zone_config) + try: + return clusters[name] + except KeyError: + raise ConfigError('no cluster %s found' % name) + +def gen_access_key(): + return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)) + +def gen_secret(): + return ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(32)) + +def gen_credentials(): + return multisite.Credentials(gen_access_key(), gen_secret()) + +def extract_gateway_endpoints(gateways, endpoints_config): + """ return a list of gateway endpoints associated with the given roles """ + endpoints = [] + for role in endpoints_config: + try: + # replace role names with their gateway's endpoint + endpoints.append(gateways[role].endpoint()) + except KeyError: + raise ConfigError('no radosgw endpoint found for role %s' % role) + return endpoints + +def is_default_arg(config): + return ['--default'] if config.pop('is_default', False) else [] + +def is_master_arg(config): + return ['--master'] if config.pop('is_master', False) else [] + +def create_zonegroup(cluster, gateways, period, config): + """ pass the zonegroup configuration to `zonegroup set` """ + config.pop('zones', None) # remove 'zones' from input to `zonegroup set` + endpoints = config.get('endpoints') + if endpoints: + # replace client names with their gateway endpoints + config['endpoints'] = extract_gateway_endpoints(gateways, endpoints) + zonegroup = multisite.ZoneGroup(config['name'], period) + # `zonegroup set` needs --default on command line, and 'is_master' in json + args = is_default_arg(config) + zonegroup.set(cluster, config, args) + period.zonegroups.append(zonegroup) + return zonegroup + +def create_zone(ctx, cluster, gateways, creds, zonegroup, config): + """ create a zone with the given configuration """ + zone = multisite.Zone(config['name'], zonegroup, cluster) + zone = RadosZone(config['name'], zonegroup, cluster) + + # collect Gateways for the zone's endpoints + endpoints = config.get('endpoints') + if not endpoints: + raise ConfigError('no \'endpoints\' for zone %s' % config['name']) + zone.gateways = [gateways[role] for role in endpoints] + for gateway in zone.gateways: + gateway.set_zone(zone) + + # format the gateway endpoints + endpoints = [g.endpoint() for g in zone.gateways] + + args = is_default_arg(config) + args += is_master_arg(config) + args += creds.credential_args() + if len(endpoints): + args += ['--endpoints', ','.join(endpoints)] + zone.create(cluster, args) + zonegroup.zones.append(zone) + + create_zone_pools(ctx, zone) + if ctx.rgw.compression_type: + configure_zone_compression(zone, ctx.rgw.compression_type) + + zonegroup.zones_by_type.setdefault(zone.tier_type(), []).append(zone) + + if zone.is_read_only(): + zonegroup.ro_zones.append(zone) + else: + zonegroup.rw_zones.append(zone) + + return zone + +def create_zone_pools(ctx, zone): + """ Create the data_pool for each placement type """ + gateway = zone.gateways[0] + cluster = zone.cluster + for pool_config in zone.data.get('placement_pools', []): + pool_name = pool_config['val']['data_pool'] + if ctx.rgw.ec_data_pool: + create_ec_pool(gateway.remote, pool_name, zone.name, 64, + ctx.rgw.erasure_code_profile, cluster.name) + else: + create_replicated_pool(gateway.remote, pool_name, 64, cluster.name) + +def configure_zone_compression(zone, compression): + """ Set compression type in the zone's default-placement """ + zone.json_command(zone.cluster, 'placement', ['modify', + '--placement-id', 'default-placement', + '--compression', compression + ]) + +def restart_zone_gateways(zone): + zone.stop() + zone.start() + +task = RGWMultisite diff --git a/ceph/qa/tasks/rgw_multisite_tests.py b/ceph/qa/tasks/rgw_multisite_tests.py new file mode 100644 index 000000000..4e6e2b3df --- /dev/null +++ b/ceph/qa/tasks/rgw_multisite_tests.py @@ -0,0 +1,91 @@ +""" +rgw multisite testing +""" +import logging +import sys +import nose.core +import nose.config + +from teuthology.exceptions import ConfigError +from teuthology.task import Task +from teuthology import misc + +from rgw_multi import multisite, tests + +log = logging.getLogger(__name__) + +class RGWMultisiteTests(Task): + """ + Runs the rgw_multi tests against a multisite configuration created by the + rgw-multisite task. Tests are run with nose, using any additional 'args' + provided. Overrides for tests.Config can be set in 'config'. + + - rgw-multisite-tests: + args: + - tasks.rgw_multi.tests:test_object_sync + config: + reconfigure_delay: 60 + + """ + def __init__(self, ctx, config): + super(RGWMultisiteTests, self).__init__(ctx, config) + + def setup(self): + super(RGWMultisiteTests, self).setup() + + overrides = self.ctx.config.get('overrides', {}) + misc.deep_merge(self.config, overrides.get('rgw-multisite-tests', {})) + + if not self.ctx.rgw_multisite: + raise ConfigError('rgw-multisite-tests must run after the rgw-multisite task') + realm = self.ctx.rgw_multisite.realm + master_zone = realm.meta_master_zone() + + # create the test user + log.info('creating test user..') + user = multisite.User('rgw-multisite-test-user') + user.create(master_zone, ['--display-name', 'Multisite Test User', + '--gen-access-key', '--gen-secret']) + + config = self.config.get('config', {}) + tests.init_multi(realm, user, tests.Config(**config)) + tests.realm_meta_checkpoint(realm) + + def begin(self): + # extra arguments for nose can be passed as a string or list + extra_args = self.config.get('args', []) + if not isinstance(extra_args, list): + extra_args = [extra_args] + argv = [__name__] + extra_args + + log.info("running rgw multisite tests on '%s' with args=%r", + tests.__name__, extra_args) + + # run nose tests in the rgw_multi.tests module + conf = nose.config.Config(stream=get_log_stream(), verbosity=2) + result = nose.run(defaultTest=tests.__name__, argv=argv, config=conf) + if not result: + raise RuntimeError('rgw multisite test failures') + +def get_log_stream(): + """ return a log stream for nose output """ + # XXX: this is a workaround for IOErrors when nose writes to stderr, + # copied from vstart_runner.py + class LogStream(object): + def __init__(self): + self.buffer = "" + + def write(self, data): + self.buffer += data + if "\n" in self.buffer: + lines = self.buffer.split("\n") + for line in lines[:-1]: + log.info(line) + self.buffer = lines[-1] + + def flush(self): + pass + + return LogStream() + +task = RGWMultisiteTests diff --git a/ceph/qa/tasks/s3tests.py b/ceph/qa/tasks/s3tests.py index 762eff267..ee16381d1 100644 --- a/ceph/qa/tasks/s3tests.py +++ b/ceph/qa/tasks/s3tests.py @@ -10,8 +10,6 @@ import os import random import string -import util.rgw as rgw_utils - from teuthology import misc as teuthology from teuthology import contextutil from teuthology.config import config as teuth_config @@ -20,99 +18,6 @@ from teuthology.orchestra.connection import split_user log = logging.getLogger(__name__) -def extract_sync_client_data(ctx, client_name): - """ - Extract synchronized client rgw zone and rgw region information. - - :param ctx: Context passed to the s3tests task - :param name: Name of client that we are synching with - """ - return_region_name = None - return_dict = None - cluster_name, daemon_type, client_id = teuthology.split_role(client_name) - client = ctx.ceph[cluster_name].conf.get(client_name, None) - if client: - current_client_zone = client.get('rgw zone', None) - if current_client_zone: - (endpoint_host, endpoint_port) = ctx.rgw.role_endpoints.get(client_name, (None, None)) - # pull out the radosgw_agent stuff - regions = ctx.rgw.regions - for region in regions: - log.debug('jbuck, region is {region}'.format(region=region)) - region_data = ctx.rgw.regions[region] - log.debug('region data is {region}'.format(region=region_data)) - zones = region_data['zones'] - for zone in zones: - if current_client_zone in zone: - return_region_name = region - return_dict = dict() - return_dict['api_name'] = region_data['api name'] - return_dict['is_master'] = region_data['is master'] - return_dict['port'] = endpoint_port - return_dict['host'] = endpoint_host - - # The s3tests expect the sync_agent_[addr|port} to be - # set on the non-master node for some reason - if not region_data['is master']: - (rgwagent_host, rgwagent_port) = ctx.radosgw_agent.endpoint - (return_dict['sync_agent_addr'], _) = ctx.rgw.role_endpoints[rgwagent_host] - return_dict['sync_agent_port'] = rgwagent_port - - else: #if client_zone: - log.debug('No zone info for {host}'.format(host=client_name)) - else: # if client - log.debug('No ceph conf for {host}'.format(host=client_name)) - - return return_region_name, return_dict - -def update_conf_with_region_info(ctx, config, s3tests_conf): - """ - Scan for a client (passed in s3tests_conf) that is an s3agent - with which we can sync. Update information in local conf file - if such a client is found. - """ - for key in s3tests_conf.keys(): - # we'll assume that there's only one sync relationship (source / destination) with client.X - # as the key for now - - # Iterate through all of the radosgw_agent (rgwa) configs and see if a - # given client is involved in a relationship. - # If a given client isn't, skip it - this_client_in_rgwa_config = False - for rgwa in ctx.radosgw_agent.config.keys(): - rgwa_data = ctx.radosgw_agent.config[rgwa] - - if key in rgwa_data['src'] or key in rgwa_data['dest']: - this_client_in_rgwa_config = True - log.debug('{client} is in an radosgw-agent sync relationship'.format(client=key)) - radosgw_sync_data = ctx.radosgw_agent.config[key] - break - if not this_client_in_rgwa_config: - log.debug('{client} is NOT in an radosgw-agent sync relationship'.format(client=key)) - continue - - source_client = radosgw_sync_data['src'] - dest_client = radosgw_sync_data['dest'] - - # #xtract the pertinent info for the source side - source_region_name, source_region_dict = extract_sync_client_data(ctx, source_client) - log.debug('\t{key} source_region {source_region} source_dict {source_dict}'.format - (key=key,source_region=source_region_name,source_dict=source_region_dict)) - - # The source *should* be the master region, but test anyway and then set it as the default region - if source_region_dict['is_master']: - log.debug('Setting {region} as default_region'.format(region=source_region_name)) - s3tests_conf[key]['fixtures'].setdefault('default_region', source_region_name) - - # Extract the pertinent info for the destination side - dest_region_name, dest_region_dict = extract_sync_client_data(ctx, dest_client) - log.debug('\t{key} dest_region {dest_region} dest_dict {dest_dict}'.format - (key=key,dest_region=dest_region_name,dest_dict=dest_region_dict)) - - # now add these regions to the s3tests_conf object - s3tests_conf[key]['region {region_name}'.format(region_name=source_region_name)] = source_region_dict - s3tests_conf[key]['region {region_name}'.format(region_name=dest_region_name)] = dest_region_dict - @contextlib.contextmanager def download(ctx, config): """ @@ -141,11 +46,12 @@ def download(ctx, config): else: log.info("Using branch '%s' for s3tests", branch) sha1 = cconf.get('sha1') + git_remote = cconf.get('git_remote', None) or teuth_config.ceph_git_base_url ctx.cluster.only(client).run( args=[ 'git', 'clone', '-b', branch, - teuth_config.ceph_git_base_url + 's3-tests.git', + git_remote + 's3-tests.git', '{tdir}/s3-tests'.format(tdir=testdir), ], ) @@ -192,7 +98,7 @@ def create_users(ctx, config): assert isinstance(config, dict) log.info('Creating rgw users...') testdir = teuthology.get_testdir(ctx) - users = {'s3 main': 'foo', 's3 alt': 'bar'} + users = {'s3 main': 'foo', 's3 alt': 'bar', 's3 tenant': 'testx$tenanteduser'} for client in config['clients']: s3tests_conf = config['s3tests_conf'][client] s3tests_conf.setdefault('fixtures', {}) @@ -312,21 +218,6 @@ def configure(ctx, config): ], ) -@contextlib.contextmanager -def sync_users(ctx, config): - """ - Sync this user. - """ - assert isinstance(config, dict) - # do a full sync if this is a multi-region test - if rgw_utils.multi_region_enabled(ctx): - log.debug('Doing a full sync') - rgw_utils.radosgw_agent_sync_all(ctx) - else: - log.debug('Not a multi-region config; skipping the metadata sync') - - yield - @contextlib.contextmanager def run_tests(ctx, config): """ @@ -338,8 +229,6 @@ def run_tests(ctx, config): assert isinstance(config, dict) testdir = teuthology.get_testdir(ctx) attrs = ["!fails_on_rgw"] - if not ctx.rgw.use_fastcgi: - attrs.append("!fails_on_mod_proxy_fcgi") for client, client_config in config.iteritems(): args = [ 'S3TEST_CONF={tdir}/archive/s3-tests.{client}.conf'.format(tdir=testdir, client=client), @@ -476,20 +365,16 @@ def task(ctx, config): 'fixtures' : {}, 's3 main' : {}, 's3 alt' : {}, + 's3 tenant': {}, } ) - # Only attempt to add in the region info if there's a radosgw_agent configured - if hasattr(ctx, 'radosgw_agent'): - update_conf_with_region_info(ctx, config, s3tests_conf) - with contextutil.nested( lambda: download(ctx=ctx, config=config), lambda: create_users(ctx=ctx, config=dict( clients=clients, s3tests_conf=s3tests_conf, )), - lambda: sync_users(ctx=ctx, config=config), lambda: configure(ctx=ctx, config=dict( clients=config, s3tests_conf=s3tests_conf, diff --git a/ceph/qa/tasks/scrub_test.py b/ceph/qa/tasks/scrub_test.py index 2c22bb6e4..a545c9b89 100644 --- a/ceph/qa/tasks/scrub_test.py +++ b/ceph/qa/tasks/scrub_test.py @@ -375,8 +375,7 @@ def task(ctx, config): for i in range(num_osds): manager.raw_cluster_cmd('tell', 'osd.%d' % i, 'injectargs', '--', '--osd-objectstore-fuse') - for i in range(num_osds): - manager.raw_cluster_cmd('tell', 'osd.%d' % i, 'flush_pg_stats') + manager.flush_pg_stats(range(num_osds)) manager.wait_for_clean() # write some data diff --git a/ceph/qa/tasks/thrashosds.py b/ceph/qa/tasks/thrashosds.py index 29fefbc06..2cd98145e 100644 --- a/ceph/qa/tasks/thrashosds.py +++ b/ceph/qa/tasks/thrashosds.py @@ -197,4 +197,6 @@ def task(ctx, config): finally: log.info('joining thrashosds') thrash_proc.do_join() + cluster_manager.wait_for_all_up() + cluster_manager.flush_all_pg_stats() cluster_manager.wait_for_recovery(config.get('timeout', 360)) diff --git a/ceph/qa/tasks/util/rgw.py b/ceph/qa/tasks/util/rgw.py index 0cdb769b0..ab76b50a2 100644 --- a/ceph/qa/tasks/util/rgw.py +++ b/ceph/qa/tasks/util/rgw.py @@ -2,6 +2,8 @@ from cStringIO import StringIO import logging import json import requests + +from requests.packages.urllib3 import PoolManager from requests.packages.urllib3.util import Retry from urlparse import urlparse @@ -10,13 +12,8 @@ from teuthology import misc as teuthology log = logging.getLogger(__name__) -def multi_region_enabled(ctx): - # this is populated by the radosgw-agent task, seems reasonable to - # use that as an indicator that we're testing multi-region sync - return 'radosgw_agent' in ctx - def rgwadmin(ctx, client, cmd, stdin=StringIO(), check_status=False, - format='json'): + format='json', decode=True, log_level=logging.DEBUG): log.info('rgwadmin: {client} : {cmd}'.format(client=client,cmd=cmd)) testdir = teuthology.get_testdir(ctx) cluster_name, daemon_type, client_id = teuthology.split_role(client) @@ -32,7 +29,7 @@ def rgwadmin(ctx, client, cmd, stdin=StringIO(), check_status=False, '--cluster', cluster_name, ] pre.extend(cmd) - log.info('rgwadmin: cmd=%s' % pre) + log.log(log_level, 'rgwadmin: cmd=%s' % pre) (remote,) = ctx.cluster.only(client).remotes.iterkeys() proc = remote.run( args=pre, @@ -43,14 +40,16 @@ def rgwadmin(ctx, client, cmd, stdin=StringIO(), check_status=False, ) r = proc.exitstatus out = proc.stdout.getvalue() + if not decode: + return (r, out) j = None if not r and out != '': try: j = json.loads(out) - log.info(' json result: %s' % j) + log.log(log_level, ' json result: %s' % j) except ValueError: j = out - log.info(' raw result: %s' % j) + log.log(log_level, ' raw result: %s' % j) return (r, j) def get_user_summary(out, user): @@ -71,234 +70,12 @@ def get_user_successful_ops(out, user): return 0 return get_user_summary(out, user)['total']['successful_ops'] -def get_zone_host_and_port(ctx, client, zone): - cluster_name, daemon_type, client_id = teuthology.split_role(client) - client_with_id = daemon_type + '.' + client_id - _, period = rgwadmin(ctx, client, check_status=True, - cmd=['period', 'get']) - period_map = period['period_map'] - zonegroups = period_map['zonegroups'] - for zonegroup in zonegroups: - for zone_info in zonegroup['zones']: - if zone_info['name'] == zone: - endpoint = urlparse(zone_info['endpoints'][0]) - host, port = endpoint.hostname, endpoint.port - if port is None: - port = 80 - return host, port - assert False, 'no endpoint for zone {zone} found'.format(zone=zone) - -def get_master_zone(ctx, client): - cluster_name, daemon_type, client_id = teuthology.split_role(client) - client_with_id = daemon_type + '.' + client_id - _, period = rgwadmin(ctx, client, check_status=True, - cmd=['period', 'get']) - period_map = period['period_map'] - zonegroups = period_map['zonegroups'] - for zonegroup in zonegroups: - is_master = (zonegroup['is_master'] == "true") - log.info('zonegroup={z} is_master={ism}'.format(z=zonegroup, ism=is_master)) - if not is_master: - continue - master_zone = zonegroup['master_zone'] - log.info('master_zone=%s' % master_zone) - for zone_info in zonegroup['zones']: - if zone_info['name'] == master_zone: - return master_zone - log.info('couldn\'t find master zone') - return None - -def get_master_client(ctx, clients): - master_zone = get_master_zone(ctx, clients[0]) # can use any client for this as long as system configured correctly - if not master_zone: - return None - - for client in clients: - zone = zone_for_client(ctx, client) - if zone == master_zone: - return client - - return None - -def get_zone_system_keys(ctx, client, zone): - _, zone_info = rgwadmin(ctx, client, check_status=True, - cmd=['zone', 'get', '--rgw-zone', zone]) - system_key = zone_info['system_key'] - return system_key['access_key'], system_key['secret_key'] - -def zone_for_client(ctx, client): - cluster_name, daemon_type, client_id = teuthology.split_role(client) - ceph_config = ctx.ceph[cluster_name].conf.get('global', {}) - ceph_config.update(ctx.ceph[cluster_name].conf.get('client', {})) - ceph_config.update(ctx.ceph[cluster_name].conf.get(client, {})) - return ceph_config.get('rgw zone') - -def region_for_client(ctx, client): - cluster_name, daemon_type, client_id = teuthology.split_role(client) - ceph_config = ctx.ceph[cluster_name].conf.get('global', {}) - ceph_config.update(ctx.ceph[cluster_name].conf.get('client', {})) - ceph_config.update(ctx.ceph[cluster_name].conf.get(client, {})) - return ceph_config.get('rgw region') - -def radosgw_data_log_window(ctx, client): - cluster_name, daemon_type, client_id = teuthology.split_role(client) - ceph_config = ctx.ceph[cluster_name].conf.get('global', {}) - ceph_config.update(ctx.ceph[cluster_name].conf.get('client', {})) - ceph_config.update(ctx.ceph[cluster_name].conf.get(client, {})) - return ceph_config.get('rgw data log window', 30) - -def radosgw_agent_sync_data(ctx, agent_host, agent_port, full=False): - log.info('sync agent {h}:{p}'.format(h=agent_host, p=agent_port)) - # use retry with backoff to tolerate slow startup of radosgw-agent - s = requests.Session() - s.mount('http://{addr}:{port}/'.format(addr = agent_host, port = agent_port), - requests.adapters.HTTPAdapter(max_retries=Retry(total=5, backoff_factor=1))) - method = "full" if full else "incremental" - return s.post('http://{addr}:{port}/data/{method}'.format(addr = agent_host, port = agent_port, method = method)) - -def radosgw_agent_sync_metadata(ctx, agent_host, agent_port, full=False): - log.info('sync agent {h}:{p}'.format(h=agent_host, p=agent_port)) - # use retry with backoff to tolerate slow startup of radosgw-agent - s = requests.Session() - s.mount('http://{addr}:{port}/'.format(addr = agent_host, port = agent_port), - requests.adapters.HTTPAdapter(max_retries=Retry(total=5, backoff_factor=1))) - method = "full" if full else "incremental" - return s.post('http://{addr}:{port}/metadata/{method}'.format(addr = agent_host, port = agent_port, method = method)) - -def radosgw_agent_sync_all(ctx, full=False, data=False): - if ctx.radosgw_agent.procs: - for agent_client, c_config in ctx.radosgw_agent.config.iteritems(): - zone_for_client(ctx, agent_client) - sync_host, sync_port = get_sync_agent(ctx, agent_client) - log.debug('doing a sync via {host1}'.format(host1=sync_host)) - radosgw_agent_sync_metadata(ctx, sync_host, sync_port, full) - if (data): - radosgw_agent_sync_data(ctx, sync_host, sync_port, full) - -def host_for_role(ctx, role): - for target, roles in zip(ctx.config['targets'].iterkeys(), ctx.config['roles']): - if role in roles: - _, host = split_user(target) - return host +def wait_for_radosgw(url): + """ poll the given url until it starts accepting connections -def get_sync_agent(ctx, source): - for task in ctx.config['tasks']: - if 'radosgw-agent' not in task: - continue - for client, conf in task['radosgw-agent'].iteritems(): - if conf['src'] == source: - return host_for_role(ctx, source), conf.get('port', 8000) - return None, None - -def extract_zone_info(ctx, client, client_config): - """ - Get zone information. - :param client: dictionary of client information - :param client_config: dictionary of client configuration information - :returns: zone extracted from client and client_config information + add_daemon() doesn't wait until radosgw finishes startup, so this is used + to avoid racing with later tasks that expect radosgw to be up and listening """ - cluster_name, daemon_type, client_id = teuthology.split_role(client) - client_with_id = daemon_type + '.' + client_id - ceph_config = ctx.ceph[cluster_name].conf.get('global', {}) - ceph_config.update(ctx.ceph[cluster_name].conf.get('client', {})) - ceph_config.update(ctx.ceph[cluster_name].conf.get(client_with_id, {})) - for key in ['rgw zone', 'rgw region', 'rgw zone root pool']: - assert key in ceph_config, \ - 'ceph conf must contain {key} for {client}'.format(key=key, - client=client) - region = ceph_config['rgw region'] - zone = ceph_config['rgw zone'] - zone_info = dict() - for key in ['rgw control pool', 'rgw gc pool', 'rgw log pool', - 'rgw intent log pool', 'rgw usage log pool', - 'rgw user keys pool', 'rgw user email pool', - 'rgw user swift pool', 'rgw user uid pool', - 'rgw domain root']: - new_key = key.split(' ', 1)[1] - new_key = new_key.replace(' ', '_') - - if key in ceph_config: - value = ceph_config[key] - log.debug('{key} specified in ceph_config ({val})'.format( - key=key, val=value)) - zone_info[new_key] = value - else: - zone_info[new_key] = '.' + region + '.' + zone + '.' + new_key - - index_pool = '.' + region + '.' + zone + '.' + 'index_pool' - data_pool = '.' + region + '.' + zone + '.' + 'data_pool' - data_extra_pool = '.' + region + '.' + zone + '.' + 'data_extra_pool' - compression_type = ceph_config.get('rgw compression type', '') - - zone_info['placement_pools'] = [{'key': 'default_placement', - 'val': {'index_pool': index_pool, - 'data_pool': data_pool, - 'data_extra_pool': data_extra_pool, - 'compression': compression_type} - }] - - # these keys are meant for the zones argument in the region info. We - # insert them into zone_info with a different format and then remove them - # in the fill_in_endpoints() method - for key in ['rgw log meta', 'rgw log data']: - if key in ceph_config: - zone_info[key] = ceph_config[key] - - # these keys are meant for the zones argument in the region info. We - # insert them into zone_info with a different format and then remove them - # in the fill_in_endpoints() method - for key in ['rgw log meta', 'rgw log data']: - if key in ceph_config: - zone_info[key] = ceph_config[key] - - return region, zone, zone_info - -def extract_region_info(region, region_info): - """ - Extract region information from the region_info parameter, using get - to set default values. - - :param region: name of the region - :param region_info: region information (in dictionary form). - :returns: dictionary of region information set from region_info, using - default values for missing fields. - """ - assert isinstance(region_info['zones'], list) and region_info['zones'], \ - 'zones must be a non-empty list' - return dict( - name=region, - api_name=region_info.get('api name', region), - is_master=region_info.get('is master', False), - log_meta=region_info.get('log meta', False), - log_data=region_info.get('log data', False), - master_zone=region_info.get('master zone', region_info['zones'][0]), - placement_targets=region_info.get('placement targets', - [{'name': 'default_placement', - 'tags': []}]), - default_placement=region_info.get('default placement', - 'default_placement'), - ) - -def get_config_master_client(ctx, config, regions): - - role_zones = dict([(client, extract_zone_info(ctx, client, c_config)) - for client, c_config in config.iteritems()]) - log.debug('roles_zones = %r', role_zones) - region_info = dict([ - (region_name, extract_region_info(region_name, r_config)) - for region_name, r_config in regions.iteritems()]) - - # read master zonegroup and master_zone - for zonegroup, zg_info in region_info.iteritems(): - if zg_info['is_master']: - master_zonegroup = zonegroup - master_zone = zg_info['master_zone'] - break - - for client in config.iterkeys(): - (zonegroup, zone, zone_info) = role_zones[client] - if zonegroup == master_zonegroup and zone == master_zone: - return client - - return None - + # use a connection pool with retry/backoff to poll until it starts listening + http = PoolManager(retries=Retry(connect=8, backoff_factor=1)) + http.request('GET', url) diff --git a/ceph/qa/workunits/ceph-disk/ceph-disk-no-lockbox b/ceph/qa/workunits/ceph-disk/ceph-disk-no-lockbox index aa730200e..b9c1c6c39 100755 --- a/ceph/qa/workunits/ceph-disk/ceph-disk-no-lockbox +++ b/ceph/qa/workunits/ceph-disk/ceph-disk-no-lockbox @@ -1761,6 +1761,11 @@ class PrepareBluestore(Prepare): action='store_true', default=None, help='bluestore objectstore', ) + parser.add_argument( + '--filestore', + action='store_true', default=True, + help='IGNORED FORWARD COMPATIBIILTY HACK', + ) return parser @staticmethod @@ -2409,6 +2414,11 @@ class PrepareFilestoreData(PrepareData): self.set_data_partition() self.populate_data_path_device(*to_prepare_list) + def populate_data_path(self, path, *to_prepare_list): + super(PrepareFilestoreData, self).populate_data_path(path, + *to_prepare_list) + write_one_line(path, 'type', 'filestore') + class PrepareBluestoreData(PrepareData): diff --git a/ceph/qa/workunits/ceph-disk/ceph-disk-test.py b/ceph/qa/workunits/ceph-disk/ceph-disk-test.py index 6452dc687..b80e1da89 100644 --- a/ceph/qa/workunits/ceph-disk/ceph-disk-test.py +++ b/ceph/qa/workunits/ceph-disk/ceph-disk-test.py @@ -245,7 +245,6 @@ class TestCephDisk(object): # # bluestore # - c.conf['global']['enable experimental unrecoverable data corrupting features'] = '*' c.conf['global']['bluestore fsck on mount'] = 'true' c.save_conf() @@ -261,7 +260,7 @@ class TestCephDisk(object): disk = c.unused_disks()[0] osd_uuid = str(uuid.uuid1()) c.sh("ceph-disk --verbose zap " + disk) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + disk) c.wait_for_osd_up(osd_uuid) device = json.loads(c.sh("ceph-disk list --format json " + disk))[0] @@ -283,7 +282,7 @@ class TestCephDisk(object): c = CephDisk() disk = c.unused_disks()[0] osd_uuid = str(uuid.uuid1()) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + " " + disk) + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + disk) c.wait_for_osd_up(osd_uuid) c.check_osd_status(osd_uuid) c.destroy_osd(osd_uuid) @@ -292,7 +291,7 @@ class TestCephDisk(object): c = CephDisk() disk = c.unused_disks()[0] osd_uuid = str(uuid.uuid1()) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + " " + disk) + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + disk) c.wait_for_osd_up(osd_uuid) partition = c.get_osd_partition(osd_uuid) assert partition['type'] == 'data' @@ -374,7 +373,7 @@ class TestCephDisk(object): osd_uuid = str(uuid.uuid1()) journal_uuid = str(uuid.uuid1()) c.sh("ceph-disk --verbose zap " + disk) - c.sh(ceph_disk + " --verbose prepare " + + c.sh(ceph_disk + " --verbose prepare --filestore " + " --osd-uuid " + osd_uuid + " --journal-uuid " + journal_uuid + " --dmcrypt " + @@ -429,7 +428,7 @@ class TestCephDisk(object): c.sh("ceph-disk --verbose zap " + disk) c.conf['global']['osd objectstore'] = 'memstore' c.save_conf() - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + disk) c.wait_for_osd_up(osd_uuid) device = json.loads(c.sh("ceph-disk list --format json " + disk))[0] @@ -447,7 +446,7 @@ class TestCephDisk(object): disk = c.unused_disks()[0] osd_uuid = str(uuid.uuid1()) c.sh("ceph-disk --verbose zap " + disk) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + disk) c.wait_for_osd_up(osd_uuid) device = json.loads(c.sh("ceph-disk list --format json " + disk))[0] @@ -552,7 +551,7 @@ class TestCephDisk(object): symlink = os.path.join(tempdir, 'osd') os.symlink(disk, symlink) c.sh("ceph-disk --verbose zap " + symlink) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + symlink) c.wait_for_osd_up(osd_uuid) device = json.loads(c.sh("ceph-disk list --format json " + symlink))[0] @@ -581,7 +580,7 @@ class TestCephDisk(object): c.sh("chown ceph:ceph " + tempdir + " || true") journal_file = os.path.join(tempdir, 'journal') osd_uuid = str(uuid.uuid1()) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + data_disk + " " + journal_file) c.wait_for_osd_up(osd_uuid) device = json.loads( @@ -629,7 +628,7 @@ class TestCephDisk(object): def activate_separated_journal(self, data_disk, journal_disk): c = CephDisk() osd_uuid = str(uuid.uuid1()) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + data_disk + " " + journal_disk) c.wait_for_osd_up(osd_uuid) device = json.loads( @@ -684,7 +683,7 @@ class TestCephDisk(object): # # Create another OSD with the journal partition of the previous OSD # - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + data_disk + " " + journal_path) c.helper("pool_read_write 1") # 1 == pool size c.wait_for_osd_up(osd_uuid) @@ -722,7 +721,7 @@ class TestCephDisk(object): # osd_uuid = str(uuid.uuid1()) c.sh("ceph-disk --verbose zap " + multipath) - c.sh("ceph-disk --verbose prepare --osd-uuid " + osd_uuid + + c.sh("ceph-disk --verbose prepare --filestore --osd-uuid " + osd_uuid + " " + multipath) c.wait_for_osd_up(osd_uuid) device = json.loads( diff --git a/ceph/qa/workunits/ceph-helpers.sh b/ceph/qa/workunits/ceph-helpers.sh index b8b213356..bb681bf44 100755 --- a/ceph/qa/workunits/ceph-helpers.sh +++ b/ceph/qa/workunits/ceph-helpers.sh @@ -29,11 +29,18 @@ else echo "Missing xmlstarlet binary!" exit 1 fi + if [ `uname` = FreeBSD ]; then SED=gsed + DIFFCOLOPTS="" else SED=sed -fi + termwidth=$(stty -a | head -1 | sed -e 's/.*columns \([0-9]*\).*/\1/') + if [ -n "$termwidth" -a "$termwidth" != "0" ]; then + termwidth="-W ${termwidth}" + fi + DIFFCOLOPTS="-y $termwidth" +fi #! @file ceph-helpers.sh # @brief Toolbox to manage Ceph cluster dedicated to testing @@ -174,7 +181,6 @@ function test_teardown() { # @param delays sequence of sleep times before failure # function kill_daemon() { - set -x local pid=$(cat $1) local send_signal=$2 local delays=${3:-0.1 0.2 1 1 1 2 3 5 5 5 10 10 20 60 60 60 120} @@ -515,7 +521,7 @@ function run_osd() { mkdir -p $osd_data ceph-disk $ceph_disk_args \ - prepare $osd_data || return 1 + prepare --filestore $osd_data || return 1 activate_osd $dir $id "$@" } @@ -536,9 +542,7 @@ function run_osd_bluestore() { ceph-disk $ceph_disk_args \ prepare --bluestore $osd_data || return 1 - local ceph_osd_args - ceph_osd_args+=" --enable-experimental-unrecoverable-data-corrupting-features=bluestore" - activate_osd $dir $id $ceph_osd_args "$@" + activate_osd $dir $id "$@" } function test_run_osd() { @@ -656,7 +660,6 @@ function activate_osd() { ceph_disk_args+=" --prepend-to-path=" local ceph_args="$CEPH_ARGS" - ceph_args+=" --enable-experimental-unrecoverable-data-corrupting-features=bluestore" ceph_args+=" --osd-failsafe-full-ratio=.99" ceph_args+=" --osd-journal-size=100" ceph_args+=" --osd-scrub-load-threshold=2000" @@ -762,8 +765,8 @@ function get_osds() { local poolname=$1 local objectname=$2 - local osds=$(ceph --format xml osd map $poolname $objectname 2>/dev/null | \ - $XMLSTARLET sel -t -m "//acting/osd" -v . -o ' ') + local osds=$(ceph --format json osd map $poolname $objectname 2>/dev/null | \ + jq '.acting | .[]') # get rid of the trailing space echo $osds } @@ -832,8 +835,7 @@ function get_pg() { local poolname=$1 local objectname=$2 - ceph --format xml osd map $poolname $objectname 2>/dev/null | \ - $XMLSTARLET sel -t -m "//pgid" -v . -n + ceph --format json osd map $poolname $objectname 2>/dev/null | jq -r '.pgid' } function test_get_pg() { @@ -866,9 +868,9 @@ function get_config() { local config=$3 CEPH_ARGS='' \ - ceph --format xml daemon $dir/ceph-$daemon.$id.asok \ + ceph --format json daemon $dir/ceph-$daemon.$id.asok \ config get $config 2> /dev/null | \ - $XMLSTARLET sel -t -m "//$config" -v . -n + jq -r ".$config" } function test_get_config() { @@ -902,10 +904,9 @@ function set_config() { local config=$3 local value=$4 - CEPH_ARGS='' \ - ceph --format xml daemon $dir/ceph-$daemon.$id.asok \ - config set $config $value 2> /dev/null | \ - $XMLSTARLET sel -Q -t -m "//success" -v . + test $(env CEPH_ARGS='' ceph --format json daemon $dir/ceph-$daemon.$id.asok \ + config set $config $value 2> /dev/null | \ + jq 'has("success")') == true } function test_set_config() { @@ -936,8 +937,8 @@ function get_primary() { local poolname=$1 local objectname=$2 - ceph --format xml osd map $poolname $objectname 2>/dev/null | \ - $XMLSTARLET sel -t -m "//acting_primary" -v . -n + ceph --format json osd map $poolname $objectname 2>/dev/null | \ + jq '.acting_primary' } function test_get_primary() { @@ -969,9 +970,8 @@ function get_not_primary() { local objectname=$2 local primary=$(get_primary $poolname $objectname) - ceph --format xml osd map $poolname $objectname 2>/dev/null | \ - $XMLSTARLET sel -t -m "//acting/osd[not(.='$primary')]" -v . -n | \ - head -1 + ceph --format json osd map $poolname $objectname 2>/dev/null | \ + jq ".acting | map(select (. != $primary)) | .[0]" } function test_get_not_primary() { @@ -1024,7 +1024,6 @@ function objectstore_tool() { journal_args=" --journal-path $osd_data/journal" fi ceph-objectstore-tool \ - --enable-experimental-unrecoverable-data-corrupting-features=bluestore \ --data-path $osd_data \ $journal_args \ "$@" || return 1 @@ -1059,12 +1058,13 @@ function test_objectstore_tool() { # @return 0 if recovery in progress, 1 otherwise # function get_is_making_recovery_progress() { - local progress=$(ceph --format xml status 2>/dev/null | \ - $XMLSTARLET sel \ - -t -m "//pgmap/recovering_keys_per_sec" -v . -o ' ' \ - -t -m "//pgmap/recovering_bytes_per_sec" -v . -o ' ' \ - -t -m "//pgmap/recovering_objects_per_sec" -v .) - test -n "$progress" + local recovery_progress + recovery_progress+=".recovering_keys_per_sec + " + recovery_progress+=".recovering_bytes_per_sec + " + recovery_progress+=".recovering_objects_per_sec" + local progress=$(ceph --format json status 2>/dev/null | \ + jq -r ".pgmap | $recovery_progress") + test "$progress" != null } function test_get_is_making_recovery_progress() { @@ -1088,17 +1088,11 @@ function test_get_is_making_recovery_progress() { # @return 0 on success, 1 on error # function get_num_active_clean() { - local expression="(" - expression+="contains(.,'active') and " - expression+="contains(.,'clean') and " - expression+="not(contains(.,'stale'))" - expression+=")" - # xmlstarlet 1.3.0 (which is on Ubuntu precise) - # add extra new lines that must be ignored with - # grep -v '^$' - ceph --format xml pg dump pgs 2>/dev/null | \ - $XMLSTARLET sel -t -m "//pg_stat/state[$expression]" -v . -n | \ - grep -cv '^$' + local expression + expression+="select(contains(\"active\") and contains(\"clean\")) | " + expression+="select(contains(\"stale\") | not)" + ceph --format json pg dump pgs 2>/dev/null | \ + jq "[.[] | .state | $expression] | length" } function test_get_num_active_clean() { @@ -1124,8 +1118,7 @@ function test_get_num_active_clean() { # @return 0 on success, 1 on error # function get_num_pgs() { - ceph --format xml status 2>/dev/null | \ - $XMLSTARLET sel -t -m "//pgmap/num_pgs" -v . + ceph --format json status 2>/dev/null | jq '.pgmap.num_pgs' } function test_get_num_pgs() { @@ -1155,8 +1148,8 @@ function test_get_num_pgs() { function get_last_scrub_stamp() { local pgid=$1 local sname=${2:-last_scrub_stamp} - ceph --format xml pg dump pgs 2>/dev/null | \ - $XMLSTARLET sel -t -m "//pg_stat[pgid='$pgid']/$sname" -v . + ceph --format json pg dump pgs 2>/dev/null | \ + jq -r ".[] | select(.pgid==\"$pgid\") | .$sname" } function test_get_last_scrub_stamp() { @@ -1259,7 +1252,10 @@ function wait_for_clean() { local cur_active_clean local -a delays=($(get_timeout_delays $TIMEOUT .1)) local -i loop=0 - test $(get_num_pgs) != 0 || return 1 + + while test $(get_num_pgs) == 0 ; do + sleep 1 + done while true ; do # Comparing get_num_active_clean & get_num_pgs is used to determine @@ -1326,7 +1322,7 @@ function test_wait_for_health_ok() { setup $dir || return 1 run_mon $dir a --osd_pool_default_size=1 --osd_failsafe_full_ratio=.99 --mon_pg_warn_min_per_osd=0 || return 1 - run_mgr $dir x || return 1 + run_mgr $dir x --mon_pg_warn_min_per_osd=0 || return 1 ! TIMEOUT=1 wait_for_health_ok || return 1 run_osd $dir 0 || return 1 wait_for_health_ok || return 1 @@ -1647,6 +1643,47 @@ function test_wait_background() { if [ ! -z "$pids" ]; then return 1; fi } +function flush_pg_stats() +{ + local timeout=${1:-$TIMEOUT} + + ids=`ceph osd ls` + seqs='' + for osd in $ids; do + seq=`ceph tell osd.$osd flush_pg_stats` + seqs="$seqs $osd-$seq" + done + + for s in $seqs; do + osd=`echo $s | cut -d - -f 1` + seq=`echo $s | cut -d - -f 2` + echo "waiting osd.$osd seq $seq" + while test $(ceph osd last-stat-seq $osd) -lt $seq; do + sleep 1 + if [ $((timeout--)) -eq 0 ]; then + return 1 + fi + done + done +} + +function test_flush_pg_stats() +{ + local dir=$1 + + setup $dir || return 1 + run_mon $dir a --osd_pool_default_size=1 || return 1 + run_mgr $dir x || return 1 + run_osd $dir 0 || return 1 + rados -p rbd put obj /etc/group + flush_pg_stats + local jq_filter='.pools | .[] | select(.name == "rbd") | .stats' + raw_bytes_used=`ceph df detail --format=json | jq "$jq_filter.raw_bytes_used"` + bytes_used=`ceph df detail --format=json | jq "$jq_filter.bytes_used"` + test $raw_bytes_used > 0 || return 1 + test $raw_bytes_used == $bytes_used || return 1 +} + ####################################################################### ## diff --git a/ceph/qa/workunits/cephtool/test.sh b/ceph/qa/workunits/cephtool/test.sh index 92a8db1f3..36fb92a31 100755 --- a/ceph/qa/workunits/cephtool/test.sh +++ b/ceph/qa/workunits/cephtool/test.sh @@ -1,4 +1,6 @@ #!/bin/bash -x +# -*- mode:shell-script; tab-width:8; sh-basic-offset:2; indent-tabs-mode:t -*- +# vim: ts=8 sw=8 ft=bash smarttab source $(dirname $0)/../ceph-helpers.sh @@ -6,6 +8,7 @@ set -e set -o functrace PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: ' SUDO=${SUDO:-sudo} +export CEPH_DEV=1 function get_admin_socket() { @@ -292,7 +295,7 @@ function test_tiering_agent() ceph osd pool delete $slow $slow --yes-i-really-really-mean-it } -function test_tiering() +function test_tiering_1() { # tiering ceph osd pool create slow 2 @@ -319,7 +322,7 @@ function test_tiering() # test with dirty objects in the tier pool # tier pool currently set to 'writeback' rados -p cache put /etc/passwd /etc/passwd - ceph tell osd.\* flush_pg_stats || true + flush_pg_stats # 1 dirty object in pool 'cache' ceph osd tier cache-mode cache proxy expect_false ceph osd tier cache-mode cache none @@ -328,7 +331,7 @@ function test_tiering() # remove object from tier pool rados -p cache rm /etc/passwd rados -p cache cache-flush-evict-all - ceph tell osd.\* flush_pg_stats || true + flush_pg_stats # no dirty objects in pool 'cache' ceph osd tier cache-mode cache proxy ceph osd tier cache-mode cache none @@ -372,9 +375,14 @@ function test_tiering() ceph osd pool ls detail | grep cache2 ceph osd pool ls detail -f json-pretty | grep cache2 + ceph osd pool delete slow slow --yes-i-really-really-mean-it + ceph osd pool delete slow2 slow2 --yes-i-really-really-mean-it ceph osd pool delete cache cache --yes-i-really-really-mean-it ceph osd pool delete cache2 cache2 --yes-i-really-really-mean-it +} +function test_tiering_2() +{ # make sure we can't clobber snapshot state ceph osd pool create snap_base 2 ceph osd pool create snap_cache 2 @@ -382,7 +390,10 @@ function test_tiering() expect_false ceph osd tier add snap_base snap_cache ceph osd pool delete snap_base snap_base --yes-i-really-really-mean-it ceph osd pool delete snap_cache snap_cache --yes-i-really-really-mean-it +} +function test_tiering_3() +{ # make sure we can't create snapshot on tier ceph osd pool create basex 2 ceph osd pool create cachex 2 @@ -391,7 +402,10 @@ function test_tiering() ceph osd tier remove basex cachex ceph osd pool delete basex basex --yes-i-really-really-mean-it ceph osd pool delete cachex cachex --yes-i-really-really-mean-it +} +function test_tiering_4() +{ # make sure we can't create an ec pool tier ceph osd pool create eccache 2 2 erasure expect_false ceph osd set-require-min-compat-client bobtail @@ -399,8 +413,12 @@ function test_tiering() expect_false ceph osd tier add repbase eccache ceph osd pool delete repbase repbase --yes-i-really-really-mean-it ceph osd pool delete eccache eccache --yes-i-really-really-mean-it +} +function test_tiering_5() +{ # convenient add-cache command + ceph osd pool create slow 2 ceph osd pool create cache3 2 ceph osd tier add-cache slow cache3 1024000 ceph osd dump | grep cache3 | grep bloom | grep 'false_positive_probability: 0.05' | grep 'target_bytes 1024000' | grep '1200s x4' @@ -411,10 +429,11 @@ function test_tiering() ceph osd pool ls | grep cache3 ceph osd pool delete cache3 cache3 --yes-i-really-really-mean-it ! ceph osd pool ls | grep cache3 || exit 1 - - ceph osd pool delete slow2 slow2 --yes-i-really-really-mean-it ceph osd pool delete slow slow --yes-i-really-really-mean-it +} +function test_tiering_6() +{ # check add-cache whether work ceph osd pool create datapool 2 ceph osd pool create cachepool 2 @@ -428,7 +447,10 @@ function test_tiering() ceph osd tier remove datapool cachepool ceph osd pool delete cachepool cachepool --yes-i-really-really-mean-it ceph osd pool delete datapool datapool --yes-i-really-really-mean-it +} +function test_tiering_7() +{ # protection against pool removal when used as tiers ceph osd pool create datapool 2 ceph osd pool create cachepool 2 @@ -441,7 +463,10 @@ function test_tiering() ceph osd tier remove datapool cachepool ceph osd pool delete cachepool cachepool --yes-i-really-really-mean-it ceph osd pool delete datapool datapool --yes-i-really-really-mean-it +} +function test_tiering_8() +{ ## check health check ceph osd set notieragent ceph osd pool create datapool 2 @@ -455,15 +480,17 @@ function test_tiering() rados -p cache4 put foo1 $tmpfile rados -p cache4 put foo2 $tmpfile rm -f $tmpfile - ceph tell osd.\* flush_pg_stats || true + flush_pg_stats ceph df | grep datapool | grep ' 2 ' ceph osd tier remove-overlay datapool ceph osd tier remove datapool cache4 ceph osd pool delete cache4 cache4 --yes-i-really-really-mean-it ceph osd pool delete datapool datapool --yes-i-really-really-mean-it ceph osd unset notieragent +} - +function test_tiering_9() +{ # make sure 'tier remove' behaves as we expect # i.e., removing a tier from a pool that's not its base pool only # results in a 'pool foo is now (or already was) not a tier of bar' @@ -649,6 +676,8 @@ function test_mon_misc() ceph osd dump | grep '^epoch' ceph --concise osd dump | grep '^epoch' + ceph osd df | grep 'MIN/MAX VAR' + # df ceph df > $TMPFILE grep GLOBAL $TMPFILE @@ -678,10 +707,17 @@ function test_mon_misc() ceph_watch_start mymsg="this is a test log message $$.$(date)" ceph log "$mymsg" + ceph log last | grep "$mymsg" + ceph log last 100 | grep "$mymsg" ceph_watch_wait "$mymsg" + ceph mgr dump + ceph mon metadata a ceph mon metadata + ceph mon count-metadata ceph_version + ceph mon versions + ceph node ls } @@ -762,7 +798,7 @@ function without_test_dup_command() function test_mds_tell() { - FS_NAME=cephfs + local FS_NAME=cephfs if ! mds_exists ; then echo "Skipping test, no MDS found" return @@ -808,7 +844,7 @@ function test_mds_tell() function test_mon_mds() { - FS_NAME=cephfs + local FS_NAME=cephfs remove_all_fs ceph osd pool create fs_data 10 @@ -838,6 +874,8 @@ function test_mon_mds() ceph mds metadata $mds_id done ceph mds metadata + ceph mds versions + ceph mds count-metadata os # XXX mds fail, but how do you undo it? mdsmapfile=$TEMP_DIR/mdsmap.$$ @@ -1085,6 +1123,194 @@ function test_mon_mon() expect_false ceph mon feature set abcd --yes-i-really-mean-it } +function gen_secrets_file() +{ + # lets assume we can have the following types + # all - generates both cephx and lockbox, with mock dm-crypt key + # cephx - only cephx + # no_cephx - lockbox and dm-crypt, no cephx + # no_lockbox - dm-crypt and cephx, no lockbox + # empty - empty file + # empty_json - correct json, empty map + # bad_json - bad json :) + # + local t=$1 + if [[ -z "$t" ]]; then + t="all" + fi + + fn=$(mktemp $TEMP_DIR/secret.XXXXXX) + echo $fn + if [[ "$t" == "empty" ]]; then + return 0 + fi + + echo "{" > $fn + if [[ "$t" == "bad_json" ]]; then + echo "asd: ; }" >> $fn + return 0 + elif [[ "$t" == "empty_json" ]]; then + echo "}" >> $fn + return 0 + fi + + cephx_secret="\"cephx_secret\": \"$(ceph-authtool --gen-print-key)\"" + lb_secret="\"cephx_lockbox_secret\": \"$(ceph-authtool --gen-print-key)\"" + dmcrypt_key="\"dmcrypt_key\": \"$(ceph-authtool --gen-print-key)\"" + + if [[ "$t" == "all" ]]; then + echo "$cephx_secret,$lb_secret,$dmcrypt_key" >> $fn + elif [[ "$t" == "cephx" ]]; then + echo "$cephx_secret" >> $fn + elif [[ "$t" == "no_cephx" ]]; then + echo "$lb_secret,$dmcrypt_key" >> $fn + elif [[ "$t" == "no_lockbox" ]]; then + echo "$cephx_secret,$dmcrypt_key" >> $fn + else + echo "unknown gen_secrets_file() type \'$fn\'" + return 1 + fi + echo "}" >> $fn + return 0 +} + +function test_mon_osd_create_destroy() +{ + ceph osd new 2>&1 | grep 'EINVAL' + ceph osd new '' -1 2>&1 | grep 'EINVAL' + ceph osd new '' 10 2>&1 | grep 'EINVAL' + + old_maxosd=$(ceph osd getmaxosd | sed -e 's/max_osd = //' -e 's/ in epoch.*//') + + old_osds=$(ceph osd ls) + num_osds=$(ceph osd ls | wc -l) + + uuid=$(uuidgen) + id=$(ceph osd new $uuid 2>/dev/null) + + for i in $old_osds; do + [[ "$i" != "$id" ]] + done + + ceph osd find $id + + id2=`ceph osd new $uuid 2>/dev/null` + + [[ $id2 == $id ]] + + ceph osd new $uuid $id + + id3=$(ceph osd getmaxosd | sed -e 's/max_osd = //' -e 's/ in epoch.*//') + ceph osd new $uuid $((id3+1)) 2>&1 | grep EEXIST + + uuid2=$(uuidgen) + id2=$(ceph osd new $uuid2) + ceph osd find $id2 + [[ "$id2" != "$id" ]] + + ceph osd new $uuid $id2 2>&1 | grep EEXIST + ceph osd new $uuid2 $id2 + + # test with secrets + empty_secrets=$(gen_secrets_file "empty") + empty_json=$(gen_secrets_file "empty_json") + all_secrets=$(gen_secrets_file "all") + cephx_only=$(gen_secrets_file "cephx") + no_cephx=$(gen_secrets_file "no_cephx") + no_lockbox=$(gen_secrets_file "no_lockbox") + bad_json=$(gen_secrets_file "bad_json") + + # empty secrets should be idempotent + new_id=$(ceph osd new $uuid $id -i $empty_secrets) + [[ "$new_id" == "$id" ]] + + # empty json, thus empty secrets + new_id=$(ceph osd new $uuid $id -i $empty_json) + [[ "$new_id" == "$id" ]] + + ceph osd new $uuid $id -i $all_secrets 2>&1 | grep 'EEXIST' + + ceph osd rm $id + ceph osd rm $id2 + ceph osd setmaxosd $old_maxosd + + ceph osd new $uuid -i $bad_json 2>&1 | grep 'EINVAL' + ceph osd new $uuid -i $no_cephx 2>&1 | grep 'EINVAL' + ceph osd new $uuid -i $no_lockbox 2>&1 | grep 'EINVAL' + + osds=$(ceph osd ls) + id=$(ceph osd new $uuid -i $all_secrets) + for i in $osds; do + [[ "$i" != "$id" ]] + done + + ceph osd find $id + + # validate secrets and dm-crypt are set + k=$(ceph auth get-key osd.$id --format=json-pretty 2>/dev/null | jq '.key') + s=$(cat $all_secrets | jq '.cephx_secret') + [[ $k == $s ]] + k=$(ceph auth get-key client.osd-lockbox.$uuid --format=json-pretty 2>/dev/null | \ + jq '.key') + s=$(cat $all_secrets | jq '.cephx_lockbox_secret') + [[ $k == $s ]] + ceph config-key exists dm-crypt/osd/$uuid/luks + + osds=$(ceph osd ls) + id2=$(ceph osd new $uuid2 -i $cephx_only) + for i in $osds; do + [[ "$i" != "$id2" ]] + done + + ceph osd find $id2 + k=$(ceph auth get-key osd.$id --format=json-pretty 2>/dev/null | jq '.key') + s=$(cat $all_secrets | jq '.cephx_secret') + [[ $k == $s ]] + expect_false ceph auth get-key client.osd-lockbox.$uuid2 + expect_false ceph config-key exists dm-crypt/osd/$uuid2/luks + + ceph osd destroy osd.$id2 --yes-i-really-mean-it + ceph osd destroy $id2 --yes-i-really-mean-it + ceph osd find $id2 + expect_false ceph auth get-key osd.$id2 + ceph osd dump | grep osd.$id2 | grep destroyed + + id3=$id2 + uuid3=$(uuidgen) + ceph osd new $uuid3 $id3 -i $all_secrets + ceph osd dump | grep osd.$id3 | expect_false grep destroyed + ceph auth get-key client.osd-lockbox.$uuid3 + ceph auth get-key osd.$id3 + ceph config-key exists dm-crypt/osd/$uuid3/luks + + ceph osd purge osd.$id3 --yes-i-really-mean-it + expect_false ceph osd find $id2 + expect_false ceph auth get-key osd.$id2 + expect_false ceph auth get-key client.osd-lockbox.$uuid3 + expect_false ceph config-key exists dm-crypt/osd/$uuid3/luks + ceph osd purge osd.$id3 --yes-i-really-mean-it + ceph osd purge osd.$id3 --yes-i-really-mean-it + + ceph osd purge osd.$id --yes-i-really-mean-it + expect_false ceph osd find $id + expect_false ceph auth get-key osd.$id + expect_false ceph auth get-key client.osd-lockbox.$uuid + expect_false ceph config-key exists dm-crypt/osd/$uuid/luks + + rm $empty_secrets $empty_json $all_secrets $cephx_only \ + $no_cephx $no_lockbox $bad_json + + for i in $(ceph osd ls); do + [[ "$i" != "$id" ]] + [[ "$i" != "$id2" ]] + [[ "$i" != "$id3" ]] + done + + [[ "$(ceph osd ls | wc -l)" == "$num_osds" ]] + ceph osd setmaxosd $old_maxosd + +} + function test_mon_osd() { # @@ -1155,10 +1381,13 @@ function test_mon_osd() expect_false ceph osd unset sortbitwise # cannot be unset expect_false ceph osd set bogus expect_false ceph osd unset bogus + ceph osd require-osd-release luminous + # can't lower (or use new command for anything but jewel) + expect_false ceph osd require-osd-release jewel + # these are no-ops but should succeed. ceph osd set require_jewel_osds - expect_false ceph osd unset require_jewel_osds ceph osd set require_kraken_osds - expect_false ceph osd unset require_kraken_osds + expect_false ceph osd unset require_jewel_osds ceph osd set noup ceph osd down 0 @@ -1193,6 +1422,47 @@ function test_mon_osd() ceph osd dump | grep 'osd.0.*in' ceph osd find 0 + ceph osd add-nodown 0 1 + ceph health detail | grep 'nodown osd(s).*0.*1' + ceph osd rm-nodown 0 1 + ! ceph health detail | grep 'nodown osd(s).*0.*1' + + ceph osd out 0 # so we can mark it as noin later + ceph osd add-noin 0 + ceph health detail | grep 'noin osd(s).*0' + ceph osd rm-noin 0 + ! ceph health detail | grep 'noin osd(s).*0' + ceph osd in 0 + + ceph osd add-noout 0 + ceph health detail | grep 'noout osd(s).*0' + ceph osd rm-noout 0 + ! ceph health detail | grep 'noout osds(s).*0' + + # test osd id parse + expect_false ceph osd add-noup 797er + expect_false ceph osd add-nodown u9uwer + expect_false ceph osd add-noin 78~15 + expect_false ceph osd add-noout 0 all 1 + + expect_false ceph osd rm-noup 1234567 + expect_false ceph osd rm-nodown fsadf7 + expect_false ceph osd rm-noin 0 1 any + expect_false ceph osd rm-noout 790-fd + + ids=`ceph osd ls-tree default` + for osd in $ids + do + ceph osd add-nodown $osd + ceph osd add-noout $osd + done + ceph -s | grep 'nodown osd(s)' + ceph -s | grep 'noout osd(s)' + ceph osd rm-nodown any + ceph osd rm-noout all + ! ceph -s | grep 'nodown osd(s)' + ! ceph -s | grep 'noout osd(s)' + # make sure mark out preserves weight ceph osd reweight osd.0 .5 ceph osd dump | grep ^osd.0 | grep 'weight 0.5' @@ -1200,11 +1470,6 @@ function test_mon_osd() ceph osd in 0 ceph osd dump | grep ^osd.0 | grep 'weight 0.5' - f=$TEMP_DIR/map.$$ - ceph osd getcrushmap -o $f - [ -s $f ] - ceph osd setcrushmap -i $f - rm $f ceph osd getmap -o $f [ -s $f ] rm $f @@ -1254,8 +1519,8 @@ function test_mon_osd() max_osd=$((max_osd + 1)) ceph osd getmaxosd | grep "max_osd = $max_osd" - ceph osd create $uuid $((id - 1)) 2>&1 | grep 'EINVAL' - ceph osd create $uuid $((id + 1)) 2>&1 | grep 'EINVAL' + ceph osd create $uuid $((id - 1)) 2>&1 | grep 'EEXIST' + ceph osd create $uuid $((id + 1)) 2>&1 | grep 'EEXIST' id2=`ceph osd create $uuid` [ "$id" = "$id2" ] id2=`ceph osd create $uuid $id` @@ -1268,7 +1533,7 @@ function test_mon_osd() max_osd=$((id + 1)) ceph osd getmaxosd | grep "max_osd = $max_osd" - ceph osd create $uuid $gap_start 2>&1 | grep 'EINVAL' + ceph osd create $uuid $gap_start 2>&1 | grep 'EEXIST' # # When CEPH_CLI_TEST_DUP_COMMAND is set, osd create @@ -1310,12 +1575,49 @@ function test_mon_osd() ceph osd unpause ceph osd tree + ceph osd tree up + ceph osd tree down + ceph osd tree in + ceph osd tree out + ceph osd tree up in + ceph osd tree up out + ceph osd tree down in + ceph osd tree down out + ceph osd tree out down + expect_false ceph osd tree up down + expect_false ceph osd tree in out + expect_false ceph osd tree up foo + + ceph osd metadata + ceph osd count-metadata os + ceph osd versions + ceph osd perf ceph osd blocked-by ceph osd stat | grep up, } +function test_mon_crush() +{ + f=$TEMP_DIR/map.$$ + epoch=$(ceph osd getcrushmap -o $f 2>&1 | tail -n1) + [ -s $f ] + [ "$epoch" -gt 1 ] + nextepoch=$(( $epoch + 1 )) + echo epoch $epoch nextepoch $nextepoch + rm -f $f.epoch + expect_false ceph osd setcrushmap $nextepoch -i $f + gotepoch=$(ceph osd setcrushmap $epoch -i $f 2>&1 | tail -n1) + echo gotepoch $gotepoch + [ "$gotepoch" -eq "$nextepoch" ] + # should be idempotent + gotepoch=$(ceph osd setcrushmap $epoch -i $f 2>&1 | tail -n1) + echo epoch $gotepoch + [ "$gotepoch" -eq "$nextepoch" ] + rm $f +} + function test_mon_osd_pool() { # @@ -1478,9 +1780,9 @@ function test_mon_pg() wait_for_health "HEALTH_ERR.*1 full osd(s)" $SUDO ceph --admin-daemon $(get_admin_socket osd.0) injectfull full wait_for_health "HEALTH_ERR.*2 full osd(s)" - ceph health detail | grep "osd.0 is full at.*%" - ceph health detail | grep "osd.2 is full at.*%" - ceph health detail | grep "osd.1 is backfill full at.*%" + ceph health detail | grep "osd.0 is full" + ceph health detail | grep "osd.2 is full" + ceph health detail | grep "osd.1 is backfill full" $SUDO ceph --admin-daemon $(get_admin_socket osd.0) injectfull none $SUDO ceph --admin-daemon $(get_admin_socket osd.1) injectfull none $SUDO ceph --admin-daemon $(get_admin_socket osd.2) injectfull none @@ -1531,7 +1833,7 @@ function test_mon_osd_pool_set() wait_for_clean ceph osd pool get $TEST_POOL_GETSET all - for s in pg_num pgp_num size min_size crush_rule crush_ruleset; do + for s in pg_num pgp_num size min_size crush_rule; do ceph osd pool get $TEST_POOL_GETSET $s done @@ -1640,7 +1942,6 @@ function test_mon_osd_pool_set() ceph osd pool set $TEST_POOL_GETSET nodelete 0 ceph osd pool delete $TEST_POOL_GETSET $TEST_POOL_GETSET --yes-i-really-really-mean-it - ceph osd pool get rbd crush_ruleset | grep 'crush_ruleset: 0' ceph osd pool get rbd crush_rule | grep 'crush_rule: ' } @@ -1886,11 +2187,11 @@ function test_mon_tell() ceph_watch_start debug ceph tell mon.a version - ceph_watch_wait 'mon.0 \[DBG\] from.*cmd=\[{"prefix": "version"}\]: dispatch' + ceph_watch_wait 'mon.a \[DBG\] from.*cmd=\[{"prefix": "version"}\]: dispatch' ceph_watch_start debug ceph tell mon.b version - ceph_watch_wait 'mon.1 \[DBG\] from.*cmd=\[{"prefix": "version"}\]: dispatch' + ceph_watch_wait 'mon.b \[DBG\] from.*cmd=\[{"prefix": "version"}\]: dispatch' } function test_mon_crushmap_validation() @@ -2001,9 +2302,12 @@ function test_mon_cephdf_commands() rados -p cephdf_for_test ls - | grep -q cephdf_for_test && break sleep 1 done - - cal_raw_used_size=`ceph df detail | grep cephdf_for_test | awk -F ' ' '{printf "%d\n", 2 * $3}'` - raw_used_size=`ceph df detail | grep cephdf_for_test | awk -F ' ' '{print $10}'` + # "rados ls" goes straight to osd, but "ceph df" is served by mon. so we need + # to sync mon with osd + flush_pg_stats + local jq_filter='.pools | .[] | select(.name == "cephdf_for_test") | .stats' + cal_raw_used_size=`ceph df detail --format=json | jq "$jq_filter.raw_bytes_used"` + raw_used_size=`ceph df detail --format=json | jq "$jq_filter.bytes_used * 2"` ceph osd pool delete cephdf_for_test cephdf_for_test --yes-i-really-really-mean-it rm ./cephdf_for_test @@ -2011,6 +2315,48 @@ function test_mon_cephdf_commands() expect_false test $cal_raw_used_size != $raw_used_size } +function test_mon_tell_help_command() +{ + ceph tell mon.a help + + # wrong target + expect_false ceph tell mon.zzz help +} + +function test_osd_tell_help_command() +{ + ceph tell osd.1 help + expect_false ceph tell osd.100 help +} + +function test_mds_tell_help_command() +{ + local FS_NAME=cephfs + if ! mds_exists ; then + echo "Skipping test, no MDS found" + return + fi + + remove_all_fs + ceph osd pool create fs_data 10 + ceph osd pool create fs_metadata 10 + ceph fs new $FS_NAME fs_metadata fs_data + wait_mds_active $FS_NAME + + + ceph tell mds.a help + expect_false ceph tell mds.z help + + remove_all_fs + ceph osd pool delete fs_data fs_data --yes-i-really-really-mean-it + ceph osd pool delete fs_metadata fs_metadata --yes-i-really-really-mean-it +} + +function test_mgr_tell_help_command() +{ + ceph tell mgr help +} + # # New tests should be added to the TESTS array below # @@ -2030,12 +2376,16 @@ function test_mon_cephdf_commands() set +x MON_TESTS+=" mon_injectargs" MON_TESTS+=" mon_injectargs_SI" -MON_TESTS+=" tiering" +for i in `seq 9`; do + MON_TESTS+=" tiering_$i"; +done MON_TESTS+=" auth" MON_TESTS+=" auth_profiles" MON_TESTS+=" mon_misc" MON_TESTS+=" mon_mon" MON_TESTS+=" mon_osd" +MON_TESTS+=" mon_crush" +MON_TESTS+=" mon_osd_create_destroy" MON_TESTS+=" mon_osd_pool" MON_TESTS+=" mon_osd_pool_quota" MON_TESTS+=" mon_pg" @@ -2050,18 +2400,25 @@ MON_TESTS+=" mon_ping" MON_TESTS+=" mon_deprecated_commands" MON_TESTS+=" mon_caps" MON_TESTS+=" mon_cephdf_commands" +MON_TESTS+=" mon_tell_help_command" + OSD_TESTS+=" osd_bench" OSD_TESTS+=" osd_negative_filestore_merge_threshold" OSD_TESTS+=" tiering_agent" OSD_TESTS+=" admin_heap_profiler" +OSD_TESTS+=" osd_tell_help_command" MDS_TESTS+=" mds_tell" MDS_TESTS+=" mon_mds" MDS_TESTS+=" mon_mds_metadata" +MDS_TESTS+=" mds_tell_help_command" + +MGR_TESTS+=" mgr_tell_help_command" TESTS+=$MON_TESTS TESTS+=$OSD_TESTS TESTS+=$MDS_TESTS +TESTS+=$MGR_TESTS # # "main" follows @@ -2106,6 +2463,9 @@ while [[ $# -gt 0 ]]; do "--test-mds" ) tests_to_run+="$MDS_TESTS" ;; + "--test-mgr" ) + tests_to_run+="$MGR_TESTS" + ;; "-t" ) shift if [[ -z "$1" ]]; then diff --git a/ceph/qa/workunits/mon/crush_ops.sh b/ceph/qa/workunits/mon/crush_ops.sh index 80c58ca75..11891480a 100755 --- a/ceph/qa/workunits/mon/crush_ops.sh +++ b/ceph/qa/workunits/mon/crush_ops.sh @@ -26,7 +26,7 @@ ceph osd crush rule rm foo # idempotent ceph osd crush rule rm bar # can't delete in-use rules, tho: -expect_false ceph osd crush rule rm replicated_ruleset +expect_false ceph osd crush rule rm replicated_rule # build a simple map expect_false ceph osd crush add-bucket foo osd diff --git a/ceph/qa/workunits/rados/test_health_warnings.sh b/ceph/qa/workunits/rados/test_health_warnings.sh new file mode 100755 index 000000000..252fa3443 --- /dev/null +++ b/ceph/qa/workunits/rados/test_health_warnings.sh @@ -0,0 +1,60 @@ +#!/bin/bash -ex + +set -u + +# number of osds = 10 +crushtool -o crushmap --build --num_osds 10 host straw 2 rack straw 2 row straw 2 root straw 0 +ceph osd setcrushmap -i crushmap +ceph osd tree +ceph tell osd.* injectargs --osd_max_markdown_count 1024 --osd_max_markdown_period 1 + +wait_for_healthy() { + while ceph health | grep down + do + sleep 1 + done +} + +test_mark_two_osds_same_host_down() { + ceph osd set noup + ceph osd down osd.0 osd.1 + ceph health detail + ceph health | grep "1 host" + ceph health | grep "2 osds" + ceph health detail | grep "osd.0" + ceph health detail | grep "osd.1" + ceph osd unset noup + wait_for_healthy +} + +test_mark_two_osds_same_rack_down() { + ceph osd set noup + ceph osd down osd.8 osd.9 + ceph health detail + ceph health | grep "1 host" + ceph health | grep "1 rack" + ceph health | grep "1 row" + ceph health | grep "2 osds" + ceph health detail | grep "osd.8" + ceph health detail | grep "osd.9" + ceph osd unset noup + wait_for_healthy +} + +test_mark_all_but_last_osds_down() { + ceph osd set noup + ceph osd down $(ceph osd ls | sed \$d) + ceph health detail + ceph health | grep "1 row" + ceph health | grep "2 racks" + ceph health | grep "4 hosts" + ceph health | grep "9 osds" + ceph osd unset noup + wait_for_healthy +} + +test_mark_two_osds_same_host_down +test_mark_two_osds_same_rack_down +test_mark_all_but_last_osds_down + +exit 0 diff --git a/ceph/qa/workunits/rados/test_pool_access.sh b/ceph/qa/workunits/rados/test_pool_access.sh new file mode 100755 index 000000000..8597b7147 --- /dev/null +++ b/ceph/qa/workunits/rados/test_pool_access.sh @@ -0,0 +1,23 @@ +#!/bin/bash -x + +set -e + +expect_1() +{ + set -x + set +e + "$@" + if [ $? == 1 ]; then return 0; else return 1; fi +} + + +key=`ceph auth get-or-create-key client.poolaccess1 mon 'allow r' osd 'allow *'` +rados --id poolaccess1 --key $key -p rbd ls + +key=`ceph auth get-or-create-key client.poolaccess2 mon 'allow r' osd 'allow * pool=nopool'` +expect_1 rados --id poolaccess2 --key $key -p rbd ls + +key=`ceph auth get-or-create-key client.poolaccess3 mon 'allow r' osd 'allow rw pool=nopool'` +expect_1 rados --id poolaccess3 --key $key -p rbd ls + +echo OK diff --git a/ceph/qa/workunits/rbd/krbd_data_pool.sh b/ceph/qa/workunits/rbd/krbd_data_pool.sh index 0b7b6c933..c3f48e381 100755 --- a/ceph/qa/workunits/rbd/krbd_data_pool.sh +++ b/ceph/qa/workunits/rbd/krbd_data_pool.sh @@ -67,6 +67,16 @@ function mkfs_and_mount() { sudo rbd unmap $dev } +function list_HEADs() { + local pool=$1 + + rados -p $pool ls | while read obj; do + if rados -p $pool stat $obj >/dev/null 2>&1; then + echo $obj + fi + done +} + function count_data_objects() { local spec=$1 @@ -78,7 +88,14 @@ function count_data_objects() { local prefix prefix=$(rbd info $spec | grep 'block_name_prefix: ' | awk '{ print $NF }') - echo $(rados -p $pool ls | grep -c $prefix) + rados -p $pool ls | grep -c $prefix +} + +function get_num_clones() { + local pool=$1 + + rados -p $pool --format=json df | + python -c 'import sys, json; print json.load(sys.stdin)["pools"][0]["num_object_clones"]' } ceph osd pool create repdata 24 24 @@ -146,6 +163,12 @@ for pool in rbd rbdnonzero; do done done +[[ $(get_num_clones rbd) -eq 0 ]] +[[ $(get_num_clones repdata) -eq 0 ]] +[[ $(get_num_clones ecdata) -eq 0 ]] +[[ $(get_num_clones rbdnonzero) -eq 0 ]] +[[ $(get_num_clones clonesonly) -eq 0 ]] + for pool in rbd rbdnonzero; do for i in {0..3}; do compare $pool/img$i $OBJECT_X @@ -161,10 +184,16 @@ for pool in rbd rbdnonzero; do done # mkfs should discard some objects everywhere but in clonesonly -[[ $(rados -p rbd ls | wc -l) -lt $((NUM_META_RBDS + 5 * NUM_OBJECTS)) ]] -[[ $(rados -p repdata ls | wc -l) -lt $((1 + 14 * NUM_OBJECTS)) ]] -[[ $(rados -p ecdata ls | wc -l) -lt $((1 + 14 * NUM_OBJECTS)) ]] -[[ $(rados -p rbdnonzero ls | wc -l) -lt $((NUM_META_RBDS + 5 * NUM_OBJECTS)) ]] -[[ $(rados -p clonesonly ls | wc -l) -eq $((NUM_META_CLONESONLY + 6 * NUM_OBJECTS)) ]] +[[ $(list_HEADs rbd | wc -l) -lt $((NUM_META_RBDS + 5 * NUM_OBJECTS)) ]] +[[ $(list_HEADs repdata | wc -l) -lt $((1 + 14 * NUM_OBJECTS)) ]] +[[ $(list_HEADs ecdata | wc -l) -lt $((1 + 14 * NUM_OBJECTS)) ]] +[[ $(list_HEADs rbdnonzero | wc -l) -lt $((NUM_META_RBDS + 5 * NUM_OBJECTS)) ]] +[[ $(list_HEADs clonesonly | wc -l) -eq $((NUM_META_CLONESONLY + 6 * NUM_OBJECTS)) ]] + +[[ $(get_num_clones rbd) -eq $NUM_OBJECTS ]] +[[ $(get_num_clones repdata) -eq $((2 * NUM_OBJECTS)) ]] +[[ $(get_num_clones ecdata) -eq $((2 * NUM_OBJECTS)) ]] +[[ $(get_num_clones rbdnonzero) -eq $NUM_OBJECTS ]] +[[ $(get_num_clones clonesonly) -eq 0 ]] echo OK diff --git a/ceph/qa/workunits/rbd/krbd_fallocate.sh b/ceph/qa/workunits/rbd/krbd_fallocate.sh new file mode 100755 index 000000000..05fc8a98c --- /dev/null +++ b/ceph/qa/workunits/rbd/krbd_fallocate.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +# This documents the state of things as of 4.12-rc4. +# +# - fallocate -z deallocates because BLKDEV_ZERO_NOUNMAP hint is ignored by +# krbd +# +# - unaligned fallocate -z/-p appear to not deallocate -- see caveat #2 in +# linux.git commit 6ac56951dc10 ("rbd: implement REQ_OP_WRITE_ZEROES") + +set -ex + +# no blkdiscard(8) in trusty +function py_blkdiscard() { + local offset=$1 + + python <&1 | grep -q "listed 0 entries" +ceph --cluster ${CLUSTER2} osd blacklist ls 2>&1 | grep -q "listed 0 entries" + echo OK diff --git a/ceph/qa/workunits/rbd/test_librbd.sh b/ceph/qa/workunits/rbd/test_librbd.sh index f3999f4bb..447306bb4 100755 --- a/ceph/qa/workunits/rbd/test_librbd.sh +++ b/ceph/qa/workunits/rbd/test_librbd.sh @@ -1,8 +1,8 @@ #!/bin/sh -e if [ -n "${VALGRIND}" ]; then - valgrind --tool=${VALGRIND} --suppressions=${TESTDIR}/valgrind.supp \ - ceph_test_librbd + valgrind ${VALGRIND} --suppressions=${TESTDIR}/valgrind.supp \ + --error-exitcode=1 ceph_test_librbd else ceph_test_librbd fi diff --git a/ceph/qa/workunits/rbd/test_librbd_python.sh b/ceph/qa/workunits/rbd/test_librbd_python.sh index 9bef91b4e..656a5bd16 100755 --- a/ceph/qa/workunits/rbd/test_librbd_python.sh +++ b/ceph/qa/workunits/rbd/test_librbd_python.sh @@ -3,7 +3,8 @@ relpath=$(dirname $0)/../../../src/test/pybind if [ -n "${VALGRIND}" ]; then - valgrind --tool=${VALGRIND} --suppressions=${TESTDIR}/valgrind.supp \ + valgrind ${VALGRIND} --suppressions=${TESTDIR}/valgrind.supp \ + --errors-for-leak-kinds=definite --error-exitcode=1 \ nosetests -v $relpath/test_rbd.py else nosetests -v $relpath/test_rbd.py diff --git a/ceph/qa/workunits/rbd/test_rbd_mirror.sh b/ceph/qa/workunits/rbd/test_rbd_mirror.sh index 725e1d3df..e139dd7e4 100755 --- a/ceph/qa/workunits/rbd/test_rbd_mirror.sh +++ b/ceph/qa/workunits/rbd/test_rbd_mirror.sh @@ -1,8 +1,8 @@ #!/bin/sh -e if [ -n "${VALGRIND}" ]; then - valgrind --tool=${VALGRIND} --suppressions=${TESTDIR}/valgrind.supp \ - ceph_test_rbd_mirror + valgrind ${VALGRIND} --suppressions=${TESTDIR}/valgrind.supp \ + --error-exitcode=1 ceph_test_rbd_mirror else ceph_test_rbd_mirror fi diff --git a/ceph/qa/workunits/rest/test-restful.sh b/ceph/qa/workunits/rest/test-restful.sh new file mode 100755 index 000000000..7beec9fc6 --- /dev/null +++ b/ceph/qa/workunits/rest/test-restful.sh @@ -0,0 +1,16 @@ +#!/bin/sh -ex + +mydir=`dirname $0` + +secret=`ceph config-key get mgr/restful/keys/admin` +active=`ceph mgr dump | jq -r .active_name` +echo "active $active admin secret $secret" + +prefix="mgr/restful/$active" +addr=`ceph config-key get $prefix/server_addr` +port=`ceph config-key get $prefix/server_port` +url="https://$addr:$port" +echo "prefix $prefix url $url" +$mydir/test_mgr_rest_api.py $url $secret + +echo $0 OK diff --git a/ceph/qa/workunits/rest/test.py b/ceph/qa/workunits/rest/test.py index 7bbb6f3cc..565873e51 100755 --- a/ceph/qa/workunits/rest/test.py +++ b/ceph/qa/workunits/rest/test.py @@ -403,7 +403,7 @@ if __name__ == '__main__': expect('osd/reweight?id=0&weight=1', 'PUT', 200, '') for v in ['pg_num', 'pgp_num', 'size', 'min_size', - 'crush_ruleset']: + 'crush_rule']: r = expect('osd/pool/get.json?pool=rbd&var=' + v, 'GET', 200, 'json') assert(v in r.myjson['output']) @@ -418,7 +418,7 @@ if __name__ == '__main__': r = expect('osd/pool/get.json?pool=rbd&var=size', 'GET', 200, 'json') assert(r.myjson['output']['size'] == 2) - r = expect('osd/pool/get.json?pool=rbd&var=crush_ruleset', 'GET', 200, 'json') - assert(r.myjson['output']['crush_ruleset'] == 0) + r = expect('osd/pool/get.json?pool=rbd&var=crush_rule', 'GET', 200, 'json') + assert(r.myjson['output']['crush_rule'] == "replicated_rule") print('OK') diff --git a/ceph/qa/workunits/rest/test_mgr_rest_api.py b/ceph/qa/workunits/rest/test_mgr_rest_api.py new file mode 100755 index 000000000..913438f4c --- /dev/null +++ b/ceph/qa/workunits/rest/test_mgr_rest_api.py @@ -0,0 +1,94 @@ +#! /usr/bin/env python + +import requests +import time +import sys +import json + +# Do not show the stupid message about verify=False. ignore exceptions bc +# this doesn't work on some distros. +try: + from requests.packages.urllib3.exceptions import InsecureRequestWarning + requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) +except: + pass + +if len(sys.argv) < 3: + print("Usage: %s " % sys.argv[0]) + sys.exit(1) + +addr = sys.argv[1] +auth = ('admin', sys.argv[2]) +headers = {'Content-type': 'application/json'} + +request = None + +# Create a pool and get its id +request = requests.post( + addr + '/pool?wait=yes', + data=json.dumps({'name': 'supertestfriends', 'pg_num': 128}), + headers=headers, + verify=False, + auth=auth) +print(request.text) +request = requests.get(addr + '/pool', verify=False, auth=auth) +assert(request.json()[-1]['pool_name'] == 'supertestfriends') +pool_id = request.json()[-1]['pool'] + +# get a mon name +request = requests.get(addr + '/mon', verify=False, auth=auth) +firstmon = request.json()[0]['name'] +print('first mon is %s' % firstmon) + +# get a server name +request = requests.get(addr + '/osd', verify=False, auth=auth) +aserver = request.json()[0]['server'] +print('a server is %s' % aserver) + + +screenplay = [ + ('get', '/', {}), + ('get', '/config/cluster', {}), + ('get', '/crush/rule', {}), + ('get', '/doc', {}), + ('get', '/mon', {}), + ('get', '/mon/' + firstmon, {}), + ('get', '/osd', {}), + ('get', '/osd/0', {}), + ('get', '/osd/0/command', {}), + ('get', '/pool/0', {}), + ('get', '/server', {}), + ('get', '/server/' + aserver, {}), + ('post', '/osd/0/command', {'command': 'scrub'}), + ('post', '/pool?wait=1', {'name': 'supertestfriends', 'pg_num': 128}), + ('patch', '/osd/0', {'in': False}), + ('patch', '/config/osd', {'pause': True}), + ('get', '/config/osd', {}), + ('patch', '/pool/' + str(pool_id), {'size': 2}), + ('patch', '/config/osd', {'pause': False}), + ('patch', '/osd/0', {'in': True}), + ('get', '/pool', {}), + ('delete', '/pool/' + str(pool_id) + '?wait=1', {}), + ('get', '/request?page=0', {}), + ('delete', '/request', {}), + ('get', '/request', {}), +] + +for method, endpoint, args in screenplay: + if method == 'sleep': + time.sleep(endpoint) + continue + url = addr + endpoint + print("URL = " + url) + request = getattr(requests, method)( + url, + data=json.dumps(args), + headers=headers, + verify=False, + auth=auth) + print(request.text) + if request.status_code != 200 or 'error' in request.json(): + print('ERROR: %s request for URL "%s" failed' % (method, url)) + sys.exit(1) + +print('OK') diff --git a/ceph/qa/workunits/rgw/run-s3tests.sh b/ceph/qa/workunits/rgw/run-s3tests.sh index a18a5f051..31c091ede 100755 --- a/ceph/qa/workunits/rgw/run-s3tests.sh +++ b/ceph/qa/workunits/rgw/run-s3tests.sh @@ -11,6 +11,14 @@ port=$2 ## +if [ -e CMakeCache.txt ]; then + BIN_PATH=$PWD/bin +elif [ -e $root_path/../build/CMakeCache.txt ]; then + cd $root_path/../build + BIN_PATH=$PWD/bin +fi +PATH=$PATH:$BIN_PATH + dir=tmp.s3-tests.$$ # clone and bootstrap @@ -19,7 +27,7 @@ cd $dir git clone https://github.com/ceph/s3-tests cd s3-tests git checkout ceph-$branch -./bootstrap +VIRTUALENV_PYTHON=/usr/bin/python2 ./bootstrap cd ../.. # users @@ -31,7 +39,7 @@ radosgw-admin user create --uid=s3test1 --display-name='tester1' \ akey2=access2 skey2=secret2 radosgw-admin user create --uid=s3test2 --display-name='tester2' \ - --access-key=$akey2 --secret=$skey2 --email=teester2@ceph.com + --access-key=$akey2 --secret=$skey2 --email=tester2@ceph.com cat < s3.conf [DEFAULT] diff --git a/ceph/run-make-check.sh b/ceph/run-make-check.sh index c5139e98b..4ec97be2f 100755 --- a/ceph/run-make-check.sh +++ b/ceph/run-make-check.sh @@ -29,6 +29,7 @@ function get_processors() { function run() { local install_cmd + local which_pkg="which" if test -f /etc/redhat-release ; then source /etc/os-release if ! type bc > /dev/null 2>&1 ; then @@ -40,6 +41,8 @@ function run() { else install_cmd="yum install -y" fi + else + which_pkg="debianutils" fi type apt-get > /dev/null 2>&1 && install_cmd="apt-get install -y" @@ -51,7 +54,7 @@ function run() { exit 1 fi if [ -n "$install_cmd" ]; then - $DRY_RUN sudo $install_cmd ccache jq + $DRY_RUN sudo $install_cmd ccache jq $which_pkg else echo "WARNING: Don't know how to install packages" >&2 fi diff --git a/ceph/selinux/ceph.fc b/ceph/selinux/ceph.fc index 31926895c..df47fe10b 100644 --- a/ceph/selinux/ceph.fc +++ b/ceph/selinux/ceph.fc @@ -1,6 +1,7 @@ /etc/rc\.d/init\.d/ceph -- gen_context(system_u:object_r:ceph_initrc_exec_t,s0) /etc/rc\.d/init\.d/radosgw -- gen_context(system_u:object_r:ceph_initrc_exec_t,s0) +/usr/bin/ceph-mgr -- gen_context(system_u:object_r:ceph_exec_t,s0) /usr/bin/ceph-mon -- gen_context(system_u:object_r:ceph_exec_t,s0) /usr/bin/ceph-mds -- gen_context(system_u:object_r:ceph_exec_t,s0) /usr/bin/ceph-osd -- gen_context(system_u:object_r:ceph_exec_t,s0) diff --git a/ceph/selinux/ceph.te b/ceph/selinux/ceph.te index 5c6bb8ea2..272947d1e 100644 --- a/ceph/selinux/ceph.te +++ b/ceph/selinux/ceph.te @@ -108,7 +108,7 @@ allow ceph_t random_device_t:chr_file getattr; allow ceph_t urandom_device_t:chr_file getattr; allow ceph_t self:process setpgid; allow ceph_t var_run_t:dir { write create add_name }; -allow ceph_t var_run_t:file { write create open getattr }; +allow ceph_t var_run_t:file { read write create open getattr }; fsadm_manage_pid(ceph_t) diff --git a/ceph/src/.git_version b/ceph/src/.git_version index cf70c0414..17e73fff5 100644 --- a/ceph/src/.git_version +++ b/ceph/src/.git_version @@ -1,2 +1,2 @@ -f2337d1b42fa49dbb0a93e4048a42762e3dffbbf -v12.0.3 +262617c9f16c55e863693258061c5b25dea5b086 +v12.1.0 diff --git a/ceph/src/CMakeLists.txt b/ceph/src/CMakeLists.txt index c68c5fe14..aa08de7ce 100644 --- a/ceph/src/CMakeLists.txt +++ b/ceph/src/CMakeLists.txt @@ -39,7 +39,9 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas") if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -rdynamic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wstrict-null-sentinel -Woverloaded-virtual") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") + if(NOT WITH_OSD_INSTRUMENT_FUNCTIONS) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") + endif() elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) set(CMAKE_EXE_LINKER_FLAGS "-Wl,-export-dynamic") set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -rdynamic -Wl,-export-dynamic -export-dynamic") @@ -69,11 +71,11 @@ endif() include(CheckCCompilerFlag) if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) - CHECK_C_COMPILER_FLAG("-Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=2" HAS_FORTIFY_SOURCE) + CHECK_C_COMPILER_FLAG("-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" HAS_FORTIFY_SOURCE) if(NOT CMAKE_BUILD_TYPE STREQUAL Debug) if(HAS_FORTIFY_SOURCE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=2") - set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2") + set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2") endif() endif() CHECK_C_COMPILER_FLAG(-fstack-protector-strong HAS_STACK_PROTECT) @@ -90,7 +92,7 @@ if(HAVE_INTEL) endif() execute_process( - COMMAND yasm -f elf64 ${CMAKE_SOURCE_DIR}/src/common/crc32c_intel_fast_asm.S -o /dev/null + COMMAND yasm -f elf64 ${CMAKE_SOURCE_DIR}/src/common/crc32c_intel_fast_asm.s -o /dev/null RESULT_VARIABLE no_yasm OUTPUT_QUIET) if(no_yasm) @@ -113,8 +115,8 @@ else(no_yasm) message(STATUS " we are not x32") set(HAVE_GOOD_YASM_ELF64 1) execute_process(COMMAND yasm -f elf64 -i - ${CMAKE_SOURCE_DIR}/src/erasure-code/isa/isa-l/include/ - ${CMAKE_SOURCE_DIR}/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx2.asm.s + ${CMAKE_SOURCE_DIR}/src/isa-l/include/ + ${CMAKE_SOURCE_DIR}/src/isa-l/erasure_code/gf_vect_dot_prod_avx2.asm -o /dev/null RESULT_VARIABLE rc OUTPUT_QUIET) @@ -200,6 +202,8 @@ endif(USE_NSS) set(GCOV_PREFIX_STRIP 4) +# the src/.git_version file may be written out by make-dist; otherwise +# we pull the git version from .git option(ENABLE_GIT_VERSION "build Ceph with git version string" ON) if(${ENABLE_GIT_VERSION}) get_git_head_revision(GIT_REFSPEC CEPH_GIT_VER) @@ -218,6 +222,17 @@ else(${ENABLE_GIT_VERSION}) set(CEPH_GIT_NICE_VER "Development") endif(${ENABLE_GIT_VERSION}) +# the src/ceph_release file is 3 lines, +# +# +# +# note that the release name is semi-redundant and must match CEPH_RELEASE_* +# definitions in include/rados.h and common/ceph_strings.c. +file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/ceph_release CEPH_RELEASE_FILE) +list(GET CEPH_RELEASE_FILE 0 CEPH_RELEASE) +list(GET CEPH_RELEASE_FILE 1 CEPH_RELEASE_NAME) +list(GET CEPH_RELEASE_FILE 2 CEPH_RELEASE_TYPE) + option(WITH_OCF "build OCF-compliant cluster resource agent" OFF) if(WITH_OCF) add_subdirectory(ocf) @@ -335,6 +350,7 @@ add_library(crush_objs OBJECT ${crush_srcs}) add_subdirectory(json_spirit) include_directories("${CMAKE_SOURCE_DIR}/src/xxHash") +include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/src/rapidjson/include") set(GMOCK_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/src/googletest/googletest/include/gmock") @@ -361,9 +377,7 @@ set(async_rdma_common_srcs) if(HAVE_RDMA) list(APPEND async_rdma_common_srcs msg/async/rdma/Infiniband.cc - msg/async/rdma/Device.cc msg/async/rdma/RDMAConnectedSocketImpl.cc - msg/async/rdma/RDMAConnTCP.cc msg/async/rdma/RDMAServerSocketImpl.cc msg/async/rdma/RDMAStack.cc) endif(HAVE_RDMA) @@ -439,6 +453,7 @@ set(libcommon_files common/TrackedOp.cc common/SloppyCRCMap.cc common/types.cc + common/iso_8601.cc log/Log.cc log/SubsystemMap.cc mon/MonCap.cc @@ -448,6 +463,7 @@ set(libcommon_files msg/simple/Accepter.cc msg/DispatchQueue.cc msg/Message.cc + mon/PGMap.cc osd/ECMsgTypes.cc osd/HitSet.cc common/RefCountedObj.cc @@ -467,6 +483,7 @@ set(libcommon_files ${async_rdma_common_srcs} ${dpdk_common_srcs} msg/msg_types.cc + common/reverse.c common/hobject.cc osd/OSDMap.cc osd/OSDMapMapping.cc @@ -517,10 +534,21 @@ set(libcommon_files common/fs_types.cc common/dns_resolve.cc common/hostname.cc + common/util.cc arch/probe.cc ${auth_files} ${mds_files}) +if(FREEBSD) + list(APPEND libcommon_files common/freebsd_errno.cc) +elseif(DARWIN) + list(APPEND libcommon_files common/darwin_errno.cc) +elseif(SUN) + list(APPEND libcommon_files common/solaris_errno.cc) +elseif(AIX) + list(APPEND libcommon_files common/aix_errno.cc) +endif() + if(HAVE_ARM) list(APPEND libcommon_files arch/arm.c) elseif(HAVE_INTEL) @@ -534,13 +562,14 @@ if(HAVE_INTEL) common/crc32c_intel_fast.c) if(HAVE_GOOD_YASM_ELF64) list(APPEND libcommon_files - common/crc32c_intel_fast_asm.S - common/crc32c_intel_fast_zero_asm.S) + common/crc32c_intel_fast_asm.s + common/crc32c_intel_fast_zero_asm.s) endif(HAVE_GOOD_YASM_ELF64) elseif(HAVE_POWER8) list(APPEND libcommon_files common/crc32c_ppc.c - common/crc32c_ppc_asm.S) + common/crc32c_ppc_asm.S + common/crc32c_ppc_fast_zero_asm.S) endif(HAVE_INTEL) if(LINUX) @@ -557,11 +586,6 @@ if(WITH_LTTNG AND WITH_EVENTTRACE) list(APPEND libcommon_files common/EventTrace.cc) endif() -set(mon_common_files - auth/AuthSessionHandler.cc - auth/cephx/CephxSessionHandler.cc - erasure-code/ErasureCodePlugin.cc) -add_library(mon_common_objs OBJECT ${mon_common_files}) set(common_mountcephfs_files common/armor.c common/safe_io.c @@ -589,13 +613,13 @@ set(ceph_common_objs $) set(ceph_common_deps json_spirit erasure_code rt ${LIB_RESOLV} - ${Boost_THREAD_LIBRARY} - ${Boost_SYSTEM_LIBRARY} - ${Boost_REGEX_LIBRARY} - ${Boost_RANDOM_LIBRARY} - ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${Boost_DATE_TIME_LIBRARY} - ${Boost_IOSTREAMS_LIBRARY} + Boost::thread + Boost::system + Boost::regex + Boost::random + Boost::program_options + Boost::date_time + Boost::iostreams ${BLKID_LIBRARIES} ${Backtrace_LIBRARIES} ${BLKIN_LIBRARIES} @@ -633,7 +657,6 @@ install(TARGETS ceph-common DESTINATION ${CMAKE_INSTALL_PKGLIBDIR}) add_library(common_utf8 STATIC common/utf8.c) -target_link_libraries(common json_spirit common_utf8 erasure_code rt uuid resolv ${CRYPTO_LIBS} ${Boost_LIBRARIES} ${BLKID_LIBRARIES} ${EXECINFO_LIBRARIES} ${BLKIN_LIBRARIES}) if(${WITH_LTTNG}) add_subdirectory(tracing) add_dependencies(common-objs oprequest-tp) @@ -672,7 +695,7 @@ if (WITH_MGR) $) target_include_directories(ceph-mgr PRIVATE "${PYTHON_INCLUDE_DIRS}") target_link_libraries(ceph-mgr osdc client global-static common - ${Boost_PYTHON_LIBRARY} ${PYTHON_LIBRARIES} ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS} ${ALLOC_LIBS}) + Boost::python ${PYTHON_LIBRARIES} ${BLKID_LIBRARIES} ${CMAKE_DL_LIBS} ${ALLOC_LIBS}) install(TARGETS ceph-mgr DESTINATION bin) endif (WITH_MGR) @@ -752,10 +775,6 @@ target_link_libraries(ceph-dencoder install(TARGETS ceph-dencoder DESTINATION bin) # Monitor -set(common_util_src - common/util.cc) -add_library(common_util_obj OBJECT ${common_util_src}) - add_subdirectory(mon) set(ceph_mon_srcs ceph_mon.cc) @@ -840,8 +859,7 @@ add_subdirectory(osd) set(ceph_osd_srcs ceph_osd.cc) -add_executable(ceph-osd ${ceph_osd_srcs} - $) +add_executable(ceph-osd ${ceph_osd_srcs}) add_dependencies(ceph-osd erasure_code_plugins) target_link_libraries(ceph-osd osd os global-static common ${BLKID_LIBRARIES} ${RDMA_LIBRARIES}) @@ -853,10 +871,9 @@ install(TARGETS ceph-osd DESTINATION bin) add_subdirectory(mds) set(ceph_mds_srcs ceph_mds.cc) -add_executable(ceph-mds ${ceph_mds_srcs} - $) +add_executable(ceph-mds ${ceph_mds_srcs}) target_link_libraries(ceph-mds mds ${CMAKE_DL_LIBS} global-static common - ${Boost_THREAD_LIBRARY}) + Boost::thread) install(TARGETS ceph-mds DESTINATION bin) add_subdirectory(erasure-code) @@ -871,21 +888,23 @@ add_subdirectory(compressor) add_subdirectory(tools) -# dmClock +# dmClock (after gmock) -add_subdirectory(dmclock) # after gmock -add_dependencies(tests dmclock-tests dmclock-data-struct-tests) +add_subdirectory(dmclock/src) -if(WITH_TESTS) - install(PROGRAMS - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/dmclock-tests - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/dmclock-data-struct-tests - DESTINATION bin) -endif(WITH_TESTS) +option(WITH_DMCLOCK_TESTS + "enable the build of dmclock-tests and dmclock-data-struct tests binaries" + OFF) +if(WITH_TESTS AND WITH_DMCLOCK_TESTS) + # note: add_test is not being called, so dmclock tests aren't part + # of ceph tests + add_subdirectory(dmclock/test) + add_subdirectory(dmclock/support/test) +endif(WITH_TESTS AND WITH_DMCLOCK_TESTS) -if(HAVE_INTEL) +if(HAVE_INTEL AND HAVE_BETTER_YASM_ELF64) add_subdirectory(crypto/isa-l) -endif(HAVE_INTEL) +endif(HAVE_INTEL AND HAVE_BETTER_YASM_ELF64) if(WITH_TESTS) @@ -942,7 +961,6 @@ install(PROGRAMS install(PROGRAMS ${CMAKE_SOURCE_DIR}/src/ceph-create-keys # ${CMAKE_SOURCE_DIR}/src/ceph-disk - ${CMAKE_SOURCE_DIR}/src/ceph-disk-udev DESTINATION sbin) add_subdirectory(bash_completion) @@ -1058,10 +1076,6 @@ endif(WITH_RADOSGW) install(FILES sample.ceph.conf DESTINATION ${CMAKE_INSTALL_DOCDIR}) -install(FILES - fetch_config - DESTINATION ${CMAKE_INSTALL_DOCDIR} - RENAME sample.fetch_config) # Now create a useable config.h configure_file( diff --git a/ceph/src/auth/AuthServiceHandler.h b/ceph/src/auth/AuthServiceHandler.h index 6bd8bd976..4d8a64937 100644 --- a/ceph/src/auth/AuthServiceHandler.h +++ b/ceph/src/auth/AuthServiceHandler.h @@ -15,11 +15,14 @@ #ifndef CEPH_AUTHSERVICEHANDLER_H #define CEPH_AUTHSERVICEHANDLER_H -#include "include/types.h" -#include "Auth.h" +#include // for NULL +#include // for uint64_t +#include "common/entity_name.h" // for EntityName +#include "include/buffer_fwd.h" // for bufferlist class CephContext; class KeyServer; +struct AuthCapsInfo; struct AuthServiceHandler { protected: diff --git a/ceph/src/ceph-create-keys b/ceph/src/ceph-create-keys index 65ccd4a21..dda58e62e 100755 --- a/ceph/src/ceph-create-keys +++ b/ceph/src/ceph-create-keys @@ -136,6 +136,19 @@ def get_key(cluster, mon_id): ], stdout=f, ) + else: + returncode = subprocess.call( + args=args_prefix + [ + 'auth', + 'caps', + 'client.admin', + 'mon', 'allow *', + 'osd', 'allow *', + 'mds', 'allow *', + 'mgr', 'allow *', + ], + stdout=f, + ) if returncode != 0: if returncode == errno.EPERM or returncode == errno.EACCES: diff --git a/ceph/src/ceph-detect-init/ceph_detect_init/__init__.py b/ceph/src/ceph-detect-init/ceph_detect_init/__init__.py index 78374bef9..fe0a2a787 100644 --- a/ceph/src/ceph-detect-init/ceph_detect_init/__init__.py +++ b/ceph/src/ceph-detect-init/ceph_detect_init/__init__.py @@ -141,23 +141,7 @@ def platform_information(): distro_lower = distro.lower() # this could be an empty string in Debian if not codename and 'debian' in distro_lower: - debian_codenames = { - '8': 'jessie', - '7': 'wheezy', - '6': 'squeeze', - } - major_version = release.split('.')[0] - codename = debian_codenames.get(major_version, '') - - # In order to support newer jessie/sid or wheezy/sid strings - # we test this if sid is buried in the minor, we should use - # sid anyway. - if not codename and '/' in release: - major, minor = release.split('/') - if minor == 'sid': - codename = minor - else: - codename = major + pass # this is an empty string in Oracle elif distro_lower.startswith('oracle linux'): codename = 'OL' + release diff --git a/ceph/src/ceph-detect-init/ceph_detect_init/debian/__init__.py b/ceph/src/ceph-detect-init/ceph_detect_init/debian/__init__.py index 73a7851a3..94217cdfa 100644 --- a/ceph/src/ceph-detect-init/ceph_detect_init/debian/__init__.py +++ b/ceph/src/ceph-detect-init/ceph_detect_init/debian/__init__.py @@ -1,3 +1,6 @@ +import os +import subprocess + distro = None release = None codename = None @@ -8,14 +11,11 @@ def choose_init(): Returns the name of a init system (upstart, sysvinit ...). """ - assert(distro and codename) - if distro.lower() in ('ubuntu', 'linuxmint'): - if codename >= 'vivid': - return 'systemd' - else: - return 'upstart' - if distro.lower() == 'debian': - if codename in ('squeeze', 'wheezy'): - return 'sysvinit' - else: - return 'systemd' + # yes, this is heuristics + if os.path.isdir('/run/systemd/system'): + return 'systemd' + if not subprocess.call('. /lib/lsb/init-functions ; init_is_upstart', + shell=True): + return 'upstart' + if os.path.isfile('/sbin/init') and not os.path.islink('/sbin/init'): + return 'sysvinit' diff --git a/ceph/src/ceph-detect-init/tests/test_all.py b/ceph/src/ceph-detect-init/tests/test_all.py index 263cd9a28..18451bf46 100644 --- a/ceph/src/ceph-detect-init/tests/test_all.py +++ b/ceph/src/ceph-detect-init/tests/test_all.py @@ -65,30 +65,35 @@ class TestCephDetectInit(testtools.TestCase): self.assertEqual('sysvinit', centos.choose_init()) def test_debian(self): - with mock.patch.multiple('ceph_detect_init.debian', - distro='debian', - codename='wheezy'): - self.assertEqual('sysvinit', debian.choose_init()) - with mock.patch.multiple('ceph_detect_init.debian', - distro='debian', - codename='squeeze'): - self.assertEqual('sysvinit', debian.choose_init()) - with mock.patch.multiple('ceph_detect_init.debian', - distro='debian', - codename='jessie'): + with mock.patch.multiple('os.path', + isdir=lambda x: x == '/run/systemd/system'): self.assertEqual('systemd', debian.choose_init()) - with mock.patch.multiple('ceph_detect_init.debian', - distro='ubuntu', - codename='trusty'): - self.assertEqual('upstart', debian.choose_init()) - with mock.patch.multiple('ceph_detect_init.debian', - distro='ubuntu', - codename='vivid'): - self.assertEqual('systemd', debian.choose_init()) - with mock.patch.multiple('ceph_detect_init.debian', - distro='not-debian', - codename='andy'): - self.assertIs(None, debian.choose_init()) + + def mock_call_with_upstart(*args, **kwargs): + if args[0] == '. /lib/lsb/init-functions ; init_is_upstart' and \ + kwargs['shell']: + return 0 + else: + return 1 + with mock.patch.multiple('os.path', + isdir=lambda x: False, + isfile=lambda x: False): + with mock.patch.multiple('subprocess', + call=mock_call_with_upstart): + self.assertEqual('upstart', debian.choose_init()) + with mock.patch.multiple('os.path', + isdir=lambda x: False, + isfile=lambda x: x == '/sbin/init', + islink=lambda x: x != '/sbin/init'): + with mock.patch.multiple('subprocess', + call=lambda *args, **kwargs: 1): + self.assertEqual('sysvinit', debian.choose_init()) + with mock.patch.multiple('os.path', + isdir=lambda x: False, + isfile=lambda x: False): + with mock.patch.multiple('subprocess', + call=lambda *args, **kwargs: 1): + self.assertIs(None, debian.choose_init()) def test_fedora(self): with mock.patch('ceph_detect_init.fedora.release', @@ -183,8 +188,6 @@ class TestCephDetectInit(testtools.TestCase): self.assertEqual('debian', distro.distro) self.assertEqual(False, distro.is_el) self.assertEqual('6.0', distro.release) - self.assertEqual('squeeze', distro.codename) - self.assertEqual('sysvinit', distro.init) with mock.patch.multiple('platform', system=lambda: 'FreeBSD', @@ -251,30 +254,10 @@ class TestCephDetectInit(testtools.TestCase): @mock.patch('platform.system', lambda: 'Linux') def test_platform_information_linux(self): - with mock.patch('platform.linux_distribution', - lambda **kwargs: (('debian', '6.0', ''))): - self.assertEqual(('debian', '6.0', 'squeeze'), - ceph_detect_init.platform_information()) - - with mock.patch('platform.linux_distribution', - lambda **kwargs: (('debian', '7.0', ''))): - self.assertEqual(('debian', '7.0', 'wheezy'), - ceph_detect_init.platform_information()) - with mock.patch('platform.linux_distribution', lambda **kwargs: (('debian', '8.0', ''))): - self.assertEqual(('debian', '8.0', 'jessie'), - ceph_detect_init.platform_information()) - - with mock.patch('platform.linux_distribution', - lambda **kwargs: (('debian', 'jessie/sid', ''))): - self.assertEqual(('debian', 'jessie/sid', 'sid'), - ceph_detect_init.platform_information()) - - with mock.patch('platform.linux_distribution', - lambda **kwargs: (('debian', 'sid/jessie', ''))): - self.assertEqual(('debian', 'sid/jessie', 'sid'), - ceph_detect_init.platform_information()) + self.assertEqual(('debian', '8.0'), + ceph_detect_init.platform_information()[:-1]) with mock.patch('platform.linux_distribution', lambda **kwargs: (('Oracle Linux Server', '7.3', ''))): diff --git a/ceph/src/ceph-disk-udev b/ceph/src/ceph-disk-udev deleted file mode 100755 index 8846d2603..000000000 --- a/ceph/src/ceph-disk-udev +++ /dev/null @@ -1,85 +0,0 @@ -#! /bin/sh - -# Wrapper for the ceph udev rules. Since older versions of udev+blkid -# do not support gpt label fields, this shell script is invoked from -# the udev rule to read the needed gpt label fields and call the -# appropriate ceph OSD functions. - -PARTNO=$1 -NAME=$2 -PARENT_NAME=$3 - -# Get GPT partition type guid -ID_PART_ENTRY_TYPE=$(/usr/sbin/sgdisk --info=${PARTNO} /dev/${PARENT_NAME} | grep "Partition GUID code" | awk '{print $4}' | tr '[:upper:]' '[:lower:]') - -if [ -z "$ID_PART_ENTRY_TYPE" ]; then - exit -fi - -ID_PART_ENTRY_UUID=$(/usr/sbin/sgdisk --info=${PARTNO} /dev/${PARENT_NAME} | grep "Partition unique GUID" | awk '{print $4}' | tr '[:upper:]' '[:lower:]') - -# set up the symlinks -mkdir -p /dev/disk/by-partuuid -ln -sf ../../${NAME} /dev/disk/by-partuuid/$ID_PART_ENTRY_UUID -mkdir -p /dev/disk/by-parttypeuuid -ln -sf ../../${NAME} /dev/disk/by-parttypeuuid/${ID_PART_ENTRY_TYPE}.${ID_PART_ENTRY_UUID} - -case $ID_PART_ENTRY_TYPE in - -45b0969e-9b03-4f30-b4c6-b4b80ceff106) - # JOURNAL_UUID - # activate ceph-tagged journal partitions. - /usr/sbin/ceph-disk -v activate-journal /dev/${NAME} - ;; - -45b0969e-9b03-4f30-b4c6-5ec00ceff106) - # DMCRYPT_JOURNAL_UUID - # Map journal if using dm-crypt - /sbin/cryptsetup --key-file /etc/ceph/dmcrypt-keys/${ID_PART_ENTRY_UUID} --key-size 256 create ${ID_PART_ENTRY_UUID} /dev/${NAME} - ;; - -45b0969e-9b03-4f30-b4c6-35865ceff106) - # DMCRYPT_LUKS_JOURNAL_UUID - # Map journal if using dm-crypt - /sbin/cryptsetup --key-file /etc/ceph/dmcrypt-keys/${ID_PART_ENTRY_UUID} luksOpen /dev/${NAME} ${ID_PART_ENTRY_UUID} - ;; - -4fbd7e29-9d25-41b8-afd0-062c0ceff05d) - # OSD_UUID - # activate ceph-tagged partitions. - /usr/sbin/ceph-disk -v activate /dev/${NAME} - ;; - -4fbd7e29-9d25-41b8-afd0-5ec00ceff05d) - # DMCRYPT_OSD_UUID - # Map data device and activate ceph-tagged partitions - # for dm-crypted data devices - /sbin/cryptsetup --key-file /etc/ceph/dmcrypt-keys/${ID_PART_ENTRY_UUID} --key-size 256 create ${ID_PART_ENTRY_UUID} /dev/${NAME} - bash -c 'while [ ! -e /dev/mapper/${ID_PART_ENTRY_UUID} ];do sleep 1; done' - /usr/sbin/ceph-disk activate /dev/mapper/${ID_PART_ENTRY_UUID} - ;; - -4fbd7e29-9d25-41b8-afd0-35865ceff05d) - # DMCRYPT_LUKS_OSD_UUID - # Map data device and activate ceph-tagged partitions - # for dm-crypted data devices - /sbin/cryptsetup --key-file /etc/ceph/dmcrypt-keys/${ID_PART_ENTRY_UUID} luksOpen /dev/${NAME} ${ID_PART_ENTRY_UUID} - bash -c 'while [ ! -e /dev/mapper/${ID_PART_ENTRY_UUID} ];do sleep 1; done' - /usr/sbin/ceph-disk activate /dev/mapper/${ID_PART_ENTRY_UUID} - ;; - -89c57f98-2fe5-4dc0-89c1-f3ad0ceff2be) - # TOBE_UUID - ;; - -89c57f98-2fe5-4dc0-89c1-5ec00ceff2be) - # DMCRYPT_TOBE_UUID - ;; - -*) - # Not a Ceph device - ;; - -esac - -exit diff --git a/ceph/src/ceph-disk/ceph_disk/main.py b/ceph/src/ceph-disk/ceph_disk/main.py index a98350f99..414a63301 100755 --- a/ceph/src/ceph-disk/ceph_disk/main.py +++ b/ceph/src/ceph-disk/ceph_disk/main.py @@ -546,53 +546,6 @@ def command_check_call(arguments, exit=False): raise -def platform_distro(): - """ - Returns a normalized, lower case string without any leading nor trailing - whitespace that represents the distribution name of the current machine. - """ - distro = platform_information()[0] or '' - return distro.strip().lower() - - -def platform_information(): - if FREEBSD: - distro = platform.system() - release = platform.version().split()[1] - codename = platform.version().split()[3] - version = platform.version().split('-')[0][:-1] - major_version = version.split('.')[0] - major, minor = release.split('.') - else: - distro, release, codename = platform.linux_distribution() - # this could be an empty string in Debian - if not codename and 'debian' in distro.lower(): - debian_codenames = { - '8': 'jessie', - '7': 'wheezy', - '6': 'squeeze', - } - major_version = release.split('.')[0] - codename = debian_codenames.get(major_version, '') - - # In order to support newer jessie/sid, wheezy/sid strings we test - # this if sid is buried in the minor, we should use sid anyway. - if not codename and '/' in release: - major, minor = release.split('/') - if minor == 'sid': - codename = minor - else: - codename = major - # this could be an empty string in Virtuozzo linux - if not codename and 'virtuozzo linux' in distro.lower(): - codename = 'virtuozzo' - - return ( - str(distro).strip(), - str(release).strip(), - str(codename).strip() - ) - # # An alternative block_path implementation would be # @@ -1988,7 +1941,9 @@ class Prepare(object): formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.fill(textwrap.dedent("""\ If the --bluestore argument is given, a bluestore objectstore - will be used instead of the legacy filestore objectstore. + will be created. If --filestore is provided, a legacy FileStore + objectstore will be created. If neither is specified, we default + to BlueStore. When an entire device is prepared for bluestore, two partitions are created. The first partition is for metadata, @@ -2086,9 +2041,16 @@ class PrepareBluestore(Prepare): parser = argparse.ArgumentParser(add_help=False) parser.add_argument( '--bluestore', - action='store_true', default=None, + dest='bluestore', + action='store_true', default=True, help='bluestore objectstore', ) + parser.add_argument( + '--filestore', + dest='bluestore', + action='store_false', + help='filestore objectstore', + ) return parser @staticmethod @@ -2445,15 +2407,22 @@ class PrepareBluestoreBlockDB(PrepareSpace): super(PrepareBluestoreBlockDB, self).__init__(args) def get_space_size(self): - block_size = get_conf( + block_db_size = get_conf( cluster=self.args.cluster, variable='bluestore_block_db_size', ) - if block_size is None: - return 20480 # MB, default value + if block_db_size is None or int(block_db_size) == 0: + block_size = get_conf( + cluster=self.args.cluster, + variable='bluestore_block_size', + ) + if block_size is None: + return 1024 # MB + size = int(block_size) / 100 / 1048576 + return max(size, 1024) # MB else: - return int(block_size) / 1048576 # MB + return int(block_db_size) / 1048576 # MB def desired_partition_number(self): if getattr(self.args, 'block.db') == self.args.data: @@ -2996,6 +2965,11 @@ class PrepareFilestoreData(PrepareData): self.set_data_partition() self.populate_data_path_device(*to_prepare_list) + def populate_data_path(self, path, *to_prepare_list): + super(PrepareFilestoreData, self).populate_data_path(path, + *to_prepare_list) + write_one_line(path, 'type', 'filestore') + class PrepareBluestoreData(PrepareData): @@ -3081,7 +3055,7 @@ def mkfs( '--setgroup', get_ceph_group(), ], ) - else: + elif osd_type == 'filestore': ceph_osd_mkfs( [ 'ceph-osd', @@ -3098,6 +3072,8 @@ def mkfs( '--setgroup', get_ceph_group(), ], ) + else: + raise Error('unrecognized objectstore type %s' % osd_type) def auth_key( @@ -3312,8 +3288,8 @@ def start_daemon( elif os.path.exists(os.path.join(path, 'bsdrc')): command_check_call( [ - '/usr/local/etc/rc.d/ceph start osd.{osd_id}' - .format(osd_id=osd_id), + '/usr/sbin/service', 'ceph', 'start', + 'osd.{osd_id}'.format(osd_id=osd_id), ], ) else: @@ -4877,9 +4853,14 @@ def main_trigger(args): def main_fix(args): # A hash table containing 'path': ('uid', 'gid', blocking, recursive) fix_table = [ - ('/etc/ceph', 'ceph', 'ceph', True, True), + ('/usr/bin/ceph-mon', 'root', 'root', True, False), + ('/usr/bin/ceph-mds', 'root', 'root', True, False), + ('/usr/bin/ceph-osd', 'root', 'root', True, False), + ('/usr/bin/radosgw', 'root', 'root', True, False), + ('/etc/ceph', 'root', 'root', True, True), ('/var/run/ceph', 'ceph', 'ceph', True, True), ('/var/log/ceph', 'ceph', 'ceph', True, True), + ('/var/log/radosgw', 'ceph', 'ceph', True, True), ('/var/lib/ceph', 'ceph', 'ceph', True, False), ] @@ -4934,6 +4915,10 @@ def main_fix(args): # Use find to relabel + chown ~simultaenously if args.all: for directory, uid, gid, blocking, recursive in fix_table: + # Skip directories/files that are not installed + if not os.access(directory, os.F_OK): + continue + c = [ 'find', directory, @@ -4973,6 +4958,10 @@ def main_fix(args): # Fix permissions if args.permissions: for directory, uid, gid, blocking, recursive in fix_table: + # Skip directories/files that are not installed + if not os.access(directory, os.F_OK): + continue + if recursive: c = [ 'chown', @@ -5008,6 +4997,10 @@ def main_fix(args): # Fix SELinux labels if args.selinux: for directory, uid, gid, blocking, recursive in fix_table: + # Skip directories/files that are not installed + if not os.access(directory, os.F_OK): + continue + if recursive: c = [ 'restorecon', @@ -5631,7 +5624,9 @@ def main(argv): path = os.environ.get('PATH', os.defpath) os.environ['PATH'] = args.prepend_to_path + ":" + path - setup_statedir(args.statedir) + if args.func.__name__ != 'main_trigger': + # trigger may run when statedir is unavailable and does not use it + setup_statedir(args.statedir) setup_sysconfdir(args.sysconfdir) global CEPH_PREF_USER diff --git a/ceph/src/ceph-disk/tests/ceph-disk.sh b/ceph/src/ceph-disk/tests/ceph-disk.sh index ae216bc10..793016c30 100755 --- a/ceph/src/ceph-disk/tests/ceph-disk.sh +++ b/ceph/src/ceph-disk/tests/ceph-disk.sh @@ -173,7 +173,7 @@ function test_mark_init() { $mkdir -p $osd_data ${CEPH_DISK} $CEPH_DISK_ARGS \ - prepare --osd-uuid $osd_uuid $osd_data || return 1 + prepare --filestore --osd-uuid $osd_uuid $osd_data || return 1 ${CEPH_DISK} $CEPH_DISK_ARGS \ --verbose \ @@ -221,7 +221,7 @@ function test_activate_dir_magic() { mkdir -p $osd_data/fsid CEPH_ARGS="--fsid $uuid" \ - ${CEPH_DISK} $CEPH_DISK_ARGS prepare $osd_data > $dir/out 2>&1 + ${CEPH_DISK} $CEPH_DISK_ARGS prepare --filestore $osd_data > $dir/out 2>&1 grep --quiet 'Is a directory' $dir/out || return 1 ! [ -f $osd_data/magic ] || return 1 rmdir $osd_data/fsid @@ -229,7 +229,7 @@ function test_activate_dir_magic() { echo successfully prepare the OSD CEPH_ARGS="--fsid $uuid" \ - ${CEPH_DISK} $CEPH_DISK_ARGS prepare $osd_data 2>&1 | tee $dir/out + ${CEPH_DISK} $CEPH_DISK_ARGS prepare --filestore $osd_data 2>&1 | tee $dir/out grep --quiet 'Preparing osd data dir' $dir/out || return 1 grep --quiet $uuid $osd_data/ceph_fsid || return 1 [ -f $osd_data/magic ] || return 1 @@ -237,7 +237,7 @@ function test_activate_dir_magic() { echo will not override an existing OSD CEPH_ARGS="--fsid $($uuidgen)" \ - ${CEPH_DISK} $CEPH_DISK_ARGS prepare $osd_data 2>&1 | tee $dir/out + ${CEPH_DISK} $CEPH_DISK_ARGS prepare --filestore $osd_data 2>&1 | tee $dir/out grep --quiet 'Data dir .* already exists' $dir/out || return 1 grep --quiet $uuid $osd_data/ceph_fsid || return 1 } @@ -272,7 +272,7 @@ function test_activate() { fi ${CEPH_DISK} $CEPH_DISK_ARGS \ - prepare --osd-uuid $osd_uuid $to_prepare || return 1 + prepare --filestore --osd-uuid $osd_uuid $to_prepare || return 1 $timeoutcmd ${CEPH_DISK} $CEPH_DISK_ARGS \ activate \ @@ -308,7 +308,7 @@ function test_activate_dir_bluestore() { ${CEPH_DISK} $CEPH_DISK_ARGS \ prepare --bluestore --block-file --osd-uuid $osd_uuid $to_prepare || return 1 - CEPH_ARGS=" --osd-objectstore=bluestore --bluestore-fsck-on-mount=true --enable_experimental_unrecoverable_data_corrupting_features=* --bluestore-block-db-size=67108864 --bluestore-block-wal-size=134217728 --bluestore-block-size=10737418240 $CEPH_ARGS" \ + CEPH_ARGS=" --osd-objectstore=bluestore --bluestore-fsck-on-mount=true --bluestore-block-db-size=67108864 --bluestore-block-wal-size=134217728 --bluestore-block-size=10737418240 $CEPH_ARGS" \ $timeout $TIMEOUT ${CEPH_DISK} $CEPH_DISK_ARGS \ activate \ --mark-init=none \ @@ -376,7 +376,7 @@ function test_crush_device_class() { $mkdir -p $osd_data ${CEPH_DISK} $CEPH_DISK_ARGS \ - prepare --osd-uuid $osd_uuid \ + prepare --filestore --osd-uuid $osd_uuid \ --crush-device-class CRUSH_CLASS \ $osd_data || return 1 test -f $osd_data/crush_device_class || return 1 diff --git a/ceph/src/ceph-disk/tests/test_main.py b/ceph/src/ceph-disk/tests/test_main.py index 45fe48a16..8c3e08451 100644 --- a/ceph/src/ceph-disk/tests/test_main.py +++ b/ceph/src/ceph-disk/tests/test_main.py @@ -1328,11 +1328,19 @@ class TestCephDiskDeactivateAndDestroy(unittest.TestCase): commands.append(" ".join(x)) return ("", "", None) + class Os(object): + F_OK = 0 + + @staticmethod + def access(x, y): + return True + with patch.multiple( main, command=_command, command_init=lambda x: commands.append(x), command_wait=lambda x: None, + os=Os, ): main.main_fix(args) commands = " ".join(commands) diff --git a/ceph/src/ceph-disk/tests/test_prepare.py b/ceph/src/ceph-disk/tests/test_prepare.py index 6ab8ca49a..28713640a 100644 --- a/ceph/src/ceph-disk/tests/test_prepare.py +++ b/ceph/src/ceph-disk/tests/test_prepare.py @@ -45,7 +45,7 @@ class Base(object): class TestPrepare(Base): - def test_init_dir(self): + def test_init_filestore_dir(self): parser = argparse.ArgumentParser('ceph-disk') subparsers = parser.add_subparsers() main.Prepare.set_subparser(subparsers) @@ -55,6 +55,7 @@ class TestPrepare(Base): args = parser.parse_args([ 'prepare', data, + '--filestore', ]) def set_type(self): @@ -72,7 +73,7 @@ class TestPrepare(Base): @mock.patch('stat.S_ISBLK') @mock.patch('ceph_disk.main.is_partition') - def test_init_dev(self, m_is_partition, m_s_isblk): + def test_init_filestore_dev(self, m_is_partition, m_s_isblk): m_s_isblk.return_value = True parser = argparse.ArgumentParser('ceph-disk') @@ -85,6 +86,7 @@ class TestPrepare(Base): args = parser.parse_args([ 'prepare', data, + '--filestore', ]) prepare = main.Prepare.factory(args) assert isinstance(prepare.data, main.PrepareData) @@ -92,6 +94,29 @@ class TestPrepare(Base): assert isinstance(prepare.journal, main.PrepareJournal) assert prepare.journal.is_device() + def test_init_default_dir(self): + parser = argparse.ArgumentParser('ceph-disk') + subparsers = parser.add_subparsers() + main.Prepare.set_subparser(subparsers) + + data = tempfile.mkdtemp() + main.setup_statedir(data) + args = parser.parse_args([ + 'prepare', + data, + ]) + + def set_type(self): + self.type = self.FILE + with mock.patch.multiple(main.PrepareData, + set_type=set_type): + prepare = main.Prepare.factory(args) + assert isinstance(prepare.data, main.PrepareBluestoreData) + assert prepare.data.is_file() + prepare.prepare() + assert os.path.exists(os.path.join(data, 'fsid')) + shutil.rmtree(data) + def test_set_subparser(self): parser = argparse.ArgumentParser('ceph-disk') subparsers = parser.add_subparsers() diff --git a/ceph/src/ceph-disk/tox.ini b/ceph/src/ceph-disk/tox.ini index f835f409c..a2bc483a2 100644 --- a/ceph/src/ceph-disk/tox.ini +++ b/ceph/src/ceph-disk/tox.ini @@ -16,6 +16,7 @@ deps = ../ceph-detect-init [testenv:py27] +sitepackages=True passenv = CEPH_ROOT CEPH_BIN CEPH_LIB CEPH_BUILD_VIRTUALENV changedir = {env:CEPH_BUILD_DIR} commands = coverage run --append --source=ceph_disk {envbindir}/py.test -vv {toxinidir}/tests/test_main.py diff --git a/ceph/src/ceph.in b/ceph/src/ceph.in index 89b52cecc..756cab644 100755 --- a/ceph/src/ceph.in +++ b/ceph/src/ceph.in @@ -30,12 +30,15 @@ try: except NameError: pass -CEPH_GIT_VER="@CEPH_GIT_VER@" -CEPH_GIT_NICE_VER="@CEPH_GIT_NICE_VER@" +CEPH_GIT_VER = "@CEPH_GIT_VER@" +CEPH_GIT_NICE_VER = "@CEPH_GIT_NICE_VER@" +CEPH_RELEASE = "@CEPH_RELEASE@" +CEPH_RELEASE_NAME = "@CEPH_RELEASE_NAME@" +CEPH_RELEASE_TYPE = "@CEPH_RELEASE_TYPE@" # Flags from src/mon/Monitor.h -FLAG_NOFORWARD = (1 << 0) -FLAG_OBSOLETE = (1 << 1) +FLAG_NOFORWARD = (1 << 0) +FLAG_OBSOLETE = (1 << 1) FLAG_DEPRECATED = (1 << 2) # priorities from src/common/perf_counters.h @@ -56,6 +59,7 @@ MYPATH = os.path.abspath(__file__) MYDIR = os.path.dirname(MYPATH) DEVMODEMSG = '*** DEVELOPER MODE: setting PATH, PYTHONPATH and LD_LIBRARY_PATH ***' + def respawn_in_path(lib_path, pybind_path, pythonlib_path): execv_cmd = ['python'] if 'CEPH_DBG' in os.environ: @@ -71,15 +75,18 @@ def respawn_in_path(lib_path, pybind_path, pythonlib_path): if lib_path_var in os.environ: if lib_path not in os.environ[lib_path_var]: os.environ[lib_path_var] += ':' + lib_path - print(DEVMODEMSG, file=sys.stderr) + if "CEPH_DEV" not in os.environ: + print(DEVMODEMSG, file=sys.stderr) os.execvp(py_binary, execv_cmd + sys.argv) else: os.environ[lib_path_var] = lib_path - print(DEVMODEMSG, file=sys.stderr) + if "CEPH_DEV" not in os.environ: + print(DEVMODEMSG, file=sys.stderr) os.execvp(py_binary, execv_cmd + sys.argv) sys.path.insert(0, os.path.join(MYDIR, pybind_path)) sys.path.insert(0, os.path.join(MYDIR, pythonlib_path)) + def get_pythonlib_dir(): """Returns the name of a distutils build directory""" return "lib.{version[0]}".format(version=sys.version_info) @@ -91,7 +98,6 @@ if os.path.exists(os.path.join(os.getcwd(), "CMakeCache.txt")) \ if l.startswith("ceph_SOURCE_DIR:STATIC="): src_path = l.split("=")[1].strip() - if src_path is None: # Huh, maybe we're not really in a cmake environment? pass @@ -123,7 +129,7 @@ from ceph_argparse import \ matchnum, validate_command, find_cmd_target, \ send_command, json_command, run_in_thread -from ceph_daemon import DaemonWatcher, admin_socket +from ceph_daemon import admin_socket, DaemonWatcher, Termsize # just a couple of globals @@ -140,40 +146,31 @@ else: sys.stdout = codecs.getwriter('utf-8')(raw_stdout) sys.stderr = codecs.getwriter('utf-8')(raw_stderr) + def raw_write(buf): sys.stdout.flush() raw_stdout.write(buf) -############################################################################ def osdids(): ret, outbuf, outs = json_command(cluster_handle, prefix='osd ls') - if ret == -errno.EINVAL: - # try old mon - ret, outbuf, outs = send_command(cluster_handle, cmd=['osd', 'ls']) if ret: raise RuntimeError('Can\'t contact mon for osd list') return [line.decode('utf-8') for line in outbuf.split(b'\n') if line] + def monids(): ret, outbuf, outs = json_command(cluster_handle, prefix='mon dump', - argdict={'format':'json'}) - if ret == -errno.EINVAL: - # try old mon - ret, outbuf, outs = send_command(cluster_handle, - cmd=['mon', 'dump', '--format=json']) + argdict={'format': 'json'}) if ret: raise RuntimeError('Can\'t contact mon for mon list') d = json.loads(outbuf.decode('utf-8')) return [m['name'] for m in d['mons']] + def mdsids(): ret, outbuf, outs = json_command(cluster_handle, prefix='mds dump', - argdict={'format':'json'}) - if ret == -errno.EINVAL: - # try old mon - ret, outbuf, outs = send_command(cluster_handle, - cmd=['mds', 'dump', '--format=json']) + argdict={'format': 'json'}) if ret: raise RuntimeError('Can\'t contact mon for mds list') d = json.loads(outbuf.decode('utf-8')) @@ -183,6 +180,61 @@ def mdsids(): l.append(mdsdict['name']) return l + +def mgrids(): + ret, outbuf, outs = json_command(cluster_handle, prefix='mgr dump', + argdict={'format': 'json'}) + if ret: + raise RuntimeError('Can\'t contact mon for mgr list') + + d = json.loads(outbuf.decode('utf-8')) + l = [] + l.append(d['active_name']) + for i in d['standbys']: + l.append(i['name']) + return l + + +def validate_target(target): + """ + this function will return true iff target is a correct + target, such as mon.a/osd.2/mds.a/mgr. + + target: array, likes ['osd', '2'] + return: bool, or raise RuntimeError + """ + + if len(target) == 2: + # for case "service.id" + service_name, service_id = target[0], target[1] + exist_ids = [] + if service_name == "mon": + exist_ids = monids() + elif service_name == "osd": + exist_ids = osdids() + elif service_name == "mds": + exist_ids = mdsids() + elif service_name == "mgr": + exist_ids = mgrids() + else: + print('WARN: {0} is not a legal service name, should be one of mon/osd/mds/mgr'.format(service_name), + file=sys.stderr) + return False + + if service_id in exist_ids: + return True + else: + print('WARN: the service id you provided does not exist. service id should ' + 'be one of {0}.'.format('/'.join(exist_ids)), file=sys.stderr) + return False + + elif len(target) == 1 and target[0] in ['mgr', 'mon']: + return True + else: + print('WARN: \"{0}\" is not a legal target. it should be one of mon./osd./mds./mgr'.format('.'.join(target)), file=sys.stderr) + return False + + # these args must be passed to all child programs GLOBAL_ARGS = { 'client_id': '--id', @@ -191,6 +243,7 @@ GLOBAL_ARGS = { 'cephconf': '--conf', } + def parse_cmdargs(args=None, target=''): # alias: let the line-wrapping be sane AP = argparse.ArgumentParser @@ -259,6 +312,7 @@ def parse_cmdargs(args=None, target=''): def hdr(s): print('\n', s, '\n', '=' * len(s)) + def do_basic_help(parser, args): """ Print basic parser help @@ -268,6 +322,7 @@ def do_basic_help(parser, args): parser.print_help() print_locally_handled_command_help() + def print_locally_handled_command_help(): hdr("Local commands:") print(""" @@ -287,7 +342,7 @@ daemonperf {type.id | path} list|ls [stat-pats] [priority] """, file=sys.stdout) -def do_extended_help(parser, args): +def do_extended_help(parser, args, target, partial): def help_for_sigs(sigs, partial=None): sys.stdout.write(format_help(parse_json_funcsigs(sigs, 'cli'), partial=partial)) @@ -297,18 +352,18 @@ def do_extended_help(parser, args): prefix='get_command_descriptions', timeout=10) if ret: - print("couldn't get command descriptions for {0}: {1}".\ - format(target, outs), file=sys.stderr) + print("couldn't get command descriptions for {0}: {1} ({2})". + format(target, outs, ret), file=sys.stderr) + return ret else: - help_for_sigs(outbuf.decode('utf-8'), partial) + return help_for_sigs(outbuf.decode('utf-8'), partial) - partial = ' '.join(args) - if (cluster_handle.state == "connected"): - help_for_target(target=('mon', ''), partial=partial) - return 0 + assert(cluster_handle.state == "connected") + return help_for_target(target, partial) DONTSPLIT = string.ascii_letters + '{[<>]}' + def wrap(s, width, indent): """ generator to transform s into a sequence of strings width or shorter, @@ -329,7 +384,7 @@ def wrap(s, width, indent): leader = '' while len(s): - if (len(s) <= width): + if len(s) <= width: # no splitting; just possibly indent result = leader + s s = '' @@ -359,11 +414,12 @@ def wrap(s, width, indent): raise StopIteration + def format_help(cmddict, partial=None): """ Formats all the cmdsigs and helptexts from cmddict into a sorted-by- cmdsig 2-column display, with each column wrapped and indented to - fit into 40 characters. + fit into (terminal_width / 2) characters. """ fullusage = '' @@ -371,15 +427,18 @@ def format_help(cmddict, partial=None): if not cmd['help']: continue - flags = cmd.get('flags') - if (flags is not None and - (flags & (FLAG_OBSOLETE | FLAG_DEPRECATED)) != 0): + flags = cmd.get('flags', 0) + if flags & (FLAG_OBSOLETE | FLAG_DEPRECATED): continue concise = concise_sig(cmd['sig']) if partial and not concise.startswith(partial): continue - siglines = [l for l in wrap(concise, 40, 1)] - helplines = [l for l in wrap(cmd['help'], 39, 1)] + width = Termsize().cols - 1 # 1 for the line between sig and help + sig_width = int(width / 2) + # make sure width == sig_width + help_width, even (width % 2 > 0) + help_width = int(width / 2) + (width % 2) + siglines = [l for l in wrap(concise, sig_width, 1)] + helplines = [l for l in wrap(cmd['help'], help_width, 1)] # make lists the same length maxlen = max(len(siglines), len(helplines)) @@ -387,14 +446,14 @@ def format_help(cmddict, partial=None): helplines.extend([''] * (maxlen - len(helplines))) # so we can zip them for output - for (s, h) in zip(siglines, helplines): - fullusage += '{0:40s} {1}\n'.format(s, h) + for s, h in zip(siglines, helplines): + fullusage += '{s:{w}s} {h}\n'.format(s=s, h=h, w=sig_width) return fullusage def ceph_conf(parsed_args, field, name): - args=['ceph-conf'] + args = ['ceph-conf'] if name: args.extend(['--name', name]) @@ -413,7 +472,7 @@ def ceph_conf(parsed_args, field, name): stdout=subprocess.PIPE, stderr=subprocess.PIPE) outdata, errdata = p.communicate() - if (len(errdata)): + if len(errdata): raise RuntimeError('unable to get conf option %s for %s: %s' % (field, name, errdata)) return outdata.rstrip() @@ -475,12 +534,12 @@ def new_style_command(parsed_args, cmdargs, target, sigdict, inbuf, verbose): try: target = find_cmd_target(cmdargs) except Exception as e: - print('error handling command target: {0}'.format(e), - file=sys.stderr) + print('error handling command target: {0}'.format(e), + file=sys.stderr) continue if len(cmdargs) and cmdargs[0] == 'tell': - print('Can not use \'tell\' in interactive mode.', - file=sys.stderr) + print('Can not use \'tell\' in interactive mode.', + file=sys.stderr) continue valid_dict = validate_command(sigdict, cmdargs, verbose) if valid_dict: @@ -493,8 +552,8 @@ def new_style_command(parsed_args, cmdargs, target, sigdict, inbuf, verbose): argdict=valid_dict) if ret: ret = abs(ret) - print('Error: {0} {1}'.format(ret, errno.errorcode.get(ret, 'Unknown')), - file=sys.stderr) + print('Error: {0} {1}'.format(ret, errno.errorcode.get(ret, 'Unknown')), + file=sys.stderr) if outbuf: print(outbuf) if outs: @@ -557,24 +616,21 @@ def complete(sigdict, args, target): return 0 -### -# ping a monitor -### def ping_monitor(cluster_handle, name, timeout): if 'mon.' not in name: print('"ping" expects a monitor to ping; try "ping mon."', file=sys.stderr) return 1 mon_id = name[len('mon.'):] - if (mon_id == '*') : + if mon_id == '*': run_in_thread(cluster_handle.connect, timeout=timeout) - for m in monids() : + for m in monids(): s = run_in_thread(cluster_handle.ping_monitor, m) if s is None: print("mon.{0}".format(m) + '\n' + "Error connecting to monitor.") else: print("mon.{0}".format(m) + '\n' + s) - else : + else: s = run_in_thread(cluster_handle.ping_monitor, mon_id) print(s) return 0 @@ -609,8 +665,8 @@ def maybe_daemon_command(parsed_args, childargs): # for both: childargs = childargs[2:] else: - print('{0} requires at least {1} arguments'.format(childargs[0], require_args), - file=sys.stderr) + print('{0} requires at least {1} arguments'.format(childargs[0], require_args), + file=sys.stderr) return True, errno.EINVAL if sockpath and daemon_perf: @@ -633,6 +689,7 @@ def isnum(s): except ValueError: return False + def daemonperf(childargs, sockpath): """ Handle daemonperf command; returns errno or 0 @@ -670,7 +727,7 @@ def daemonperf(childargs, sockpath): arg = childargs.pop(0) # 'list'? if arg in ['list', 'ls']: - do_list = True; + do_list = True continue # prio? prio = prio_from_name(arg) @@ -707,9 +764,6 @@ def daemonperf(childargs, sockpath): return 0 -### -# main -### def main(): ceph_args = os.environ.get('CEPH_ARGS') @@ -722,7 +776,11 @@ def main(): parser, parsed_args, childargs = parse_cmdargs() if parsed_args.version: - print('ceph version {0} ({1})'.format(CEPH_GIT_NICE_VER, CEPH_GIT_VER)) # noqa + print('ceph version {0} ({1}) {2} ({3})'.format( + CEPH_GIT_NICE_VER, + CEPH_GIT_VER, + CEPH_RELEASE_NAME, + CEPH_RELEASE_TYPE)) # noqa return 0 global verbose @@ -732,8 +790,8 @@ def main(): print("parsed_args: {0}, childargs: {1}".format(parsed_args, childargs), file=sys.stderr) if parsed_args.admin_socket_nope: - print('--admin-socket is used by daemons; '\ - 'you probably mean --admin-daemon/daemon', file=sys.stderr) + print('--admin-socket is used by daemons; ' + 'you probably mean --admin-daemon/daemon', file=sys.stderr) return 1 # pass on --id, --name, --conf @@ -771,9 +829,9 @@ def main(): # and then set the keys from the dict. So we must do these # "pre-file defaults" first (see common_preinit in librados) conf_defaults = { - 'log_to_stderr':'true', - 'err_to_stderr':'true', - 'log_flush_on_exit':'true', + 'log_to_stderr': 'true', + 'err_to_stderr': 'true', + 'log_flush_on_exit': 'true', } if 'injectargs' in childargs: @@ -781,8 +839,8 @@ def main(): injectargs = childargs[position:] childargs = childargs[:position] if verbose: - print('Separate childargs {0} from injectargs {1}'.format(childargs, injectargs), - file=sys.stderr) + print('Separate childargs {0} from injectargs {1}'.format(childargs, injectargs), + file=sys.stderr) else: injectargs = None @@ -812,11 +870,11 @@ def main(): # special deprecation warning for 'ceph tell' # someday 'mds' will be here too - if len(childargs) >= 2 and \ - childargs[0] in ['mon', 'osd'] and \ - childargs[1] == 'tell': - print('"{0} tell" is deprecated; try "tell {0}. [options...]" instead (id can be "*") '.format(childargs[0]), - file=sys.stderr) + if (len(childargs) >= 2 and + childargs[0] in ['mon', 'osd'] and + childargs[1] == 'tell'): + print('"{0} tell" is deprecated; try "tell {0}. [options...]" instead (id can be "*") '.format(childargs[0]), + file=sys.stderr) return 1 if parsed_args.help: @@ -832,7 +890,7 @@ def main(): print('"ping" requires a monitor name as argument: "ping mon."', file=sys.stderr) return 1 if parsed_args.completion: - #for completion let timeout be really small + # for completion let timeout be really small timeout = 3 try: if childargs and childargs[0] == 'ping': @@ -847,10 +905,18 @@ def main(): except Exception as e: print(str(e), file=sys.stderr) return 1 - if parsed_args.help: - return do_extended_help(parser, childargs) + return do_extended_help(parser, childargs, ('mon', ''), ' '.join(childargs)) + # implement "tell service.id help" + if len(childargs) >= 3 and childargs[0] == 'tell' and childargs[2] == 'help': + target = childargs[1].split('.') + if validate_target(target): + return do_extended_help(parser, childargs, target, None) + else: + print('target {0} doesn\'t exists, please pass correct target to tell command, such as mon.a/' + 'osd.1/mds.a/mgr'.format(childargs[1]), file=sys.stderr) + return 1 # implement -w/--watch_* # This is ugly, but Namespace() isn't quite rich enough. level = '' @@ -869,12 +935,6 @@ def main(): # first do a ceph status ret, outbuf, outs = json_command(cluster_handle, prefix='status') - if ret == -errno.EINVAL: - # try old mon - ret, outbuf, outs = send_command(cluster_handle, cmd=['status']) - # old mon returns status to outs...ick - if ret == 0: - outbuf += outs if ret: print("status query failed: ", outs, file=sys.stderr) return ret @@ -932,8 +992,8 @@ def main(): childargs = injectargs if not len(childargs): print('"{0} tell" requires additional arguments.'.format(sys.argv[0]), - 'Try "{0} tell [options...]" instead.'.format(sys.argv[0]), - file=sys.stderr) + 'Try "{0} tell [options...]" instead.'.format(sys.argv[0]), + file=sys.stderr) return errno.EINVAL # fetch JSON sigs from command @@ -960,66 +1020,51 @@ def main(): ret, outbuf, outs = json_command(cluster_handle, target=target, prefix='get_command_descriptions') - compat = False - if ret == -errno.EINVAL: - # send command to old monitor or OSD - if verbose: - print(prefix + '{0} to old {1}'.format(' '.join(childargs), target[0])) - compat = True - if parsed_args.output_format: - childargs.extend(['--format', parsed_args.output_format]) - ret, outbuf, outs = send_command(cluster_handle, target, childargs, - inbuf) - - if ret == -errno.EINVAL: - # did we race with a mon upgrade? try again! - ret, outbuf, outs = json_command(cluster_handle, target=target, - prefix='get_command_descriptions') - if ret == 0: - compat = False # yep, carry on - if not compat: - if ret: - if ret < 0: - outs = 'problem getting command descriptions from {0}.{1}'.format(*target) - else: - sigdict = parse_json_funcsigs(outbuf.decode('utf-8'), 'cli') + if ret: + where = '{0}.{1}'.format(*target) + if ret > 0: + raise RuntimeError('Unexpeceted return code from {0}: {1}'. + format(where, ret)) + outs = 'problem getting command descriptions from {0}'.format(where) + else: + sigdict = parse_json_funcsigs(outbuf.decode('utf-8'), 'cli') - if parsed_args.completion: - return complete(sigdict, childargs, target) + if parsed_args.completion: + return complete(sigdict, childargs, target) - ret, outbuf, outs = new_style_command(parsed_args, childargs, target, - sigdict, inbuf, verbose) + ret, outbuf, outs = new_style_command(parsed_args, childargs, + target, sigdict, inbuf, + verbose) - # debug tool: send any successful command *again* to - # verify that it is idempotent. - if not ret and 'CEPH_CLI_TEST_DUP_COMMAND' in os.environ: - ret, outbuf, outs = new_style_command(parsed_args, childargs, target, - sigdict, inbuf, verbose) - if ret < 0: - ret = -ret - print(prefix + 'Second attempt of previously successful command failed with {0}: {1}'.format(errno.errorcode.get(ret, 'Unknown'), outs), - file=sys.stderr) + # debug tool: send any successful command *again* to + # verify that it is idempotent. + if not ret and 'CEPH_CLI_TEST_DUP_COMMAND' in os.environ: + ret, outbuf, outs = new_style_command(parsed_args, childargs, + target, sigdict, inbuf, + verbose) + if ret < 0: + ret = -ret + print(prefix + + 'Second attempt of previously successful command ' + 'failed with {0}: {1}'.format( + errno.errorcode.get(ret, 'Unknown'), outs), + file=sys.stderr) if ret < 0: ret = -ret - print(u'Error {0}: {1}'.format(errno.errorcode.get(ret, 'Unknown'), outs), file=sys.stderr) + errstr = errno.errorcode.get(ret, 'Unknown') + print(u'Error {0}: {1}'.format(errstr, outs), file=sys.stderr) if len(targets) > 1: final_ret = ret else: return ret - # this assumes outs never has useful command output, only status - if compat: - if ret == 0: - # old cli/mon would send status string to stdout on non-error - print(outs) - else: - if outs: - print(prefix + outs, file=sys.stderr) + if outs: + print(prefix + outs, file=sys.stderr) sys.stdout.flush() - if (parsed_args.output_file): + if parsed_args.output_file: outf.write(outbuf) else: # hack: old code printed status line before many json outputs @@ -1027,8 +1072,7 @@ def main(): # to satisfy consumers that skip the first line, but not annoy # consumers that don't. if parsed_args.output_format and \ - parsed_args.output_format.startswith('json') and \ - not compat: + parsed_args.output_format.startswith('json'): print() # if we are prettifying things, normalize newlines. sigh. @@ -1046,7 +1090,7 @@ def main(): sys.stdout.flush() - if (parsed_args.output_file): + if parsed_args.output_file: outf.close() if final_ret: diff --git a/ceph/src/ceph_mds.cc b/ceph/src/ceph_mds.cc index 7c2a95034..b6cff8348 100644 --- a/ceph/src/ceph_mds.cc +++ b/ceph/src/ceph_mds.cc @@ -53,7 +53,7 @@ using namespace std; static void usage() { - cout << "usage: ceph-mds -i name [flags] [[--hot-standby][rank]]\n" + cout << "usage: ceph-mds -i [flags] [[--hot-standby][rank]]\n" << " -m monitorip:port\n" << " connect to monitor at given address\n" << " --debug_mds n\n" diff --git a/ceph/src/ceph_mgr.cc b/ceph/src/ceph_mgr.cc index c3fcc276c..051bed709 100644 --- a/ceph/src/ceph_mgr.cc +++ b/ceph/src/ceph_mgr.cc @@ -24,6 +24,12 @@ #include "mgr/MgrStandby.h" +static void usage() +{ + cout << "usage: ceph-mgr -i [flags]\n" + << std::endl; + generic_server_usage(); +} /** * A short main() which just instantiates a MgrStandby and @@ -43,16 +49,14 @@ int main(int argc, const char **argv) // Handle --help if ((args.size() == 1 && (std::string(args[0]) == "--help" || std::string(args[0]) == "-h"))) { - MgrStandby mgr; - mgr.usage(); - return 0; + usage(); } global_init_daemonize(g_ceph_context); global_init_chdir(g_ceph_context); common_init_finish(g_ceph_context); - MgrStandby mgr; + MgrStandby mgr(argc, argv); int rc = mgr.init(); if (rc != 0) { std::cerr << "Error in initialization: " << cpp_strerror(rc) << std::endl; diff --git a/ceph/src/ceph_mon.cc b/ceph/src/ceph_mon.cc index 6e8fd1d57..0b5d4edfd 100644 --- a/ceph/src/ceph_mon.cc +++ b/ceph/src/ceph_mon.cc @@ -108,7 +108,7 @@ int check_mon_data_exists() struct stat buf; if (::stat(mon_data.c_str(), &buf)) { if (errno != ENOENT) { - cerr << "stat(" << mon_data << ") " << cpp_strerror(errno) << std::endl; + derr << "stat(" << mon_data << ") " << cpp_strerror(errno) << dendl; } return -errno; } @@ -132,7 +132,7 @@ int check_mon_data_empty() DIR *dir = ::opendir(mon_data.c_str()); if (!dir) { - cerr << "opendir(" << mon_data << ") " << cpp_strerror(errno) << std::endl; + derr << "opendir(" << mon_data << ") " << cpp_strerror(errno) << dendl; return -errno; } int code = 0; @@ -147,7 +147,7 @@ int check_mon_data_empty() } } if (!de && errno) { - cerr << "readdir(" << mon_data << ") " << cpp_strerror(errno) << std::endl; + derr << "readdir(" << mon_data << ") " << cpp_strerror(errno) << dendl; code = -errno; } @@ -158,25 +158,26 @@ int check_mon_data_empty() static void usage() { - cerr << "usage: ceph-mon -i monid [flags]" << std::endl; - cerr << " --debug_mon n\n"; - cerr << " debug monitor level (e.g. 10)\n"; - cerr << " --mkfs\n"; - cerr << " build fresh monitor fs\n"; - cerr << " --force-sync\n"; - cerr << " force a sync from another mon by wiping local data (BE CAREFUL)\n"; - cerr << " --yes-i-really-mean-it\n"; - cerr << " mandatory safeguard for --force-sync\n"; - cerr << " --compact\n"; - cerr << " compact the monitor store\n"; - cerr << " --osdmap \n"; - cerr << " only used when --mkfs is provided: load the osdmap from \n"; - cerr << " --inject-monmap \n"; - cerr << " write the monmap to the local monitor store and exit\n"; - cerr << " --extract-monmap \n"; - cerr << " extract the monmap from the local monitor store and exit\n"; - cerr << " --mon-data \n"; - cerr << " where the mon store and keyring are located\n"; + cout << "usage: ceph-mon -i [flags]\n" + << " --debug_mon n\n" + << " debug monitor level (e.g. 10)\n" + << " --mkfs\n" + << " build fresh monitor fs\n" + << " --force-sync\n" + << " force a sync from another mon by wiping local data (BE CAREFUL)\n" + << " --yes-i-really-mean-it\n" + << " mandatory safeguard for --force-sync\n" + << " --compact\n" + << " compact the monitor store\n" + << " --osdmap \n" + << " only used when --mkfs is provided: load the osdmap from \n" + << " --inject-monmap \n" + << " write the monmap to the local monitor store and exit\n" + << " --extract-monmap \n" + << " extract the monmap from the local monitor store and exit\n" + << " --mon-data \n" + << " where the mon store and keyring are located\n" + << std::endl; generic_server_usage(); } @@ -272,23 +273,23 @@ int main(int argc, const char **argv) } } if (!args.empty()) { - cerr << "too many arguments: " << args << std::endl; + derr << "too many arguments: " << args << dendl; usage(); } if (force_sync && !yes_really) { - cerr << "are you SURE you want to force a sync? this will erase local data and may\n" - << "break your mon cluster. pass --yes-i-really-mean-it if you do." << std::endl; + derr << "are you SURE you want to force a sync? this will erase local data and may\n" + << "break your mon cluster. pass --yes-i-really-mean-it if you do." << dendl; exit(1); } if (g_conf->mon_data.empty()) { - cerr << "must specify '--mon-data=foo' data path" << std::endl; + derr << "must specify '--mon-data=foo' data path" << dendl; usage(); } if (g_conf->name.get_id().empty()) { - cerr << "must specify id (--id or --name mon.)" << std::endl; + derr << "must specify id (--id or --name mon.)" << dendl; usage(); } @@ -298,25 +299,25 @@ int main(int argc, const char **argv) int err = check_mon_data_exists(); if (err == -ENOENT) { if (::mkdir(g_conf->mon_data.c_str(), 0755)) { - cerr << "mkdir(" << g_conf->mon_data << ") : " - << cpp_strerror(errno) << std::endl; + derr << "mkdir(" << g_conf->mon_data << ") : " + << cpp_strerror(errno) << dendl; exit(1); } } else if (err < 0) { - cerr << "error opening '" << g_conf->mon_data << "': " - << cpp_strerror(-err) << std::endl; + derr << "error opening '" << g_conf->mon_data << "': " + << cpp_strerror(-err) << dendl; exit(-err); } err = check_mon_data_empty(); if (err == -ENOTEMPTY) { // Mon may exist. Let the user know and exit gracefully. - cerr << "'" << g_conf->mon_data << "' already exists and is not empty" - << ": monitor may already exist" << std::endl; + derr << "'" << g_conf->mon_data << "' already exists and is not empty" + << ": monitor may already exist" << dendl; exit(0); } else if (err < 0) { - cerr << "error checking if '" << g_conf->mon_data << "' is empty: " - << cpp_strerror(-err) << std::endl; + derr << "error checking if '" << g_conf->mon_data << "' is empty: " + << cpp_strerror(-err) << dendl; exit(-err); } @@ -333,7 +334,7 @@ int main(int argc, const char **argv) if (g_conf->monmap.length()) { int err = monmapbl.read_file(g_conf->monmap.c_str(), &error); if (err < 0) { - cerr << argv[0] << ": error reading " << g_conf->monmap << ": " << error << std::endl; + derr << argv[0] << ": error reading " << g_conf->monmap << ": " << error << dendl; exit(1); } try { @@ -343,13 +344,16 @@ int main(int argc, const char **argv) monmap.set_epoch(0); } catch (const buffer::error& e) { - cerr << argv[0] << ": error decoding monmap " << g_conf->monmap << ": " << e.what() << std::endl; + derr << argv[0] << ": error decoding monmap " << g_conf->monmap << ": " << e.what() << dendl; exit(1); } } else { - int err = monmap.build_initial(g_ceph_context, cerr); + ostringstream oss; + int err = monmap.build_initial(g_ceph_context, oss); + if (oss.tellp()) + derr << oss.str() << dendl; if (err < 0) { - cerr << argv[0] << ": warning: no initial monitors; must use admin socket to feed hints" << std::endl; + derr << argv[0] << ": warning: no initial monitors; must use admin socket to feed hints" << dendl; } // am i part of the initial quorum? @@ -395,7 +399,7 @@ int main(int argc, const char **argv) } if (monmap.fsid.is_zero()) { - cerr << argv[0] << ": generated monmap has no fsid; use '--fsid '" << std::endl; + derr << argv[0] << ": generated monmap has no fsid; use '--fsid '" << dendl; exit(10); } @@ -405,18 +409,21 @@ int main(int argc, const char **argv) if (osdmapfn.length()) { err = osdmapbl.read_file(osdmapfn.c_str(), &error); if (err < 0) { - cerr << argv[0] << ": error reading " << osdmapfn << ": " - << error << std::endl; + derr << argv[0] << ": error reading " << osdmapfn << ": " + << error << dendl; exit(1); } } // go MonitorDBStore store(g_conf->mon_data); - int r = store.create_and_open(cerr); + ostringstream oss; + int r = store.create_and_open(oss); + if (oss.tellp()) + derr << oss.str() << dendl; if (r < 0) { - cerr << argv[0] << ": error opening mon data directory at '" - << g_conf->mon_data << "': " << cpp_strerror(r) << std::endl; + derr << argv[0] << ": error opening mon data directory at '" + << g_conf->mon_data << "': " << cpp_strerror(r) << dendl; exit(1); } assert(r == 0); @@ -424,7 +431,7 @@ int main(int argc, const char **argv) Monitor mon(g_ceph_context, g_conf->name.get_id(), &store, 0, 0, &monmap); r = mon.mkfs(osdmapbl); if (r < 0) { - cerr << argv[0] << ": error creating monfs: " << cpp_strerror(r) << std::endl; + derr << argv[0] << ": error creating monfs: " << cpp_strerror(r) << dendl; exit(1); } store.close(); @@ -435,12 +442,12 @@ int main(int argc, const char **argv) err = check_mon_data_exists(); if (err < 0 && err == -ENOENT) { - cerr << "monitor data directory at '" << g_conf->mon_data << "'" - << " does not exist: have you run 'mkfs'?" << std::endl; + derr << "monitor data directory at '" << g_conf->mon_data << "'" + << " does not exist: have you run 'mkfs'?" << dendl; exit(1); } else if (err < 0) { - cerr << "error accessing monitor data directory at '" - << g_conf->mon_data << "': " << cpp_strerror(-err) << std::endl; + derr << "error accessing monitor data directory at '" + << g_conf->mon_data << "': " << cpp_strerror(-err) << dendl; exit(1); } @@ -451,8 +458,8 @@ int main(int argc, const char **argv) exit(1); } else if (err < 0 && err != -ENOTEMPTY) { // we don't want an empty data dir by now - cerr << "error accessing '" << g_conf->mon_data << "': " - << cpp_strerror(-err) << std::endl; + derr << "error accessing '" << g_conf->mon_data << "': " + << cpp_strerror(-err) << dendl; exit(1); } @@ -461,17 +468,17 @@ int main(int argc, const char **argv) ceph_data_stats_t stats; int err = get_fs_stats(stats, g_conf->mon_data.c_str()); if (err < 0) { - cerr << "error checking monitor data's fs stats: " << cpp_strerror(err) - << std::endl; + derr << "error checking monitor data's fs stats: " << cpp_strerror(err) + << dendl; exit(-err); } if (stats.avail_percent <= g_conf->mon_data_avail_crit) { - cerr << "error: monitor data filesystem reached concerning levels of" + derr << "error: monitor data filesystem reached concerning levels of" << " available storage space (available: " << stats.avail_percent << "% " << prettybyte_t(stats.byte_avail) << ")\nyou may adjust 'mon data avail crit' to a lower value" << " to make this go away (default: " << g_conf->mon_data_avail_crit - << "%)\n" << std::endl; + << "%)\n" << dendl; exit(ENOSPC); } } @@ -484,13 +491,13 @@ int main(int argc, const char **argv) string err_msg; err = prefork.prefork(err_msg); if (err < 0) { - cerr << err_msg << std::endl; + derr << err_msg << dendl; prefork.exit(err); } if (prefork.is_parent()) { err = prefork.parent_wait(err_msg); if (err < 0) - cerr << err_msg << std::endl; + derr << err_msg << dendl; prefork.exit(err); } global_init_postfork_start(g_ceph_context); @@ -506,11 +513,16 @@ int main(int argc, const char **argv) } MonitorDBStore *store = new MonitorDBStore(g_conf->mon_data); - err = store->open(std::cerr); - if (err < 0) { - derr << "error opening mon data directory at '" - << g_conf->mon_data << "': " << cpp_strerror(err) << dendl; - prefork.exit(1); + { + ostringstream oss; + err = store->open(oss); + if (oss.tellp()) + derr << oss.str() << dendl; + if (err < 0) { + derr << "error opening mon data directory at '" + << g_conf->mon_data << "': " << cpp_strerror(err) << dendl; + prefork.exit(1); + } } bufferlist magicbl; @@ -584,7 +596,7 @@ int main(int argc, const char **argv) try { monmap.decode(mapbl); } catch (const buffer::error& e) { - cerr << "can't decode monmap: " << e.what() << std::endl; + derr << "can't decode monmap: " << e.what() << dendl; } } else { derr << "unable to obtain a monmap: " << cpp_strerror(err) << dendl; @@ -632,7 +644,10 @@ int main(int argc, const char **argv) << ipaddr << dendl; } else { MonMap tmpmap; - int err = tmpmap.build_initial(g_ceph_context, cerr); + ostringstream oss; + int err = tmpmap.build_initial(g_ceph_context, oss); + if (oss.tellp()) + derr << oss.str() << dendl; if (err < 0) { derr << argv[0] << ": error generating initial monmap: " << cpp_strerror(err) << dendl; @@ -723,7 +738,10 @@ int main(int argc, const char **argv) if (force_sync) { derr << "flagging a forced sync ..." << dendl; - mon->sync_force(NULL, cerr); + ostringstream oss; + mon->sync_force(NULL, oss); + if (oss.tellp()) + derr << oss.str() << dendl; } err = mon->preinit(); diff --git a/ceph/src/ceph_osd.cc b/ceph/src/ceph_osd.cc index f4d28751a..a27ffb854 100644 --- a/ceph/src/ceph_osd.cc +++ b/ceph/src/ceph_osd.cc @@ -56,6 +56,10 @@ TracepointProvider::Traits osd_tracepoint_traits("libosd_tp.so", "osd_tracing"); TracepointProvider::Traits os_tracepoint_traits("libos_tp.so", "osd_objectstore_tracing"); +#ifdef WITH_OSD_INSTRUMENT_FUNCTIONS +TracepointProvider::Traits cyg_profile_traits("libcyg_profile_tp.so", + "osd_function_tracing"); +#endif } // anonymous namespace @@ -69,11 +73,12 @@ void handle_osd_signal(int signum) static void usage() { - cout << "usage: ceph-osd -i \n" + cout << "usage: ceph-osd -i [flags]\n" << " --osd-data PATH data directory\n" << " --osd-journal PATH\n" << " journal file or block device\n" << " --mkfs create a [new] data directory\n" + << " --mkkey generate a new secret key. This is normally used in combination with --mkfs\n" << " --convert-filestore\n" << " run any pending upgrade operations\n" << " --flush-journal flush all data out of journal\n" @@ -492,9 +497,6 @@ flushjournal_out: boost::scoped_ptr client_byte_throttler( new Throttle(g_ceph_context, "osd_client_bytes", g_conf->osd_client_message_size_cap)); - boost::scoped_ptr client_msg_throttler( - new Throttle(g_ceph_context, "osd_client_messages", - g_conf->osd_client_message_cap)); // All feature bits 0 - 34 should be present from dumpling v0.67 forward uint64_t osd_required = @@ -505,7 +507,7 @@ flushjournal_out: ms_public->set_default_policy(Messenger::Policy::stateless_server(0)); ms_public->set_policy_throttlers(entity_name_t::TYPE_CLIENT, client_byte_throttler.get(), - client_msg_throttler.get()); + nullptr); ms_public->set_policy(entity_name_t::TYPE_MON, Messenger::Policy::lossy_client(CEPH_FEATURE_UID | CEPH_FEATURE_PGID64 | @@ -582,6 +584,9 @@ flushjournal_out: TracepointProvider::initialize(g_ceph_context); TracepointProvider::initialize(g_ceph_context); +#ifdef WITH_OSD_INSTRUMENT_FUNCTIONS + TracepointProvider::initialize(g_ceph_context); +#endif MonClient mc(g_ceph_context); if (mc.build_initial_monmap() < 0) @@ -669,7 +674,6 @@ flushjournal_out: delete ms_objecter; client_byte_throttler.reset(); - client_msg_throttler.reset(); // cd on exit, so that gmon.out (if any) goes into a separate directory for each node. char s[20]; diff --git a/ceph/src/ceph_release b/ceph/src/ceph_release new file mode 100644 index 000000000..cfcf789ec --- /dev/null +++ b/ceph/src/ceph_release @@ -0,0 +1,3 @@ +12 +luminous +dev diff --git a/ceph/src/ceph_ver.h.in.cmake b/ceph/src/ceph_ver.h.in.cmake index 9c269cdf5..d7e1c8e9b 100644 --- a/ceph/src/ceph_ver.h.in.cmake +++ b/ceph/src/ceph_ver.h.in.cmake @@ -3,5 +3,8 @@ #define CEPH_GIT_VER @CEPH_GIT_VER@ #define CEPH_GIT_NICE_VER "@CEPH_GIT_NICE_VER@" +#define CEPH_RELEASE @CEPH_RELEASE@ +#define CEPH_RELEASE_NAME "@CEPH_RELEASE_NAME@" +#define CEPH_RELEASE_TYPE "@CEPH_RELEASE_TYPE@" #endif diff --git a/ceph/src/civetweb/src/civetweb.c b/ceph/src/civetweb/src/civetweb.c index bc647469b..4d133baa4 100644 --- a/ceph/src/civetweb/src/civetweb.c +++ b/ceph/src/civetweb/src/civetweb.c @@ -1070,6 +1070,7 @@ enum { CGI_INTERPRETER, PROTECT_URI, AUTHENTICATION_DOMAIN, + ENABLE_AUTH_DOMAIN_CHECK, SSI_EXTENSIONS, THROTTLE, ACCESS_LOG_FILE, @@ -1138,6 +1139,7 @@ static struct mg_option config_options[] = { {"cgi_interpreter", CONFIG_TYPE_FILE, NULL}, {"protect_uri", CONFIG_TYPE_STRING, NULL}, {"authentication_domain", CONFIG_TYPE_STRING, "mydomain.com"}, + {"enable_auth_domain_check", CONFIG_TYPE_BOOLEAN, "yes"}, {"ssi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"}, {"throttle", CONFIG_TYPE_STRING, NULL}, {"access_log_file", CONFIG_TYPE_FILE, NULL}, @@ -11763,16 +11765,18 @@ get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn) size_t server_domain_len; size_t request_domain_len = 0; unsigned long port = 0; - int i; + int i, auth_domain_check_enabled; const char *hostbegin = NULL; const char *hostend = NULL; const char *portbegin; char *portend; + auth_domain_check_enabled = + !strcmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK],"yes"); /* DNS is case insensitive, so use case insensitive string compare here */ server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN]; - if (!server_domain) { + if (!server_domain && auth_domain_check_enabled) { return 0; } server_domain_len = strlen(server_domain); @@ -11811,6 +11815,8 @@ get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn) return 0; } +/* Check if the request is directed to a different server. */ +/* First check if the port is the same (IPv4 and IPv6). */ #if defined(USE_IPV6) if (conn->client.lsa.sa.sa_family == AF_INET6) { if (ntohs(conn->client.lsa.sin6.sin6_port) != port) { @@ -11826,10 +11832,38 @@ get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn) } } - if ((request_domain_len != server_domain_len) - || (0 != memcmp(server_domain, hostbegin, server_domain_len))) { - /* Request is directed to another server */ - return 0; + /* Finally check if the server corresponds to the authentication + * domain of the server (the server domain). + * Allow full matches (like http://mydomain.com/path/file.ext), and + * allow subdomain matches (like http://www.mydomain.com/path/file.ext), + * but do not allow substrings (like http://notmydomain.com/path/file.ext + * or http://mydomain.com.fake/path/file.ext). + */ + if (auth_domain_check_enabled) { + if ((request_domain_len == server_domain_len) + && (!memcmp(server_domain, hostbegin, server_domain_len))) { + /* Request is directed to this server - full name match. */ + } else { + if (request_domain_len < (server_domain_len + 2)) { + /* Request is directed to another server: The server name is longer + * than + * the request name. Drop this case here to avoid overflows in the + * following checks. */ + return 0; + } + if (hostbegin[request_domain_len - server_domain_len - 1] != '.') { + /* Request is directed to another server: It could be a substring + * like notmyserver.com */ + return 0; + } + if (0 != memcmp(server_domain, + hostbegin + request_domain_len - server_domain_len, + server_domain_len)) { + /* Request is directed to another server: + * The server name is different. */ + return 0; + } + } } return hostend; diff --git a/ceph/src/civetweb/test/public_server.c b/ceph/src/civetweb/test/public_server.c index 686537c90..b86776e24 100644 --- a/ceph/src/civetweb/test/public_server.c +++ b/ceph/src/civetweb/test/public_server.c @@ -1429,6 +1429,32 @@ START_TEST(test_request_handlers) ck_assert_str_eq(buf, expected); mg_close_connection(client_conn); + /* Get data from callback using mg_connect_client and absolute URI with a + * sub-domain */ + memset(ebuf, 0, sizeof(ebuf)); + client_conn = + mg_connect_client("localhost", ipv4_port, 0, ebuf, sizeof(ebuf)); + ck_assert(client_conn != NULL); + ck_assert_str_eq(ebuf, ""); + + mg_printf(client_conn, + "GET http://subdomain.test.domain:%d/U7 HTTP/1.0\r\n\r\n", + ipv4_port); + + i = mg_get_response(client_conn, ebuf, sizeof(ebuf), 10000); + ck_assert_int_ge(i, 0); + ck_assert_str_eq(ebuf, ""); + + ri = mg_get_request_info(client_conn); + + ck_assert(ri != NULL); + ck_assert_str_eq(ri->uri, "200"); + i = mg_read(client_conn, buf, sizeof(buf)); + ck_assert_int_eq(i, (int)strlen(expected)); + buf[i] = 0; + ck_assert_str_eq(buf, expected); + mg_close_connection(client_conn); + /* Websocket test */ #ifdef USE_WEBSOCKET @@ -2824,13 +2850,12 @@ MAIN_PUBLIC_SERVER(void) test_threading(0); */ test_mg_start_stop_http_server(0); - /* - test_mg_start_stop_https_server(0); + // test_mg_start_stop_https_server(0); test_request_handlers(0); - test_mg_server_and_client_tls(0); - test_handle_form(0); - test_http_auth(0); -*/ + // test_mg_server_and_client_tls(0); + // test_handle_form(0); + // test_http_auth(0); + test_keep_alive(0); printf("\nok: %i\nfailed: %i\n\n", chk_ok, chk_failed); } diff --git a/ceph/src/client/Client.cc b/ceph/src/client/Client.cc index 98c987b00..d98b5f383 100644 --- a/ceph/src/client/Client.cc +++ b/ceph/src/client/Client.cc @@ -250,7 +250,7 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_) whoami(mc->get_global_id()), cap_epoch_barrier(0), last_tid(0), oldest_tid(0), last_flush_tid(1), initialized(false), - mounted(false), unmounting(false), + mounted(false), unmounting(false), blacklisted(false), local_osd(-1), local_osd_epoch(0), unsafe_sync_write(0), client_lock("Client::client_lock") @@ -293,6 +293,7 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_) true)); objecter_finisher.start(); filer.reset(new Filer(objecter, &objecter_finisher)); + objecter->enable_blacklist_events(); } @@ -300,7 +301,12 @@ Client::~Client() { assert(!client_lock.is_locked()); + // It is necessary to hold client_lock, because any inode destruction + // may call into ObjectCacher, which asserts that it's lock (which is + // client_lock) is held. + client_lock.Lock(); tear_down_cache(); + client_lock.Unlock(); } void Client::tear_down_cache() @@ -602,7 +608,7 @@ void Client::trim_cache(bool trim_kernel_dcache) if (lru.lru_get_size() <= lru.lru_get_max()) break; // trim! - Dentry *dn = static_cast(lru.lru_expire()); + Dentry *dn = static_cast(lru.lru_get_next_expire()); if (!dn) break; // done @@ -1649,6 +1655,11 @@ int Client::make_request(MetaRequest *request, if (request->aborted()) break; + if (blacklisted) { + request->abort(-EBLACKLISTED); + break; + } + // set up wait cond Cond caller_cond; request->caller_cond = &caller_cond; @@ -2398,6 +2409,51 @@ void Client::_handle_full_flag(int64_t pool) void Client::handle_osd_map(MOSDMap *m) { + std::set new_blacklists; + objecter->consume_blacklist_events(&new_blacklists); + + const auto myaddr = messenger->get_myaddr(); + if (!blacklisted && new_blacklists.count(myaddr)) { + auto epoch = objecter->with_osdmap([](const OSDMap &o){ + return o.get_epoch(); + }); + lderr(cct) << "I was blacklisted at osd epoch " << epoch << dendl; + blacklisted = true; + for (std::map::iterator p = mds_requests.begin(); + p != mds_requests.end(); ) { + auto req = p->second; + ++p; + req->abort(-EBLACKLISTED); + if (req->caller_cond) { + req->kick = true; + req->caller_cond->Signal(); + } + } + + // Progress aborts on any requests that were on this waitlist. Any + // requests that were on a waiting_for_open session waitlist + // will get kicked during close session below. + signal_cond_list(waiting_for_mdsmap); + + // Force-close all sessions: assume this is not abandoning any state + // on the MDS side because the MDS will have seen the blacklist too. + while(!mds_sessions.empty()) { + auto i = mds_sessions.begin(); + auto session = i->second; + _closed_mds_session(session); + } + + // Since we know all our OSD ops will fail, cancel them all preemtively, + // so that on an unhealthy cluster we can umount promptly even if e.g. + // some PGs were inaccessible. + objecter->op_cancel_writes(-EBLACKLISTED); + + } else if (blacklisted) { + // Handle case where we were blacklisted but no longer are + blacklisted = objecter->with_osdmap([myaddr](const OSDMap &o){ + return o.is_blacklisted(myaddr);}); + } + if (objecter->osdmap_full_flag()) { _handle_full_flag(-1); } else { @@ -2707,11 +2763,19 @@ void Client::kick_requests(MetaSession *session) for (map::iterator p = mds_requests.begin(); p != mds_requests.end(); ++p) { - if (p->second->got_unsafe) + MetaRequest *req = p->second; + if (req->got_unsafe) + continue; + if (req->aborted()) { + if (req->caller_cond) { + req->kick = true; + req->caller_cond->Signal(); + } continue; - if (p->second->retry_attempt > 0) + } + if (req->retry_attempt > 0) continue; // new requests only - if (p->second->mds == session->mds_num) { + if (req->mds == session->mds_num) { send_request(p->second, session); } } @@ -2732,6 +2796,8 @@ void Client::resend_unsafe_requests(MetaSession *session) MetaRequest *req = p->second; if (req->got_unsafe) continue; + if (req->aborted()) + continue; if (req->retry_attempt == 0) continue; // old requests only if (req->mds == session->mds_num) @@ -3280,6 +3346,19 @@ void Client::send_cap(Inode *in, MetaSession *session, Cap *cap, session->con->send_message(m); } +static bool is_max_size_approaching(Inode *in) +{ + /* mds will adjust max size according to the reported size */ + if (in->flushing_caps & CEPH_CAP_FILE_WR) + return false; + if (in->size >= in->max_size) + return true; + /* half of previous max_size increment has been used */ + if (in->max_size > in->reported_size && + (in->size << 1) >= in->max_size + in->reported_size) + return true; + return false; +} /** * check_caps @@ -3370,11 +3449,10 @@ void Client::check_caps(Inode *in, unsigned flags) /* approaching file_max? */ if ((cap->issued & CEPH_CAP_FILE_WR) && - (in->size << 1) >= in->max_size && - (in->reported_size << 1) < in->max_size && - cap == in->auth_cap) { + cap == in->auth_cap && + is_max_size_approaching(in)) { ldout(cct, 10) << "size " << in->size << " approaching max_size " << in->max_size - << ", reported " << in->reported_size << dendl; + << ", reported " << in->reported_size << dendl; goto ack; } @@ -5720,6 +5798,30 @@ void Client::_close_sessions() } } +void Client::flush_mdlog_sync() +{ + if (mds_requests.empty()) + return; + for (map::iterator p = mds_sessions.begin(); + p != mds_sessions.end(); + ++p) { + MetaSession *s = p->second; + flush_mdlog(s); + } +} + +void Client::flush_mdlog(MetaSession *session) +{ + // Only send this to Luminous or newer MDS daemons, older daemons + // will crash if they see an unknown CEPH_SESSION_* value in this msg. + const uint64_t features = session->con->get_features(); + if (HAVE_FEATURE(features, SERVER_LUMINOUS)) { + MClientSession *m = new MClientSession(CEPH_SESSION_REQUEST_FLUSH_MDLOG); + session->con->send_message(m); + } +} + + void Client::unmount() { Mutex::Locker lock(client_lock); @@ -5729,6 +5831,7 @@ void Client::unmount() ldout(cct, 2) << "unmounting" << dendl; unmounting = true; + flush_mdlog_sync(); // flush the mdlog for pending requests, if any while (!mds_requests.empty()) { ldout(cct, 10) << "waiting on " << mds_requests.size() << " requests" << dendl; mount_cond.Wait(client_lock); @@ -5764,6 +5867,23 @@ void Client::unmount() _ll_drop_pins(); + if (blacklisted) { + ldout(cct, 0) << " skipping clean shutdown, we are blacklisted" << dendl; + + if (cct->_conf->client_oc) { + // Purge all cached data so that ObjectCacher doesn't get hung up + // trying to flush it. ObjectCacher's behaviour on EBLACKLISTED + // is to just leave things marked dirty + // (http://tracker.ceph.com/issues/9105) + for (const auto &i : inode_map) { + objectcacher->purge_set(&(i.second->oset)); + } + } + + mounted = false; + return; + } + while (unsafe_sync_write > 0) { ldout(cct, 0) << unsafe_sync_write << " unsafe_sync_writes, waiting" << dendl; mount_cond.Wait(client_lock); @@ -9002,10 +9122,8 @@ success: if (is_quota_bytes_approaching(in, f->actor_perms)) { check_caps(in, CHECK_CAPS_NODELAY); - } else { - if ((in->size << 1) >= in->max_size && - (in->reported_size << 1) < in->max_size) - check_caps(in, 0); + } else if (is_max_size_approaching(in)) { + check_caps(in, 0); } ldout(cct, 7) << "wrote to " << totalwritten+offset << ", extending file size" << dendl; @@ -9361,8 +9479,9 @@ int Client::statfs(const char *path, struct statvfs *stbuf, // as the filesystem statistics. const fsblkcnt_t total = quota_root->quota.max_bytes >> CEPH_BLOCK_SHIFT; const fsblkcnt_t used = quota_root->rstat.rbytes >> CEPH_BLOCK_SHIFT; - const fsblkcnt_t free = total - used; - + // It is possible for a quota to be exceeded: arithmetic here must + // handle case where used > total. + const fsblkcnt_t free = total > used ? total - used : 0; stbuf->f_blocks = total; stbuf->f_bfree = free; @@ -9428,9 +9547,12 @@ int Client::_do_filelock(Inode *in, Fh *fh, int lock_type, int op, int sleep, // enable interrupt switch_interrupt_cb(callback_handle, req->get()); ret = make_request(req, fh->actor_perms, NULL, NULL, -1, &bl); - // disable interrupt switch_interrupt_cb(callback_handle, NULL); + if (ret == 0 && req->aborted()) { + // effect of this lock request has been revoked by the 'lock intr' request + ret = req->get_abort_code(); + } put_request(req); } else { ret = make_request(req, fh->actor_perms, NULL, NULL, -1, &bl); @@ -9489,6 +9611,12 @@ int Client::_do_filelock(Inode *in, Fh *fh, int lock_type, int op, int sleep, int Client::_interrupt_filelock(MetaRequest *req) { + // Set abort code, but do not kick. The abort code prevents the request + // from being re-sent. + req->abort(-EINTR); + if (req->mds < 0) + return 0; // haven't sent the request + Inode *in = req->inode(); int lock_type; @@ -9919,7 +10047,8 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, Inode **out, const UserPerm& perms) { Mutex::Locker lock(client_lock); - ldout(cct, 3) << "ll_lookup " << parent << " " << name << dendl; + vinodeno_t vparent = _get_vino(parent); + ldout(cct, 3) << "ll_lookup " << vparent << " " << name << dendl; tout(cct) << "ll_lookup" << std::endl; tout(cct) << name << std::endl; @@ -9944,7 +10073,7 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, _ll_get(in.get()); out: - ldout(cct, 3) << "ll_lookup " << parent << " " << name + ldout(cct, 3) << "ll_lookup " << vparent << " " << name << " -> " << r << " (" << hex << attr->st_ino << dec << ")" << dendl; tout(cct) << attr->st_ino << std::endl; *out = in.get(); @@ -9956,7 +10085,8 @@ int Client::ll_lookupx(Inode *parent, const char *name, Inode **out, const UserPerm& perms) { Mutex::Locker lock(client_lock); - ldout(cct, 3) << "ll_lookupx " << parent << " " << name << dendl; + vinodeno_t vparent = _get_vino(parent); + ldout(cct, 3) << "ll_lookupx " << vparent << " " << name << dendl; tout(cct) << "ll_lookupx" << std::endl; tout(cct) << name << std::endl; @@ -9981,7 +10111,7 @@ int Client::ll_lookupx(Inode *parent, const char *name, Inode **out, _ll_get(in.get()); } - ldout(cct, 3) << "ll_lookupx " << parent << " " << name + ldout(cct, 3) << "ll_lookupx " << vparent << " " << name << " -> " << r << " (" << hex << stx->stx_ino << dec << ")" << dendl; tout(cct) << stx->stx_ino << std::endl; *out = in.get(); @@ -11764,7 +11894,7 @@ int Client::ll_link(Inode *in, Inode *newparent, const char *newname, vinodeno_t vino = _get_vino(in); vinodeno_t vnewparent = _get_vino(newparent); - ldout(cct, 3) << "ll_link " << in << " to " << vnewparent << " " << + ldout(cct, 3) << "ll_link " << vino << " to " << vnewparent << " " << newname << dendl; tout(cct) << "ll_link" << std::endl; tout(cct) << vino.ino.val << std::endl; @@ -12036,7 +12166,7 @@ out: tout(cct) << (unsigned long)*fhp << std::endl; tout(cct) << ino << std::endl; - ldout(cct, 3) << "_ll_create " << parent << " " << name << " 0" << oct << + ldout(cct, 3) << "_ll_create " << vparent << " " << name << " 0" << oct << mode << dec << " " << ceph_flags_sys2wire(flags) << " = " << r << " (" << *fhp << " " << hex << ino << dec << ")" << dendl; @@ -12399,10 +12529,8 @@ int Client::_fallocate(Fh *fh, int mode, int64_t offset, int64_t length) if (is_quota_bytes_approaching(in, fh->actor_perms)) { check_caps(in, CHECK_CAPS_NODELAY); - } else { - if ((in->size << 1) >= in->max_size && - (in->reported_size << 1) < in->max_size) - check_caps(in, 0); + } else if (is_max_size_approaching(in)) { + check_caps(in, 0); } } } diff --git a/ceph/src/client/Client.h b/ceph/src/client/Client.h index 7d2b73eb3..b6369a293 100644 --- a/ceph/src/client/Client.h +++ b/ceph/src/client/Client.h @@ -388,6 +388,7 @@ protected: bool initialized; bool mounted; bool unmounting; + bool blacklisted; // When an MDS has sent us a REJECT, remember that and don't // contact it again. Remember which inst rejected us, so that @@ -723,7 +724,11 @@ protected: bool use_faked_inos() { return _use_faked_inos; } vinodeno_t map_faked_ino(ino_t ino); - + + //notify the mds to flush the mdlog + void flush_mdlog_sync(); + void flush_mdlog(MetaSession *session); + // ---------------------- // fs ops. private: diff --git a/ceph/src/client/Dentry.cc b/ceph/src/client/Dentry.cc index 8bb21ace2..bf45708cd 100644 --- a/ceph/src/client/Dentry.cc +++ b/ceph/src/client/Dentry.cc @@ -17,12 +17,12 @@ void Dentry::dump(Formatter *f) const if (inode) f->dump_stream("ino") << inode->ino; f->dump_int("ref", ref); - f->dump_unsigned("offset", offset); + f->dump_int("offset", offset); if (lease_mds >= 0) { f->dump_int("lease_mds", lease_mds); f->dump_stream("lease_ttl") << lease_ttl; - f->dump_int("lease_gen", lease_gen); - f->dump_int("lease_seq", lease_seq); + f->dump_unsigned("lease_gen", lease_gen); + f->dump_unsigned("lease_seq", lease_seq); } f->dump_int("cap_shared_gen", cap_shared_gen); } diff --git a/ceph/src/client/Inode.cc b/ceph/src/client/Inode.cc index bb1601a72..a3d422547 100644 --- a/ceph/src/client/Inode.cc +++ b/ceph/src/client/Inode.cc @@ -371,16 +371,16 @@ void Inode::dump(Formatter *f) const f->dump_stream("mode") << '0' << std::oct << mode << std::dec; f->dump_unsigned("uid", uid); f->dump_unsigned("gid", gid); - f->dump_unsigned("nlink", nlink); + f->dump_int("nlink", nlink); - f->dump_int("size", size); - f->dump_int("max_size", max_size); - f->dump_int("truncate_seq", truncate_seq); - f->dump_int("truncate_size", truncate_size); + f->dump_unsigned("size", size); + f->dump_unsigned("max_size", max_size); + f->dump_unsigned("truncate_seq", truncate_seq); + f->dump_unsigned("truncate_size", truncate_size); f->dump_stream("mtime") << mtime; f->dump_stream("atime") << atime; - f->dump_int("time_warp_seq", time_warp_seq); - f->dump_int("change_attr", change_attr); + f->dump_unsigned("time_warp_seq", time_warp_seq); + f->dump_unsigned("change_attr", change_attr); f->dump_object("layout", layout); if (is_dir()) { @@ -470,8 +470,8 @@ void Inode::dump(Formatter *f) const f->open_array_section("open_by_mode"); for (map::const_iterator p = open_by_mode.begin(); p != open_by_mode.end(); ++p) { f->open_object_section("ref"); - f->dump_unsigned("mode", p->first); - f->dump_unsigned("refs", p->second); + f->dump_int("mode", p->first); + f->dump_int("refs", p->second); f->close_section(); } f->close_section(); diff --git a/ceph/src/client/MetaRequest.h b/ceph/src/client/MetaRequest.h index e0eac4a15..8880933d7 100644 --- a/ceph/src/client/MetaRequest.h +++ b/ceph/src/client/MetaRequest.h @@ -8,7 +8,6 @@ #include "include/types.h" #include "include/xlist.h" #include "include/filepath.h" -#include "include/atomic.h" #include "mds/mdstypes.h" #include "InodeRef.h" #include "UserPerm.h" @@ -48,7 +47,7 @@ public: __u32 sent_on_mseq; // mseq at last submission of this request int num_fwd; // # of times i've been forwarded int retry_attempt; - atomic_t ref; + std::atomic ref = { 1 }; MClientReply *reply; // the reply bool kick; @@ -83,7 +82,7 @@ public: regetattr_mask(0), mds(-1), resend_mds(-1), send_to_auth(false), sent_on_mseq(0), num_fwd(0), retry_attempt(0), - ref(1), reply(0), + reply(0), kick(false), success(false), got_unsafe(false), item(this), unsafe_item(this), unsafe_dir_item(this), unsafe_target_item(this), @@ -153,13 +152,13 @@ public: Dentry *old_dentry(); MetaRequest* get() { - ref.inc(); + ref++; return this; } /// psuedo-private put method; use Client::put_request() bool _put() { - int v = ref.dec(); + int v = --ref; return v == 0; } diff --git a/ceph/src/client/ObjecterWriteback.h b/ceph/src/client/ObjecterWriteback.h index 97cb228d5..892843764 100644 --- a/ceph/src/client/ObjecterWriteback.h +++ b/ceph/src/client/ObjecterWriteback.h @@ -17,7 +17,9 @@ class ObjecterWriteback : public WritebackHandler { void read(const object_t& oid, uint64_t object_no, const object_locator_t& oloc, uint64_t off, uint64_t len, snapid_t snapid, bufferlist *pbl, uint64_t trunc_size, - __u32 trunc_seq, int op_flags, Context *onfinish) override { + __u32 trunc_seq, int op_flags, + const ZTracer::Trace &parent_trace, + Context *onfinish) override { m_objecter->read_trunc(oid, oloc, off, len, snapid, pbl, 0, trunc_size, trunc_seq, new C_OnFinisher(new C_Lock(m_lock, onfinish), @@ -34,6 +36,7 @@ class ObjecterWriteback : public WritebackHandler { const SnapContext& snapc, const bufferlist &bl, ceph::real_time mtime, uint64_t trunc_size, __u32 trunc_seq, ceph_tid_t journal_tid, + const ZTracer::Trace &parent_trace, Context *oncommit) override { return m_objecter->write_trunc(oid, oloc, off, len, snapc, bl, mtime, 0, trunc_size, trunc_seq, diff --git a/ceph/src/client/SyntheticClient.cc b/ceph/src/client/SyntheticClient.cc index 54c3ddbff..14c10467a 100644 --- a/ceph/src/client/SyntheticClient.cc +++ b/ceph/src/client/SyntheticClient.cc @@ -261,7 +261,7 @@ void parse_syn_options(vector& args) } -SyntheticClient::SyntheticClient(Client *client, int w) +SyntheticClient::SyntheticClient(StandaloneClient *client, int w) { this->client = client; whoami = w; @@ -3354,7 +3354,6 @@ int SyntheticClient::chunk_file(string &filename) uint64_t size = st.st_size; dout(0) << "file " << filename << " size is " << size << dendl; - inode_t inode; memset(&inode, 0, sizeof(inode)); inode.ino = st.st_ino; diff --git a/ceph/src/client/SyntheticClient.h b/ceph/src/client/SyntheticClient.h index 8330e617d..5dd247de4 100644 --- a/ceph/src/client/SyntheticClient.h +++ b/ceph/src/client/SyntheticClient.h @@ -97,7 +97,7 @@ void parse_syn_options(vector& args); class SyntheticClient { - Client *client; + StandaloneClient *client; int whoami; pthread_t thread_id; @@ -168,7 +168,7 @@ class SyntheticClient { } public: - SyntheticClient(Client *client, int w = -1); + SyntheticClient(StandaloneClient *client, int w = -1); int start_thread(); int join_thread(); diff --git a/ceph/src/client/hypertable/CephBroker.cc b/ceph/src/client/hypertable/CephBroker.cc index 77f6e0834..d7911cbfa 100644 --- a/ceph/src/client/hypertable/CephBroker.cc +++ b/ceph/src/client/hypertable/CephBroker.cc @@ -41,7 +41,7 @@ using namespace Hypertable; -atomic_t CephBroker::ms_next_fd = ATOMIC_INIT(0); +std::atomic CephBroker::ms_next_fd{0}; /* A thread-safe version of strerror */ static std::string cpp_strerror(int err) diff --git a/ceph/src/client/hypertable/CephBroker.h b/ceph/src/client/hypertable/CephBroker.h index a0d180c4d..d2df38909 100644 --- a/ceph/src/client/hypertable/CephBroker.h +++ b/ceph/src/client/hypertable/CephBroker.h @@ -27,9 +27,8 @@ extern "C" { #include } - +#include #include "Common/String.h" -#include "Common/atomic.h" #include "Common/Properties.h" #include "DfsBroker/Lib/Broker.h" @@ -97,7 +96,7 @@ namespace Hypertable { private: struct ceph_mount_info *cmount; - static atomic_t ms_next_fd; + static std::atomic ms_next_fd; virtual void report_error(ResponseCallback *cb, int error); diff --git a/ceph/src/cls/cephfs/cls_cephfs.cc b/ceph/src/cls/cephfs/cls_cephfs.cc index 6ae1f8d28..1d656c137 100644 --- a/ceph/src/cls/cephfs/cls_cephfs.cc +++ b/ceph/src/cls/cephfs/cls_cephfs.cc @@ -15,7 +15,6 @@ #include #include -#include #include "objclass/objclass.h" diff --git a/ceph/src/cls/cephfs/cls_cephfs_client.cc b/ceph/src/cls/cephfs/cls_cephfs_client.cc index 17202bb38..b03924273 100644 --- a/ceph/src/cls/cephfs/cls_cephfs_client.cc +++ b/ceph/src/cls/cephfs/cls_cephfs_client.cc @@ -14,7 +14,7 @@ #include "cls_cephfs_client.h" - +#include "include/rados/librados.hpp" #include "mds/CInode.h" #define XATTR_CEILING "scan_ceiling" diff --git a/ceph/src/cls/cephfs/cls_cephfs_client.h b/ceph/src/cls/cephfs/cls_cephfs_client.h index 1305358f3..b028917d4 100644 --- a/ceph/src/cls/cephfs/cls_cephfs_client.h +++ b/ceph/src/cls/cephfs/cls_cephfs_client.h @@ -1,10 +1,11 @@ -#include "include/rados/librados.hpp" #include "mds/mdstypes.h" - #include "cls_cephfs.h" class AccumulateArgs; +namespace librados { + class IoCtx; +} class ClsCephFSClient { diff --git a/ceph/src/cls/journal/cls_journal_client.cc b/ceph/src/cls/journal/cls_journal_client.cc index 88f221328..c4744ebee 100644 --- a/ceph/src/cls/journal/cls_journal_client.cc +++ b/ceph/src/cls/journal/cls_journal_client.cc @@ -2,11 +2,11 @@ // vim: ts=8 sw=2 smarttab #include "cls/journal/cls_journal_client.h" +#include "include/rados/librados.hpp" #include "include/buffer.h" #include "include/Context.h" #include "common/Cond.h" #include -#include namespace cls { namespace journal { diff --git a/ceph/src/cls/journal/cls_journal_client.h b/ceph/src/cls/journal/cls_journal_client.h index 477254f32..8635b805d 100644 --- a/ceph/src/cls/journal/cls_journal_client.h +++ b/ceph/src/cls/journal/cls_journal_client.h @@ -4,15 +4,16 @@ #ifndef CEPH_CLS_JOURNAL_CLIENT_H #define CEPH_CLS_JOURNAL_CLIENT_H -#include "include/int_types.h" -#include "include/rados/librados.hpp" #include "cls/journal/cls_journal_types.h" -#include #include -#include #include class Context; +namespace librados { + class IoCtx; + class ObjectWriteOperation; + class ObjectReadOperation; +} namespace cls { namespace journal { diff --git a/ceph/src/cls/journal/cls_journal_types.h b/ceph/src/cls/journal/cls_journal_types.h index 4e1f2d7fd..f2cb84197 100644 --- a/ceph/src/cls/journal/cls_journal_types.h +++ b/ceph/src/cls/journal/cls_journal_types.h @@ -9,7 +9,6 @@ #include "include/encoding.h" #include #include -#include #include namespace ceph { diff --git a/ceph/src/cls/lock/cls_lock.cc b/ceph/src/cls/lock/cls_lock.cc index 01f691b04..551ca901b 100644 --- a/ceph/src/cls/lock/cls_lock.cc +++ b/ceph/src/cls/lock/cls_lock.cc @@ -8,14 +8,8 @@ * */ -#include -#include -#include #include -#include #include -#include -#include #include "include/types.h" #include "include/utime.h" diff --git a/ceph/src/cls/lock/cls_lock_client.cc b/ceph/src/cls/lock/cls_lock_client.cc index f56bc5269..3a3cef367 100644 --- a/ceph/src/cls/lock/cls_lock_client.cc +++ b/ceph/src/cls/lock/cls_lock_client.cc @@ -15,16 +15,10 @@ #include "include/types.h" #include "msg/msg_types.h" #include "include/rados/librados.hpp" - +#include "include/utime.h" + using namespace librados; -#include - -#include -#include -#include - -#include "cls/lock/cls_lock_types.h" #include "cls/lock/cls_lock_ops.h" #include "cls/lock/cls_lock_client.h" diff --git a/ceph/src/cls/lock/cls_lock_client.h b/ceph/src/cls/lock/cls_lock_client.h index e94606e3e..7aa06238f 100644 --- a/ceph/src/cls/lock/cls_lock_client.h +++ b/ceph/src/cls/lock/cls_lock_client.h @@ -4,12 +4,15 @@ #ifndef CEPH_CLS_LOCK_CLIENT_H #define CEPH_CLS_LOCK_CLIENT_H - -#include "include/types.h" -#include "include/rados/librados.hpp" - #include "cls/lock/cls_lock_types.h" +namespace librados { + class AioCompletion; + class ObjectWriteOperation; + class IoCtx; + class ObjectReadOperation; + class ObjectOperation; +} namespace rados { namespace cls { diff --git a/ceph/src/cls/lock/cls_lock_ops.cc b/ceph/src/cls/lock/cls_lock_ops.cc index 9905130d8..10d005900 100644 --- a/ceph/src/cls/lock/cls_lock_ops.cc +++ b/ceph/src/cls/lock/cls_lock_ops.cc @@ -12,11 +12,9 @@ * */ -#include "include/types.h" #include "msg/msg_types.h" #include "common/Formatter.h" -#include "cls/lock/cls_lock_types.h" #include "cls/lock/cls_lock_ops.h" using namespace rados::cls::lock; diff --git a/ceph/src/cls/lock/cls_lock_types.cc b/ceph/src/cls/lock/cls_lock_types.cc index 68840d72c..1c67bdea5 100644 --- a/ceph/src/cls/lock/cls_lock_types.cc +++ b/ceph/src/cls/lock/cls_lock_types.cc @@ -12,8 +12,6 @@ * */ -#include "include/types.h" -#include "msg/msg_types.h" #include "common/Formatter.h" #include "cls/lock/cls_lock_types.h" diff --git a/ceph/src/cls/log/cls_log.cc b/ceph/src/cls/log/cls_log.cc index 70b9eb851..bfc0e499f 100644 --- a/ceph/src/cls/log/cls_log.cc +++ b/ceph/src/cls/log/cls_log.cc @@ -1,12 +1,6 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include - -#include -#include -#include - #include "include/types.h" #include "include/utime.h" #include "objclass/objclass.h" diff --git a/ceph/src/cls/log/cls_log_client.cc b/ceph/src/cls/log/cls_log_client.cc index 799f7eb43..881be1636 100644 --- a/ceph/src/cls/log/cls_log_client.cc +++ b/ceph/src/cls/log/cls_log_client.cc @@ -1,6 +1,5 @@ #include -#include "include/types.h" #include "cls/log/cls_log_ops.h" #include "include/rados/librados.hpp" #include "include/compat.h" diff --git a/ceph/src/cls/log/cls_log_client.h b/ceph/src/cls/log/cls_log_client.h index c96dbb085..5af807555 100644 --- a/ceph/src/cls/log/cls_log_client.h +++ b/ceph/src/cls/log/cls_log_client.h @@ -1,10 +1,14 @@ #ifndef CEPH_CLS_LOG_CLIENT_H #define CEPH_CLS_LOG_CLIENT_H -#include "include/types.h" -#include "include/rados/librados.hpp" #include "cls_log_types.h" +namespace librados { + class ObjectWriteOperation; + class ObjectReadOperation; + class IoCtx; +} + /* * log objclass */ diff --git a/ceph/src/cls/log/cls_log_ops.h b/ceph/src/cls/log/cls_log_ops.h index 3c9152333..67dfcd5c5 100644 --- a/ceph/src/cls/log/cls_log_ops.h +++ b/ceph/src/cls/log/cls_log_ops.h @@ -4,7 +4,6 @@ #ifndef CEPH_CLS_LOG_OPS_H #define CEPH_CLS_LOG_OPS_H -#include "include/types.h" #include "cls_log_types.h" struct cls_log_add_op { diff --git a/ceph/src/cls/lua/cls_lua_client.cc b/ceph/src/cls/lua/cls_lua_client.cc index 95dd2bb60..44348270c 100644 --- a/ceph/src/cls/lua/cls_lua_client.cc +++ b/ceph/src/cls/lua/cls_lua_client.cc @@ -1,10 +1,7 @@ -#include #include #include #include "include/encoding.h" -#include "include/rados.h" -#include "include/rados/librados.h" -#include "include/types.h" +#include "include/rados/librados.hpp" // for IoCtx #include "cls_lua_client.h" #include "cls_lua_ops.h" diff --git a/ceph/src/cls/lua/cls_lua_client.h b/ceph/src/cls/lua/cls_lua_client.h index fd049247a..e37906993 100644 --- a/ceph/src/cls/lua/cls_lua_client.h +++ b/ceph/src/cls/lua/cls_lua_client.h @@ -1,8 +1,12 @@ #ifndef CLS_LUA_CLIENT_HPP #define CLS_LUA_CLIENT_HPP #include -#include -#include "include/rados/librados.hpp" + +#include "include/buffer_fwd.h" // for bufferlist + +namespace librados { + class IoCtx; +} namespace cls_lua_client { int exec(librados::IoCtx& ioctx, const std::string& oid, diff --git a/ceph/src/cls/lua/cls_lua_ops.h b/ceph/src/cls/lua/cls_lua_ops.h index ed2979220..2bf95051d 100644 --- a/ceph/src/cls/lua/cls_lua_ops.h +++ b/ceph/src/cls/lua/cls_lua_ops.h @@ -2,8 +2,8 @@ #define CEPH_CLS_LUA_OPS_H struct cls_lua_eval_op { - string script; - string handler; + std::string script; + std::string handler; bufferlist input; void encode(bufferlist &bl) const { diff --git a/ceph/src/cls/numops/cls_numops.cc b/ceph/src/cls/numops/cls_numops.cc index a4023b934..968966c27 100644 --- a/ceph/src/cls/numops/cls_numops.cc +++ b/ceph/src/cls/numops/cls_numops.cc @@ -21,8 +21,6 @@ #include "objclass/objclass.h" #include -#include -#include #include #include #include diff --git a/ceph/src/cls/numops/cls_numops_client.cc b/ceph/src/cls/numops/cls_numops_client.cc index 689282063..c91d5692b 100644 --- a/ceph/src/cls/numops/cls_numops_client.cc +++ b/ceph/src/cls/numops/cls_numops_client.cc @@ -12,11 +12,10 @@ * */ -#include "objclass/objclass.h" #include "cls/numops/cls_numops_client.h" #include "include/encoding.h" +#include "include/rados/librados.hpp" -#include #include #include diff --git a/ceph/src/cls/numops/cls_numops_client.h b/ceph/src/cls/numops/cls_numops_client.h index 8d776bffc..7eab948a7 100644 --- a/ceph/src/cls/numops/cls_numops_client.h +++ b/ceph/src/cls/numops/cls_numops_client.h @@ -15,7 +15,11 @@ #ifndef CEPH_LIBRBD_CLS_NUMOPS_CLIENT_H #define CEPH_LIBRBD_CLS_NUMOPS_CLIENT_H -#include "include/rados/librados.hpp" +#include + +namespace librados { + class IoCtx; +} namespace rados { namespace cls { diff --git a/ceph/src/cls/rbd/cls_rbd.cc b/ceph/src/cls/rbd/cls_rbd.cc index c5dc0cf45..3eb64a45a 100644 --- a/ceph/src/cls/rbd/cls_rbd.cc +++ b/ceph/src/cls/rbd/cls_rbd.cc @@ -25,17 +25,11 @@ * parameters as the client sees them - it would be silly to mention * in each one that they take an input and an output bufferlist. */ -#include "include/int_types.h" #include "include/types.h" #include -#include -#include #include -#include -#include #include -#include #include "common/bit_vector.hpp" #include "common/errno.h" @@ -229,12 +223,15 @@ int create(cls_method_context_t hctx, bufferlist *in, bufferlist *out) bufferlist featuresbl; bufferlist object_prefixbl; bufferlist snap_seqbl; + bufferlist create_timestampbl; uint64_t snap_seq = 0; + utime_t create_timestamp = ceph_clock_now(); ::encode(size, sizebl); ::encode(order, orderbl); ::encode(features, featuresbl); ::encode(object_prefix, object_prefixbl); ::encode(snap_seq, snap_seqbl); + ::encode(create_timestamp, create_timestampbl); map omap_vals; omap_vals["size"] = sizebl; @@ -242,6 +239,7 @@ int create(cls_method_context_t hctx, bufferlist *in, bufferlist *out) omap_vals["features"] = featuresbl; omap_vals["object_prefix"] = object_prefixbl; omap_vals["snap_seq"] = snap_seqbl; + omap_vals["create_timestamp"] = create_timestampbl; if (features & RBD_FEATURE_DATA_POOL) { if (data_pool_id == -1) { @@ -775,6 +773,32 @@ int set_stripe_unit_count(cls_method_context_t hctx, bufferlist *in, bufferlist return 0; } +int get_create_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "get_create_timestamp"); + + utime_t timestamp; + bufferlist bl; + int r = cls_cxx_map_get_val(hctx, "create_timestamp", &bl); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error reading create_timestamp: %s", cpp_strerror(r).c_str()); + return r; + } + } else { + try { + bufferlist::iterator it = bl.begin(); + ::decode(timestamp, it); + } catch (const buffer::error &err) { + CLS_ERR("could not decode create_timestamp"); + return -EIO; + } + } + + ::encode(timestamp, *out); + return 0; +} + /** * get the image flags * @@ -5085,6 +5109,7 @@ CLS_INIT(rbd) cls_method_handle_t h_set_protection_status; cls_method_handle_t h_get_stripe_unit_count; cls_method_handle_t h_set_stripe_unit_count; + cls_method_handle_t h_get_create_timestamp; cls_method_handle_t h_get_flags; cls_method_handle_t h_set_flags; cls_method_handle_t h_remove_parent; @@ -5233,6 +5258,9 @@ CLS_INIT(rbd) cls_register_cxx_method(h_class, "set_stripe_unit_count", CLS_METHOD_RD | CLS_METHOD_WR, set_stripe_unit_count, &h_set_stripe_unit_count); + cls_register_cxx_method(h_class, "get_create_timestamp", + CLS_METHOD_RD, + get_create_timestamp, &h_get_create_timestamp); cls_register_cxx_method(h_class, "get_flags", CLS_METHOD_RD, get_flags, &h_get_flags); diff --git a/ceph/src/cls/rbd/cls_rbd_client.cc b/ceph/src/cls/rbd/cls_rbd_client.cc index 8d7307d40..88b5b3d03 100644 --- a/ceph/src/cls/rbd/cls_rbd_client.cc +++ b/ceph/src/cls/rbd/cls_rbd_client.cc @@ -4,10 +4,9 @@ #include "cls/rbd/cls_rbd_client.h" #include "cls/lock/cls_lock_client.h" #include "include/buffer.h" -#include "include/Context.h" #include "include/encoding.h" #include "include/rbd_types.h" -#include "common/Cond.h" +#include "include/rados/librados.hpp" #include @@ -916,6 +915,39 @@ namespace librbd { return ioctx->operate(oid, &op); } + void get_create_timestamp_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_create_timestamp", empty_bl); + } + + int get_create_timestamp_finish(bufferlist::iterator *it, + utime_t *timestamp) { + assert(timestamp); + + try { + ::decode(*timestamp, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp) + { + librados::ObjectReadOperation op; + get_create_timestamp_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_create_timestamp_finish(&it, timestamp); + } + /************************ rbd_id object methods ************************/ void get_id_start(librados::ObjectReadOperation *op) { diff --git a/ceph/src/cls/rbd/cls_rbd_client.h b/ceph/src/cls/rbd/cls_rbd_client.h index ebca318e9..754017f2d 100644 --- a/ceph/src/cls/rbd/cls_rbd_client.h +++ b/ceph/src/cls/rbd/cls_rbd_client.h @@ -8,14 +8,15 @@ #include "cls/rbd/cls_rbd_types.h" #include "common/bit_vector.hpp" #include "common/snap_types.h" -#include "include/rados/librados.hpp" #include "include/types.h" #include "librbd/Types.h" -#include -#include - class Context; +namespace librados { + class ObjectReadOperation; + class IoCtx; + class ObjectWriteOperation; +} namespace librbd { namespace cls_client { @@ -178,6 +179,11 @@ namespace librbd { uint64_t stripe_unit, uint64_t stripe_count); int set_stripe_unit_count(librados::IoCtx *ioctx, const std::string &oid, uint64_t stripe_unit, uint64_t stripe_count); + void get_create_timestamp_start(librados::ObjectReadOperation *op); + int get_create_timestamp_finish(bufferlist::iterator *it, + utime_t *timestamp); + int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp); int metadata_list(librados::IoCtx *ioctx, const std::string &oid, const std::string &start, uint64_t max_return, map *pairs); diff --git a/ceph/src/cls/refcount/cls_refcount.cc b/ceph/src/cls/refcount/cls_refcount.cc index 9a196c977..41ac88271 100644 --- a/ceph/src/cls/refcount/cls_refcount.cc +++ b/ceph/src/cls/refcount/cls_refcount.cc @@ -1,19 +1,11 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include - -#include -#include #include -#include "include/types.h" -#include "include/utime.h" #include "objclass/objclass.h" #include "cls/refcount/cls_refcount_ops.h" -#include "common/Clock.h" -#include "global/global_context.h" #include "include/compat.h" CLS_VER(1,0) diff --git a/ceph/src/cls/refcount/cls_refcount_client.cc b/ceph/src/cls/refcount/cls_refcount_client.cc index f88ff5edd..1c27a80ad 100644 --- a/ceph/src/cls/refcount/cls_refcount_client.cc +++ b/ceph/src/cls/refcount/cls_refcount_client.cc @@ -1,6 +1,6 @@ #include -#include "include/types.h" +#include "cls/refcount/cls_refcount_client.h" #include "cls/refcount/cls_refcount_ops.h" #include "include/rados/librados.hpp" diff --git a/ceph/src/cls/refcount/cls_refcount_client.h b/ceph/src/cls/refcount/cls_refcount_client.h index 9fbb8c059..654cc00f3 100644 --- a/ceph/src/cls/refcount/cls_refcount_client.h +++ b/ceph/src/cls/refcount/cls_refcount_client.h @@ -2,7 +2,11 @@ #define CEPH_CLS_REFCOUNT_CLIENT_H #include "include/types.h" -#include "include/rados/librados.hpp" + +namespace librados { + class ObjectWriteOperation; + class IoCtx; +} /* * refcount objclass diff --git a/ceph/src/cls/refcount/cls_refcount_ops.h b/ceph/src/cls/refcount/cls_refcount_ops.h index 813a1c1c9..5cbfe3b8b 100644 --- a/ceph/src/cls/refcount/cls_refcount_ops.h +++ b/ceph/src/cls/refcount/cls_refcount_ops.h @@ -4,8 +4,6 @@ #ifndef CEPH_CLS_REFCOUNT_OPS_H #define CEPH_CLS_REFCOUNT_OPS_H -#include - #include "include/types.h" class Formatter; diff --git a/ceph/src/cls/replica_log/cls_replica_log.cc b/ceph/src/cls/replica_log/cls_replica_log.cc index bc8f08871..e8ae3bc3d 100644 --- a/ceph/src/cls/replica_log/cls_replica_log.cc +++ b/ceph/src/cls/replica_log/cls_replica_log.cc @@ -10,7 +10,6 @@ */ #include "objclass/objclass.h" -#include "global/global_context.h" #include "cls_replica_log_types.h" #include "cls_replica_log_ops.h" diff --git a/ceph/src/cls/replica_log/cls_replica_log_client.cc b/ceph/src/cls/replica_log/cls_replica_log_client.cc index 5591389c7..13e876dc2 100644 --- a/ceph/src/cls/replica_log/cls_replica_log_client.cc +++ b/ceph/src/cls/replica_log/cls_replica_log_client.cc @@ -9,7 +9,7 @@ #include -#include "cls/replica_log/cls_replica_log_ops.h" +#include "cls/replica_log/cls_replica_log_client.h" #include "include/rados/librados.hpp" using namespace librados; diff --git a/ceph/src/cls/replica_log/cls_replica_log_client.h b/ceph/src/cls/replica_log/cls_replica_log_client.h index d1a83e08f..407de814d 100644 --- a/ceph/src/cls/replica_log/cls_replica_log_client.h +++ b/ceph/src/cls/replica_log/cls_replica_log_client.h @@ -12,8 +12,12 @@ #ifndef CLS_REPLICA_LOG_CLIENT_H_ #define CLS_REPLICA_LOG_CLIENT_H_ -#include "include/rados/librados.hpp" -#include "cls_replica_log_types.h" +#include "cls_replica_log_ops.h" + +namespace librados { + class ObjectWriteOperation; + class IoCtx; +} /** * Prepare a progress marker object to send out. diff --git a/ceph/src/cls/replica_log/cls_replica_log_ops.h b/ceph/src/cls/replica_log/cls_replica_log_ops.h index c5361a019..85ba5e08d 100644 --- a/ceph/src/cls/replica_log/cls_replica_log_ops.h +++ b/ceph/src/cls/replica_log/cls_replica_log_ops.h @@ -10,7 +10,6 @@ #ifndef CLS_REPLICA_LOG_OPS_H_ #define CLS_REPLICA_LOG_OPS_H_ -#include "include/types.h" #include "cls_replica_log_types.h" struct cls_replica_log_delete_marker_op { diff --git a/ceph/src/cls/rgw/cls_rgw.cc b/ceph/src/cls/rgw/cls_rgw.cc index aad9b4f8a..05cbb8ce9 100644 --- a/ceph/src/cls/rgw/cls_rgw.cc +++ b/ceph/src/cls/rgw/cls_rgw.cc @@ -1,15 +1,10 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "include/int_types.h" #include "include/types.h" -#include -#include -#include #include -#include "common/ceph_time.h" #include "objclass/objclass.h" #include "cls/rgw/cls_rgw_ops.h" #include "cls/rgw/cls_rgw_const.h" @@ -17,7 +12,6 @@ #include "common/strtol.h" #include "common/escape.h" -#include "global/global_context.h" #include "include/compat.h" CLS_VER(1,0) @@ -111,7 +105,7 @@ static void bi_log_index_key(cls_method_context_t hctx, string& key, string& id, static int log_index_operation(cls_method_context_t hctx, cls_rgw_obj_key& obj_key, RGWModifyOp op, string& tag, real_time& timestamp, rgw_bucket_entry_ver& ver, RGWPendingState state, uint64_t index_ver, - string& max_marker, uint16_t bilog_flags, string *owner, string *owner_display_name) + string& max_marker, uint16_t bilog_flags, string *owner, string *owner_display_name, rgw_zone_set *zones_trace) { bufferlist bl; @@ -132,6 +126,9 @@ static int log_index_operation(cls_method_context_t hctx, cls_rgw_obj_key& obj_k if (owner_display_name) { entry.owner_display_name = *owner_display_name; } + if (zones_trace) { + entry.zones_trace = std::move(*zones_trace); + } string key; bi_log_index_key(hctx, key, entry.id, index_ver); @@ -367,6 +364,11 @@ static int read_bucket_header(cls_method_context_t hctx, struct rgw_bucket_dir_h int rc = cls_cxx_map_read_header(hctx, &bl); if (rc < 0) return rc; + + if (bl.length() == 0) { + *header = rgw_bucket_dir_header(); + return 0; + } bufferlist::iterator iter = bl.begin(); try { ::decode(*header, iter); @@ -689,7 +691,7 @@ int rgw_bucket_prepare_op(cls_method_context_t hctx, bufferlist *in, bufferlist if (op.log_op) { rc = log_index_operation(hctx, op.key, op.op, op.tag, entry.meta.mtime, - entry.ver, info.state, header.ver, header.max_marker, op.bilog_flags, NULL, NULL); + entry.ver, info.state, header.ver, header.max_marker, op.bilog_flags, NULL, NULL, &op.zones_trace); if (rc < 0) return rc; } @@ -846,7 +848,7 @@ int rgw_bucket_complete_op(cls_method_context_t hctx, bufferlist *in, bufferlist if (cancel) { if (op.log_op) { rc = log_index_operation(hctx, op.key, op.op, op.tag, entry.meta.mtime, entry.ver, - CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags, NULL, NULL); + CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags, NULL, NULL, &op.zones_trace); if (rc < 0) return rc; } @@ -908,7 +910,7 @@ int rgw_bucket_complete_op(cls_method_context_t hctx, bufferlist *in, bufferlist if (op.log_op) { rc = log_index_operation(hctx, op.key, op.op, op.tag, entry.meta.mtime, entry.ver, - CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags, NULL, NULL); + CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags, NULL, NULL, &op.zones_trace); if (rc < 0) return rc; } @@ -933,7 +935,7 @@ int rgw_bucket_complete_op(cls_method_context_t hctx, bufferlist *in, bufferlist if (op.log_op) { rc = log_index_operation(hctx, remove_key, CLS_RGW_OP_DEL, op.tag, remove_entry.meta.mtime, - remove_entry.ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags, NULL, NULL); + remove_entry.ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags, NULL, NULL, &op.zones_trace); if (rc < 0) continue; } @@ -1536,7 +1538,7 @@ static int rgw_bucket_link_olh(cls_method_context_t hctx, bufferlist *in, buffer ret = log_index_operation(hctx, op.key, operation, op.op_tag, entry.meta.mtime, ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, op.bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP, - powner, powner_display_name); + powner, powner_display_name, &op.zones_trace); if (ret < 0) return ret; } @@ -1682,7 +1684,7 @@ static int rgw_bucket_unlink_instance(cls_method_context_t hctx, bufferlist *in, ret = log_index_operation(hctx, op.key, CLS_RGW_OP_UNLINK_INSTANCE, op.op_tag, mtime, ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, - op.bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP, NULL, NULL); + op.bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP, NULL, NULL, &op.zones_trace); if (ret < 0) return ret; } @@ -1942,7 +1944,7 @@ int rgw_dir_suggest_changes(cls_method_context_t hctx, bufferlist *in, bufferlis return ret; if (log_op && cur_disk.exists) { ret = log_index_operation(hctx, cur_disk.key, CLS_RGW_OP_DEL, cur_disk.tag, cur_disk.meta.mtime, - cur_disk.ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, 0, NULL, NULL); + cur_disk.ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, 0, NULL, NULL, NULL); if (ret < 0) { CLS_LOG(0, "ERROR: %s(): failed to log operation ret=%d", __func__, ret); return ret; @@ -1965,7 +1967,7 @@ int rgw_dir_suggest_changes(cls_method_context_t hctx, bufferlist *in, bufferlis return ret; if (log_op) { ret = log_index_operation(hctx, cur_change.key, CLS_RGW_OP_ADD, cur_change.tag, cur_change.meta.mtime, - cur_change.ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, 0, NULL, NULL); + cur_change.ver, CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker, 0, NULL, NULL, NULL); if (ret < 0) { CLS_LOG(0, "ERROR: %s(): failed to log operation ret=%d", __func__, ret); return ret; @@ -3176,10 +3178,10 @@ static int gc_iterate_entries(cls_method_context_t hctx, const string& marker, b *truncated = false; string start_key; - if (key_iter.empty()) { + if (marker.empty()) { prepend_index_prefix(marker, GC_OBJ_TIME_INDEX, &start_key); } else { - start_key = key_iter; + start_key = marker; } if (expired_only) { @@ -3223,7 +3225,8 @@ static int gc_iterate_entries(cls_method_context_t hctx, const string& marker, b if (max_entries && (i >= max_entries)) { if (truncated) *truncated = true; - key_iter = key; + --iter; + key_iter = iter->first; return 0; } @@ -3248,11 +3251,10 @@ static int gc_list_cb(cls_method_context_t hctx, const string& key, cls_rgw_gc_o static int gc_list_entries(cls_method_context_t hctx, const string& marker, uint32_t max, bool expired_only, - list& entries, bool *truncated) + list& entries, bool *truncated, string& next_marker) { - string key_iter; int ret = gc_iterate_entries(hctx, marker, expired_only, - key_iter, max, truncated, + next_marker, max, truncated, gc_list_cb, &entries); return ret; } @@ -3270,7 +3272,8 @@ static int rgw_cls_gc_list(cls_method_context_t hctx, bufferlist *in, bufferlist } cls_rgw_gc_list_ret op_ret; - int ret = gc_list_entries(hctx, op.marker, op.max, op.expired_only, op_ret.entries, &op_ret.truncated); + int ret = gc_list_entries(hctx, op.marker, op.max, op.expired_only, + op_ret.entries, &op_ret.truncated, op_ret.next_marker); if (ret < 0) return ret; @@ -3476,6 +3479,246 @@ static int rgw_cls_lc_get_head(cls_method_context_t hctx, bufferlist *in, buffe return 0; } +static int rgw_reshard_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_rgw_reshard_add_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: rgw_reshard_add: failed to decode entry\n"); + return -EINVAL; + } + + + string key; + op.entry.get_key(&key); + + bufferlist bl; + ::encode(op.entry, bl); + int ret = cls_cxx_map_set_val(hctx, key, &bl); + if (ret < 0) { + CLS_ERR("error adding reshard job for bucket %s with key %s",op.entry.bucket_name.c_str(), key.c_str()); + return ret; + } + + return ret; +} + +static int rgw_reshard_list(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + cls_rgw_reshard_list_op op; + bufferlist::iterator in_iter = in->begin(); + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: rgw_cls_rehard_list(): failed to decode entry\n"); + return -EINVAL; + } + cls_rgw_reshard_list_ret op_ret; + bufferlist::iterator iter; + map vals; + string filter_prefix; +#define MAX_RESHARD_LIST_ENTRIES 1000 + /* one extra entry for identifying truncation */ + int32_t max = (op.max < MAX_RESHARD_LIST_ENTRIES ? op.max : MAX_RESHARD_LIST_ENTRIES) + 1; + int ret = cls_cxx_map_get_vals(hctx, op.marker, filter_prefix, max, &vals); + if (ret < 0) + return ret; + map::iterator it; + cls_rgw_reshard_entry entry; + int i = 0; + for (it = vals.begin(); i < (int)op.max && it != vals.end(); ++it, ++i) { + iter = it->second.begin(); + try { + ::decode(entry, iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: rgw_cls_rehard_list(): failed to decode entry\n"); + return -EIO; + } + op_ret.entries.push_back(entry); + } + op_ret.is_truncated = op.max && (vals.size() > op.max); + ::encode(op_ret, *out); + return 0; +} + +static int get_reshard_entry(cls_method_context_t hctx, const string& key, cls_rgw_reshard_entry *entry) +{ + bufferlist bl; + int ret = cls_cxx_map_get_val(hctx, key, &bl); + if (ret < 0) + return ret; + bufferlist::iterator iter = bl.begin(); + try { + ::decode(*entry, iter); + } catch (buffer::error& err) { + CLS_LOG(0, "ERROR: %s : failed to decode entry %s\n", __func__, err.what()); + return -EIO; + } + return 0; +} + +static int rgw_reshard_get(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_rgw_reshard_get_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: rgw_reshard_get: failed to decode entry\n"); + return -EINVAL; + } + + string key; + cls_rgw_reshard_entry entry; + op.entry.get_key(&key); + int ret = get_reshard_entry(hctx, key, &entry); + if (ret < 0) { + return ret; + } + + cls_rgw_reshard_get_ret op_ret; + op_ret.entry = entry; + ::encode(op_ret, *out); + return 0; +} + +static int rgw_reshard_remove(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_rgw_reshard_remove_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: rgw_cls_rehard_remove: failed to decode entry\n"); + return -EINVAL; + } + + string key; + cls_rgw_reshard_entry entry; + cls_rgw_reshard_entry::generate_key(op.tenant, op.bucket_name, &key); + int ret = get_reshard_entry(hctx, key, &entry); + if (ret < 0) { + return ret; + } + + if (!op.bucket_id.empty() && + entry.bucket_id != op.bucket_id) { + return 0; + } + + ret = cls_cxx_map_remove_key(hctx, key); + if (ret < 0) { + CLS_LOG(0, "ERROR: failed to remove key: key=%s ret=%d", key.c_str(), ret); + return 0; + } + return ret; +} + +static int rgw_set_bucket_resharding(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + cls_rgw_set_bucket_resharding_op op; + + bufferlist::iterator in_iter = in->begin(); + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_set_bucket_resharding: failed to decode entry\n"); + return -EINVAL; + } + + struct rgw_bucket_dir_header header; + int rc = read_bucket_header(hctx, &header); + if (rc < 0) { + CLS_LOG(1, "ERROR: %s(): failed to read header\n", __func__); + return rc; + } + + header.new_instance.set_status(op.entry.new_bucket_instance_id, op.entry.num_shards, op.entry.reshard_status); + + return write_bucket_header(hctx, &header); +} + +static int rgw_clear_bucket_resharding(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + cls_rgw_set_bucket_resharding_op op; + + bufferlist::iterator in_iter = in->begin(); + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_clear_bucket_resharding: failed to decode entry\n"); + return -EINVAL; + } + + struct rgw_bucket_dir_header header; + int rc = read_bucket_header(hctx, &header); + if (rc < 0) { + CLS_LOG(1, "ERROR: %s(): failed to read header\n", __func__); + return rc; + } + header.new_instance.clear(); + + return write_bucket_header(hctx, &header); +} + +static int rgw_guard_bucket_resharding(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + cls_rgw_guard_bucket_resharding_op op; + + bufferlist::iterator in_iter = in->begin(); + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_clear_bucket_resharding: failed to decode entry\n"); + return -EINVAL; + } + + struct rgw_bucket_dir_header header; + int rc = read_bucket_header(hctx, &header); + if (rc < 0) { + CLS_LOG(1, "ERROR: %s(): failed to read header\n", __func__); + return rc; + } + + if (header.resharding()) { + return op.ret_err; + } + + return 0; +} + +static int rgw_get_bucket_resharding(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + cls_rgw_get_bucket_resharding_op op; + + bufferlist::iterator in_iter = in->begin(); + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_rgw_clear_bucket_resharding: failed to decode entry\n"); + return -EINVAL; + } + + struct rgw_bucket_dir_header header; + int rc = read_bucket_header(hctx, &header); + if (rc < 0) { + CLS_LOG(1, "ERROR: %s(): failed to read header\n", __func__); + return rc; + } + + cls_rgw_get_bucket_resharding_ret op_ret; + op_ret.new_instance = header.new_instance; + + ::encode(op_ret, *out); + + return 0; +} + CLS_INIT(rgw) { CLS_LOG(1, "Loaded rgw class!"); @@ -3515,6 +3758,14 @@ CLS_INIT(rgw) cls_method_handle_t h_rgw_lc_put_head; cls_method_handle_t h_rgw_lc_get_head; cls_method_handle_t h_rgw_lc_list_entries; + cls_method_handle_t h_rgw_reshard_add; + cls_method_handle_t h_rgw_reshard_list; + cls_method_handle_t h_rgw_reshard_get; + cls_method_handle_t h_rgw_reshard_remove; + cls_method_handle_t h_rgw_set_bucket_resharding; + cls_method_handle_t h_rgw_clear_bucket_resharding; + cls_method_handle_t h_rgw_guard_bucket_resharding; + cls_method_handle_t h_rgw_get_bucket_resharding; cls_register(RGW_CLASS, &h_class); @@ -3565,7 +3816,19 @@ CLS_INIT(rgw) cls_register_cxx_method(h_class, RGW_LC_PUT_HEAD, CLS_METHOD_RD| CLS_METHOD_WR, rgw_cls_lc_put_head, &h_rgw_lc_put_head); cls_register_cxx_method(h_class, RGW_LC_GET_HEAD, CLS_METHOD_RD, rgw_cls_lc_get_head, &h_rgw_lc_get_head); cls_register_cxx_method(h_class, RGW_LC_LIST_ENTRIES, CLS_METHOD_RD, rgw_cls_lc_list_entries, &h_rgw_lc_list_entries); - + cls_register_cxx_method(h_class, "reshard_add", CLS_METHOD_RD | CLS_METHOD_WR, rgw_reshard_add, &h_rgw_reshard_add); + cls_register_cxx_method(h_class, "reshard_list", CLS_METHOD_RD, rgw_reshard_list, &h_rgw_reshard_list); + cls_register_cxx_method(h_class, "reshard_get", CLS_METHOD_RD,rgw_reshard_get, &h_rgw_reshard_get); + cls_register_cxx_method(h_class, "reshard_remove", CLS_METHOD_RD | CLS_METHOD_WR, rgw_reshard_remove, &h_rgw_reshard_remove); + cls_register_cxx_method(h_class, "set_bucket_resharding", CLS_METHOD_RD | CLS_METHOD_WR, + rgw_set_bucket_resharding, &h_rgw_set_bucket_resharding); + cls_register_cxx_method(h_class, "clear_bucket_resharding", CLS_METHOD_RD | CLS_METHOD_WR, + rgw_clear_bucket_resharding, &h_rgw_clear_bucket_resharding); + cls_register_cxx_method(h_class, "guard_bucket_resharding", CLS_METHOD_RD , + rgw_guard_bucket_resharding, &h_rgw_guard_bucket_resharding); + cls_register_cxx_method(h_class, "get_bucket_resharding", CLS_METHOD_RD , + rgw_get_bucket_resharding, &h_rgw_get_bucket_resharding); + return; } diff --git a/ceph/src/cls/rgw/cls_rgw_client.cc b/ceph/src/cls/rgw/cls_rgw_client.cc index 969a467d1..dd357779a 100644 --- a/ceph/src/cls/rgw/cls_rgw_client.cc +++ b/ceph/src/cls/rgw/cls_rgw_client.cc @@ -2,11 +2,8 @@ // vim: ts=8 sw=2 smarttab #include -#include "include/types.h" -#include "cls/rgw/cls_rgw_ops.h" #include "cls/rgw/cls_rgw_const.h" #include "cls/rgw/cls_rgw_client.h" -#include "include/rados/librados.hpp" #include "common/debug.h" @@ -152,7 +149,7 @@ void cls_rgw_bucket_update_stats(librados::ObjectWriteOperation& o, bool absolut void cls_rgw_bucket_prepare_op(ObjectWriteOperation& o, RGWModifyOp op, string& tag, const cls_rgw_obj_key& key, const string& locator, bool log_op, - uint16_t bilog_flags) + uint16_t bilog_flags, rgw_zone_set& zones_trace) { struct rgw_cls_obj_prepare_op call; call.op = op; @@ -161,6 +158,7 @@ void cls_rgw_bucket_prepare_op(ObjectWriteOperation& o, RGWModifyOp op, string& call.locator = locator; call.log_op = log_op; call.bilog_flags = bilog_flags; + call.zones_trace = zones_trace; bufferlist in; ::encode(call, in); o.exec(RGW_CLASS, RGW_BUCKET_PREPARE_OP, in); @@ -171,7 +169,8 @@ void cls_rgw_bucket_complete_op(ObjectWriteOperation& o, RGWModifyOp op, string& const cls_rgw_obj_key& key, rgw_bucket_dir_entry_meta& dir_meta, list *remove_objs, bool log_op, - uint16_t bilog_flags) + uint16_t bilog_flags, + rgw_zone_set *zones_trace) { bufferlist in; @@ -185,6 +184,9 @@ void cls_rgw_bucket_complete_op(ObjectWriteOperation& o, RGWModifyOp op, string& call.bilog_flags = bilog_flags; if (remove_objs) call.remove_objs = *remove_objs; + if (zones_trace) { + call.zones_trace = *zones_trace; + } ::encode(call, in); o.exec(RGW_CLASS, RGW_BUCKET_COMPLETE_OP, in); } @@ -326,9 +328,10 @@ int cls_rgw_bi_list(librados::IoCtx& io_ctx, const string oid, return 0; } -int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag, +int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, + const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag, bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op) + uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op, rgw_zone_set& zones_trace) { bufferlist in, out; struct rgw_cls_link_olh_op call; @@ -343,17 +346,20 @@ int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, const string& oid, const cl call.log_op = log_op; call.unmod_since = unmod_since; call.high_precision_time = high_precision_time; + call.zones_trace = zones_trace; ::encode(call, in); - int r = io_ctx.exec(oid, RGW_CLASS, RGW_BUCKET_LINK_OLH, in, out); + op.exec(RGW_CLASS, RGW_BUCKET_LINK_OLH, in); + int r = io_ctx.operate(oid, &op); if (r < 0) return r; return 0; } -int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const string& oid, +int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, + const string& oid, const cls_rgw_obj_key& key, const string& op_tag, - const string& olh_tag, uint64_t olh_epoch, bool log_op) + const string& olh_tag, uint64_t olh_epoch, bool log_op, rgw_zone_set& zones_trace) { bufferlist in, out; struct rgw_cls_unlink_instance_op call; @@ -362,8 +368,10 @@ int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const string& oid, call.olh_epoch = olh_epoch; call.olh_tag = olh_tag; call.log_op = log_op; + call.zones_trace = zones_trace; ::encode(call, in); - int r = io_ctx.exec(oid, RGW_CLASS, RGW_BUCKET_UNLINK_INSTANCE, in, out); + op.exec(RGW_CLASS, RGW_BUCKET_UNLINK_INSTANCE, in); + int r = io_ctx.operate(oid, &op); if (r < 0) return r; @@ -419,14 +427,13 @@ void cls_rgw_trim_olh_log(librados::ObjectWriteOperation& op, const cls_rgw_obj_ op.exec(RGW_CLASS, RGW_BUCKET_TRIM_OLH_LOG, in); } -int cls_rgw_clear_olh(IoCtx& io_ctx, string& oid, const cls_rgw_obj_key& olh, const string& olh_tag) +int cls_rgw_clear_olh(IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid, const cls_rgw_obj_key& olh, const string& olh_tag) { bufferlist in, out; struct rgw_cls_bucket_clear_olh_op call; call.key = olh; call.olh_tag = olh_tag; ::encode(call, in); - librados::ObjectWriteOperation op; int op_ret; op.exec(RGW_CLASS, RGW_BUCKET_CLEAR_OLH, in, &out, &op_ret); int r = io_ctx.operate(oid, &op); @@ -635,7 +642,7 @@ void cls_rgw_gc_defer_entry(ObjectWriteOperation& op, uint32_t expiration_secs, } int cls_rgw_gc_list(IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bool expired_only, - list& entries, bool *truncated) + list& entries, bool *truncated, string& next_marker) { bufferlist in, out; cls_rgw_gc_list_op call; @@ -659,8 +666,8 @@ int cls_rgw_gc_list(IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bo if (truncated) *truncated = ret.truncated; - - return r; + next_marker = std::move(ret.next_marker); + return r; } void cls_rgw_gc_remove(librados::ObjectWriteOperation& op, const list& tags) @@ -773,3 +780,140 @@ int cls_rgw_lc_list(IoCtx& io_ctx, string& oid, return r; } + +void cls_rgw_reshard_add(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry) +{ + bufferlist in; + struct cls_rgw_reshard_add_op call; + call.entry = entry; + ::encode(call, in); + op.exec("rgw", "reshard_add", in); +} + +int cls_rgw_reshard_list(librados::IoCtx& io_ctx, const string& oid, string& marker, uint32_t max, + list& entries, bool* is_truncated) +{ + bufferlist in, out; + struct cls_rgw_reshard_list_op call; + call.marker = marker; + call.max = max; + ::encode(call, in); + int r = io_ctx.exec(oid, "rgw", "reshard_list", in, out); + if (r < 0) + return r; + + struct cls_rgw_reshard_list_ret op_ret; + bufferlist::iterator iter = out.begin(); + try { + ::decode(op_ret, iter); + } catch (buffer::error& err) { + return -EIO; + } + + entries.swap(op_ret.entries); + *is_truncated = op_ret.is_truncated; + + return 0; +} + +int cls_rgw_reshard_get(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry) +{ + bufferlist in, out; + struct cls_rgw_reshard_get_op call; + call.entry = entry; + ::encode(call, in); + int r = io_ctx.exec(oid, "rgw", "reshard_get", in, out); + if (r < 0) + return r; + + struct cls_rgw_reshard_get_ret op_ret; + bufferlist::iterator iter = out.begin(); + try { + ::decode(op_ret, iter); + } catch (buffer::error& err) { + return -EIO; + } + + entry = op_ret.entry; + + return 0; +} + +void cls_rgw_reshard_remove(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry) +{ + bufferlist in; + struct cls_rgw_reshard_remove_op call; + call.tenant = entry.tenant; + call.bucket_name = entry.bucket_name; + call.bucket_id = entry.bucket_id; + ::encode(call, in); + op.exec("rgw", "reshard_remove", in); +} + +int cls_rgw_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid, + const cls_rgw_bucket_instance_entry& entry) +{ + bufferlist in, out; + struct cls_rgw_set_bucket_resharding_op call; + call.entry = entry; + ::encode(call, in); + return io_ctx.exec(oid, "rgw", "set_bucket_resharding", in, out); +} + +int cls_rgw_clear_bucket_resharding(librados::IoCtx& io_ctx, const string& oid) +{ + bufferlist in, out; + struct cls_rgw_clear_bucket_resharding_op call; + ::encode(call, in); + return io_ctx.exec(oid, "rgw", "clear_bucket_resharding", in, out); +} + +int cls_rgw_get_bucket_resharding(librados::IoCtx& io_ctx, const string& oid, + cls_rgw_bucket_instance_entry *entry) +{ + bufferlist in, out; + struct cls_rgw_get_bucket_resharding_op call; + ::encode(call, in); + int r= io_ctx.exec(oid, "rgw", "get_bucket_resharding", in, out); + if (r < 0) + return r; + + struct cls_rgw_get_bucket_resharding_ret op_ret; + bufferlist::iterator iter = out.begin(); + try { + ::decode(op_ret, iter); + } catch (buffer::error& err) { + return -EIO; + } + + *entry = op_ret.new_instance; + + return 0; +} + +void cls_rgw_guard_bucket_resharding(librados::ObjectOperation& op, int ret_err) +{ + bufferlist in, out; + struct cls_rgw_guard_bucket_resharding_op call; + call.ret_err = ret_err; + ::encode(call, in); + op.exec("rgw", "guard_bucket_resharding", in); +} + +static bool issue_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid, + const cls_rgw_bucket_instance_entry& entry, + BucketIndexAioManager *manager) { + bufferlist in; + struct cls_rgw_set_bucket_resharding_op call; + call.entry = entry; + ::encode(call, in); + librados::ObjectWriteOperation op; + op.exec("rgw", "set_bucket_resharding", in); + return manager->aio_operate(io_ctx, oid, &op); +} + +int CLSRGWIssueSetBucketResharding::issue_op(int shard_id, const string& oid) +{ + return issue_set_bucket_resharding(io_ctx, oid, entry, &manager); +} + diff --git a/ceph/src/cls/rgw/cls_rgw_client.h b/ceph/src/cls/rgw/cls_rgw_client.h index aa2413fdb..ebedbc283 100644 --- a/ceph/src/cls/rgw/cls_rgw_client.h +++ b/ceph/src/cls/rgw/cls_rgw_client.h @@ -1,10 +1,8 @@ #ifndef CEPH_CLS_RGW_CLIENT_H #define CEPH_CLS_RGW_CLIENT_H -#include "include/types.h" #include "include/str_list.h" #include "include/rados/librados.hpp" -#include "cls_rgw_types.h" #include "cls_rgw_ops.h" #include "common/RefCountedObj.h" #include "include/compat.h" @@ -12,7 +10,6 @@ // Forward declaration class BucketIndexAioManager; - /* * Bucket index AIO request argument, this is used to pass a argument * to callback. @@ -313,14 +310,14 @@ void cls_rgw_bucket_update_stats(librados::ObjectWriteOperation& o, bool absolut void cls_rgw_bucket_prepare_op(librados::ObjectWriteOperation& o, RGWModifyOp op, string& tag, const cls_rgw_obj_key& key, const string& locator, bool log_op, - uint16_t bilog_op); + uint16_t bilog_op, rgw_zone_set& zones_trace); void cls_rgw_bucket_complete_op(librados::ObjectWriteOperation& o, RGWModifyOp op, string& tag, rgw_bucket_entry_ver& ver, const cls_rgw_obj_key& key, rgw_bucket_dir_entry_meta& dir_meta, list *remove_objs, bool log_op, - uint16_t bilog_op); + uint16_t bilog_op, rgw_zone_set *zones_trace); void cls_rgw_remove_obj(librados::ObjectWriteOperation& o, list& keep_attr_prefixes); void cls_rgw_obj_store_pg_ver(librados::ObjectWriteOperation& o, const string& attr); @@ -337,16 +334,18 @@ int cls_rgw_bi_list(librados::IoCtx& io_ctx, const string oid, list *entries, bool *is_truncated); -int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag, +int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, + const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag, bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op); -int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, const string& op_tag, - const string& olh_tag, uint64_t olh_epoch, bool log_op); + uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op, rgw_zone_set& zones_trace); +int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, + const string& oid, const cls_rgw_obj_key& key, const string& op_tag, + const string& olh_tag, uint64_t olh_epoch, bool log_op, rgw_zone_set& zones_trace); int cls_rgw_get_olh_log(librados::IoCtx& io_ctx, string& oid, librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker, const string& olh_tag, map > *log, bool *is_truncated); void cls_rgw_trim_olh_log(librados::ObjectWriteOperation& op, const cls_rgw_obj_key& olh, uint64_t ver, const string& olh_tag); -int cls_rgw_clear_olh(librados::IoCtx& io_ctx, string& oid, const cls_rgw_obj_key& olh, const string& olh_tag); +int cls_rgw_clear_olh(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid, const cls_rgw_obj_key& olh, const string& olh_tag); /** * List the bucket with the starting object and filter prefix. @@ -456,6 +455,16 @@ public: CLSRGWConcurrentIO(io_ctx, oids, max_aio), result(dir_headers) {} }; +class CLSRGWIssueSetBucketResharding : public CLSRGWConcurrentIO { + cls_rgw_bucket_instance_entry entry; +protected: + int issue_op(int shard_id, const string& oid) override; +public: + CLSRGWIssueSetBucketResharding(librados::IoCtx& ioc, map& _bucket_objs, + const cls_rgw_bucket_instance_entry& _entry, + uint32_t _max_aio) : CLSRGWConcurrentIO(ioc, _bucket_objs, _max_aio), entry(_entry) {} +}; + int cls_rgw_get_dir_header_async(librados::IoCtx& io_ctx, string& oid, RGWGetDirHeader_CB *ctx); void cls_rgw_encode_suggestion(char op, rgw_bucket_dir_entry& dirent, bufferlist& updates); @@ -478,7 +487,7 @@ void cls_rgw_gc_set_entry(librados::ObjectWriteOperation& op, uint32_t expiratio void cls_rgw_gc_defer_entry(librados::ObjectWriteOperation& op, uint32_t expiration_secs, const string& tag); int cls_rgw_gc_list(librados::IoCtx& io_ctx, string& oid, string& marker, uint32_t max, bool expired_only, - list& entries, bool *truncated); + list& entries, bool *truncated, string& next_marker); void cls_rgw_gc_remove(librados::ObjectWriteOperation& op, const list& tags); @@ -493,9 +502,20 @@ int cls_rgw_lc_list(librados::IoCtx& io_ctx, string& oid, uint32_t max_entries, map& entries); - - - - +/* resharding */ +void cls_rgw_reshard_add(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry); +int cls_rgw_reshard_list(librados::IoCtx& io_ctx, const string& oid, string& marker, uint32_t max, + list& entries, bool* is_truncated); +int cls_rgw_reshard_get(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry); +int cls_rgw_reshard_get_head(librados::IoCtx& io_ctx, const string& oid, cls_rgw_reshard_entry& entry); +void cls_rgw_reshard_remove(librados::ObjectWriteOperation& op, const cls_rgw_reshard_entry& entry); + +/* resharding attribute */ +int cls_rgw_set_bucket_resharding(librados::IoCtx& io_ctx, const string& oid, + const cls_rgw_bucket_instance_entry& entry); +int cls_rgw_clear_bucket_resharding(librados::IoCtx& io_ctx, const string& oid); +void cls_rgw_guard_bucket_resharding(librados::ObjectOperation& op, int ret_err); +int cls_rgw_get_bucket_resharding(librados::IoCtx& io_ctx, const string& oid, + cls_rgw_bucket_instance_entry *entry); #endif diff --git a/ceph/src/cls/rgw/cls_rgw_ops.cc b/ceph/src/cls/rgw/cls_rgw_ops.cc index 0b3701bf9..82ad868bf 100644 --- a/ceph/src/cls/rgw/cls_rgw_ops.cc +++ b/ceph/src/cls/rgw/cls_rgw_ops.cc @@ -64,6 +64,7 @@ void cls_rgw_gc_list_op::generate_test_instances(list& ls) void cls_rgw_gc_list_ret::dump(Formatter *f) const { encode_json("entries", entries, f); + f->dump_string("next_marker", next_marker); f->dump_int("truncated", (int)truncated); } @@ -108,6 +109,7 @@ void rgw_cls_obj_prepare_op::dump(Formatter *f) const f->dump_string("locator", locator); f->dump_bool("log_op", log_op); f->dump_int("bilog_flags", bilog_flags); + ::encode_json("zones_trace", zones_trace, f); } void rgw_cls_obj_complete_op::generate_test_instances(list& o) @@ -145,6 +147,7 @@ void rgw_cls_obj_complete_op::dump(Formatter *f) const f->dump_string("tag", tag); f->dump_bool("log_op", log_op); f->dump_int("bilog_flags", bilog_flags); + ::encode_json("zones_trace", zones_trace, f); } void rgw_cls_link_olh_op::generate_test_instances(list& o) @@ -179,6 +182,7 @@ void rgw_cls_link_olh_op::dump(Formatter *f) const utime_t ut(unmod_since); ::encode_json("unmod_since", ut, f); ::encode_json("high_precision_time", high_precision_time, f); + ::encode_json("zones_trace", zones_trace, f); } void rgw_cls_unlink_instance_op::generate_test_instances(list& o) @@ -201,6 +205,7 @@ void rgw_cls_unlink_instance_op::dump(Formatter *f) const ::encode_json("olh_epoch", olh_epoch, f); ::encode_json("log_op", log_op, f); ::encode_json("bilog_flags", (uint32_t)bilog_flags, f); + ::encode_json("zones_trace", zones_trace, f); } void rgw_cls_read_olh_log_op::generate_test_instances(list& o) @@ -407,3 +412,135 @@ void cls_rgw_bi_log_list_ret::generate_test_instances(listentries.push_back(rgw_bi_log_entry()); ls.back()->truncated = true; } + +void cls_rgw_reshard_add_op::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_add_op); + ls.push_back(new cls_rgw_reshard_add_op); + list l; + cls_rgw_reshard_entry::generate_test_instances(l); + list::iterator iter = l.begin(); + ls.back()->entry = *(*iter); +} + +void cls_rgw_reshard_add_op::dump(Formatter *f) const +{ + ::encode_json("entry", entry, f); +} + +void cls_rgw_reshard_list_op::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_list_op); + ls.push_back(new cls_rgw_reshard_list_op); + ls.back()->max = 1000; + ls.back()->marker = "foo"; +} + +void cls_rgw_reshard_list_op::dump(Formatter *f) const +{ + ::encode_json("max", max, f); + ::encode_json("marker", marker, f); +} + +void cls_rgw_reshard_list_ret::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_list_ret); + ls.push_back(new cls_rgw_reshard_list_ret); + ls.back()->entries.push_back(cls_rgw_reshard_entry()); + ls.back()->is_truncated = true; +} + +void cls_rgw_reshard_list_ret::dump(Formatter *f) const +{ + ::encode_json("entries", entries, f); + ::encode_json("is_truncated", is_truncated, f); +} + +void cls_rgw_reshard_get_op::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_get_op); + ls.push_back(new cls_rgw_reshard_get_op); +} + +void cls_rgw_reshard_get_op::dump(Formatter *f) const +{ + ::encode_json("entry", entry, f); +} + +void cls_rgw_reshard_get_ret::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_get_ret); + ls.push_back(new cls_rgw_reshard_get_ret); +} + +void cls_rgw_reshard_get_ret::dump(Formatter *f) const +{ + ::encode_json("entry", entry, f); +} + +void cls_rgw_reshard_remove_op::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_remove_op); + ls.push_back(new cls_rgw_reshard_remove_op); + ls.back()->bucket_name = "foo"; + ls.back()->bucket_id = "bucket_id"; +} + +void cls_rgw_reshard_remove_op::dump(Formatter *f) const +{ + ::encode_json("bucket_name", bucket_name, f); + ::encode_json("bucket_id", bucket_name, f); +} + + +void cls_rgw_set_bucket_resharding_op::generate_test_instances( + list& ls) +{ + ls.push_back(new cls_rgw_set_bucket_resharding_op); + ls.push_back(new cls_rgw_set_bucket_resharding_op); +} + +void cls_rgw_set_bucket_resharding_op::dump(Formatter *f) const +{ + ::encode_json("entry", entry, f); +} + +void cls_rgw_clear_bucket_resharding_op::generate_test_instances( + list& ls) +{ + ls.push_back(new cls_rgw_clear_bucket_resharding_op); + ls.push_back(new cls_rgw_clear_bucket_resharding_op); +} + +void cls_rgw_clear_bucket_resharding_op::dump(Formatter *f) const +{ +} + +void cls_rgw_guard_bucket_resharding_op::generate_test_instances( + list& ls) +{ + ls.push_back(new cls_rgw_guard_bucket_resharding_op); + ls.push_back(new cls_rgw_guard_bucket_resharding_op); +} + +void cls_rgw_guard_bucket_resharding_op::dump(Formatter *f) const +{ + ::encode_json("ret_err", ret_err, f); +} + + +void cls_rgw_get_bucket_resharding_op::generate_test_instances( + list& ls) +{ + ls.push_back(new cls_rgw_get_bucket_resharding_op); + ls.push_back(new cls_rgw_get_bucket_resharding_op); +} + +void cls_rgw_get_bucket_resharding_op::dump(Formatter *f) const +{ +} + + + + + diff --git a/ceph/src/cls/rgw/cls_rgw_ops.h b/ceph/src/cls/rgw/cls_rgw_ops.h index 740359293..538443adf 100644 --- a/ceph/src/cls/rgw/cls_rgw_ops.h +++ b/ceph/src/cls/rgw/cls_rgw_ops.h @@ -1,10 +1,6 @@ #ifndef CEPH_CLS_RGW_OPS_H #define CEPH_CLS_RGW_OPS_H -#include - -#include "include/types.h" -#include "common/ceph_time.h" #include "cls/rgw/cls_rgw_types.h" struct rgw_cls_tag_timeout_op @@ -36,11 +32,12 @@ struct rgw_cls_obj_prepare_op string locator; bool log_op; uint16_t bilog_flags; + rgw_zone_set zones_trace; rgw_cls_obj_prepare_op() : op(CLS_RGW_OP_UNKNOWN), log_op(false), bilog_flags(0) {} void encode(bufferlist &bl) const { - ENCODE_START(6, 5, bl); + ENCODE_START(7, 5, bl); uint8_t c = (uint8_t)op; ::encode(c, bl); ::encode(tag, bl); @@ -48,10 +45,11 @@ struct rgw_cls_obj_prepare_op ::encode(log_op, bl); ::encode(key, bl); ::encode(bilog_flags, bl); + ::encode(zones_trace, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl); + DECODE_START_LEGACY_COMPAT_LEN(7, 3, 3, bl); uint8_t c; ::decode(c, bl); op = (RGWModifyOp)c; @@ -71,6 +69,9 @@ struct rgw_cls_obj_prepare_op if (struct_v >= 6) { ::decode(bilog_flags, bl); } + if (struct_v >= 7) { + ::decode(zones_trace, bl); + } DECODE_FINISH(bl); } void dump(Formatter *f) const; @@ -90,11 +91,12 @@ struct rgw_cls_obj_complete_op uint16_t bilog_flags; list remove_objs; + rgw_zone_set zones_trace; rgw_cls_obj_complete_op() : op(CLS_RGW_OP_ADD), log_op(false), bilog_flags(0) {} void encode(bufferlist &bl) const { - ENCODE_START(8, 7, bl); + ENCODE_START(9, 7, bl); uint8_t c = (uint8_t)op; ::encode(c, bl); ::encode(ver.epoch, bl); @@ -106,10 +108,11 @@ struct rgw_cls_obj_complete_op ::encode(log_op, bl); ::encode(key, bl); ::encode(bilog_flags, bl); + ::encode(zones_trace, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(8, 3, 3, bl); + DECODE_START_LEGACY_COMPAT_LEN(9, 3, 3, bl); uint8_t c; ::decode(c, bl); op = (RGWModifyOp)c; @@ -149,6 +152,9 @@ struct rgw_cls_obj_complete_op if (struct_v >= 8) { ::decode(bilog_flags, bl); } + if (struct_v >= 9) { + ::decode(zones_trace, bl); + } DECODE_FINISH(bl); } void dump(Formatter *f) const; @@ -167,11 +173,12 @@ struct rgw_cls_link_olh_op { uint16_t bilog_flags; real_time unmod_since; /* only create delete marker if newer then this */ bool high_precision_time; + rgw_zone_set zones_trace; rgw_cls_link_olh_op() : delete_marker(false), olh_epoch(0), log_op(false), bilog_flags(0), high_precision_time(false) {} void encode(bufferlist& bl) const { - ENCODE_START(4, 1, bl); + ENCODE_START(5, 1, bl); ::encode(key, bl); ::encode(olh_tag, bl); ::encode(delete_marker, bl); @@ -184,11 +191,12 @@ struct rgw_cls_link_olh_op { ::encode(t, bl); ::encode(unmod_since, bl); ::encode(high_precision_time, bl); + ::encode(zones_trace, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START(4, bl); + DECODE_START(5, bl); ::decode(key, bl); ::decode(olh_tag, bl); ::decode(delete_marker, bl); @@ -203,11 +211,16 @@ struct rgw_cls_link_olh_op { unmod_since = ceph::real_clock::from_time_t(static_cast(t)); } if (struct_v >= 3) { + uint64_t t; + ::decode(t, bl); ::decode(unmod_since, bl); } if (struct_v >= 4) { ::decode(high_precision_time, bl); } + if (struct_v >= 5) { + ::decode(zones_trace, bl); + } DECODE_FINISH(bl); } @@ -223,22 +236,24 @@ struct rgw_cls_unlink_instance_op { bool log_op; uint16_t bilog_flags; string olh_tag; + rgw_zone_set zones_trace; rgw_cls_unlink_instance_op() : olh_epoch(0), log_op(false), bilog_flags(0) {} void encode(bufferlist& bl) const { - ENCODE_START(2, 1, bl); + ENCODE_START(3, 1, bl); ::encode(key, bl); ::encode(op_tag, bl); ::encode(olh_epoch, bl); ::encode(log_op, bl); ::encode(bilog_flags, bl); ::encode(olh_tag, bl); + ::encode(zones_trace, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START(2, bl); + DECODE_START(3, bl); ::decode(key, bl); ::decode(op_tag, bl); ::decode(olh_epoch, bl); @@ -247,6 +262,9 @@ struct rgw_cls_unlink_instance_op { if (struct_v >= 2) { ::decode(olh_tag, bl); } + if (struct_v >= 3) { + ::decode(zones_trace, bl); + } DECODE_FINISH(bl); } @@ -841,20 +859,24 @@ WRITE_CLASS_ENCODER(cls_rgw_gc_list_op) struct cls_rgw_gc_list_ret { list entries; + string next_marker; bool truncated; cls_rgw_gc_list_ret() : truncated(false) {} void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); ::encode(entries, bl); + ::encode(next_marker, bl); ::encode(truncated, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); ::decode(entries, bl); + if (struct_v >= 2) + ::decode(next_marker, bl); ::decode(truncated, bl); DECODE_FINISH(bl); } @@ -1119,4 +1141,234 @@ struct cls_rgw_lc_list_entries_ret { }; WRITE_CLASS_ENCODER(cls_rgw_lc_list_entries_ret) +struct cls_rgw_reshard_add_op { + cls_rgw_reshard_entry entry; + + cls_rgw_reshard_add_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(entry, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(entry, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_add_op) + +struct cls_rgw_reshard_list_op { + uint32_t max{0}; + string marker; + + cls_rgw_reshard_list_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(max, bl); + ::encode(marker, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(max, bl); + ::decode(marker, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_list_op) + + +struct cls_rgw_reshard_list_ret { + list entries; + bool is_truncated{false}; + + cls_rgw_reshard_list_ret() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(entries, bl); + ::encode(is_truncated, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(entries, bl); + ::decode(is_truncated, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_list_ret) + +struct cls_rgw_reshard_get_op { + cls_rgw_reshard_entry entry; + + cls_rgw_reshard_get_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(entry, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(entry, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_get_op) + +struct cls_rgw_reshard_get_ret { + cls_rgw_reshard_entry entry; + + cls_rgw_reshard_get_ret() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(entry, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(entry, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_get_ret) + +struct cls_rgw_reshard_remove_op { + string tenant; + string bucket_name; + string bucket_id; + + cls_rgw_reshard_remove_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(tenant, bl); + ::encode(bucket_name, bl); + ::encode(bucket_id, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(tenant, bl); + ::decode(bucket_name, bl); + ::decode(bucket_id, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_remove_op) + +struct cls_rgw_set_bucket_resharding_op { + cls_rgw_bucket_instance_entry entry; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(entry, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(entry, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_set_bucket_resharding_op) + +struct cls_rgw_clear_bucket_resharding_op { + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_clear_bucket_resharding_op) + +struct cls_rgw_guard_bucket_resharding_op { + int ret_err{0}; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(ret_err, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(ret_err, bl); + DECODE_FINISH(bl); + } + + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_guard_bucket_resharding_op) + +struct cls_rgw_get_bucket_resharding_op { + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + DECODE_FINISH(bl); + } + + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_get_bucket_resharding_op) + +struct cls_rgw_get_bucket_resharding_ret { + cls_rgw_bucket_instance_entry new_instance; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(new_instance, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(new_instance, bl); + DECODE_FINISH(bl); + } + + static void generate_test_instances(list& o); + void dump(Formatter *f) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_get_bucket_resharding_ret) + #endif /* CEPH_CLS_RGW_OPS_H */ diff --git a/ceph/src/cls/rgw/cls_rgw_types.cc b/ceph/src/cls/rgw/cls_rgw_types.cc index 7d9c83bfa..73b6f2020 100644 --- a/ceph/src/cls/rgw/cls_rgw_types.cc +++ b/ceph/src/cls/rgw/cls_rgw_types.cc @@ -1,6 +1,5 @@ #include "cls/rgw/cls_rgw_types.h" -#include "common/Formatter.h" #include "common/ceph_json.h" #include "include/utime.h" @@ -391,6 +390,7 @@ void rgw_bi_log_entry::decode_json(JSONObj *obj) bilog_flags = (uint16_t)f; JSONDecoder::decode_json("owner", owner, obj); JSONDecoder::decode_json("owner_display_name", owner_display_name, obj); + JSONDecoder::decode_json("zones_trace", zones_trace, obj); } void rgw_bi_log_entry::dump(Formatter *f) const @@ -449,6 +449,7 @@ void rgw_bi_log_entry::dump(Formatter *f) const f->dump_bool("versioned", (bilog_flags & RGW_BILOG_FLAG_VERSIONED_OP) != 0); f->dump_string("owner", owner); f->dump_string("owner_display_name", owner_display_name); + encode_json("zones_trace", zones_trace, f); } void rgw_bi_log_entry::generate_test_instances(list& ls) @@ -515,6 +516,7 @@ void rgw_bucket_dir_header::dump(Formatter *f) const iter->second.dump(f); f->close_section(); } + ::encode_json("new_instance", new_instance, f); f->close_section(); } @@ -563,3 +565,54 @@ void rgw_bucket_dir::dump(Formatter *f) const f->close_section(); } +void cls_rgw_reshard_entry::generate_key(const string& tenant, const string& bucket_name, string *key) +{ + *key = tenant + ":" + bucket_name; +} + +void cls_rgw_reshard_entry::get_key(string *key) const +{ + generate_key(tenant, bucket_name, key); +} + +void cls_rgw_reshard_entry::dump(Formatter *f) const +{ + utime_t ut(time); + encode_json("time",ut, f); + encode_json("tenant", tenant, f); + encode_json("bucket_name", bucket_name, f); + encode_json("bucket_id", bucket_id, f); + encode_json("new_instance_id", new_instance_id, f); + encode_json("old_num_shards", old_num_shards, f); + encode_json("new_num_shards", new_num_shards, f); + +} + +void cls_rgw_reshard_entry::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_reshard_entry); + ls.push_back(new cls_rgw_reshard_entry); + ls.back()->time = ceph::real_clock::from_ceph_timespec({2, 3}); + ls.back()->tenant = "tenant"; + ls.back()->bucket_name = "bucket1"""; + ls.back()->bucket_id = "bucket_id"; + ls.back()->new_instance_id = "new_instance_id"; + ls.back()->old_num_shards = 8; + ls.back()->new_num_shards = 64; +} + +void cls_rgw_bucket_instance_entry::dump(Formatter *f) const +{ + encode_json("reshard_status", (int)reshard_status, f); + encode_json("new_bucket_instance_id", new_bucket_instance_id, f); + encode_json("num_shards", num_shards, f); + +} + +void cls_rgw_bucket_instance_entry::generate_test_instances(list& ls) +{ + ls.push_back(new cls_rgw_bucket_instance_entry); + ls.push_back(new cls_rgw_bucket_instance_entry); + ls.back()->reshard_status = CLS_RGW_RESHARD_IN_PROGRESS; + ls.back()->new_bucket_instance_id = "new_instance_id"; +} diff --git a/ceph/src/cls/rgw/cls_rgw_types.h b/ceph/src/cls/rgw/cls_rgw_types.h index 2b8dae327..cc09cff53 100644 --- a/ceph/src/cls/rgw/cls_rgw_types.h +++ b/ceph/src/cls/rgw/cls_rgw_types.h @@ -1,9 +1,6 @@ #ifndef CEPH_CLS_RGW_TYPES_H #define CEPH_CLS_RGW_TYPES_H -#include - -#include "include/types.h" #include "common/ceph_time.h" #include "common/Formatter.h" @@ -21,6 +18,8 @@ namespace ceph { class Formatter; } +using rgw_zone_set = std::set; + enum RGWPendingState { CLS_RGW_STATE_PENDING_MODIFY = 0, CLS_RGW_STATE_COMPLETE = 1, @@ -510,11 +509,12 @@ struct rgw_bi_log_entry { uint16_t bilog_flags; string owner; /* only being set if it's a delete marker */ string owner_display_name; /* only being set if it's a delete marker */ + rgw_zone_set zones_trace; rgw_bi_log_entry() : op(CLS_RGW_OP_UNKNOWN), state(CLS_RGW_STATE_PENDING_MODIFY), index_ver(0), bilog_flags(0) {} void encode(bufferlist &bl) const { - ENCODE_START(3, 1, bl); + ENCODE_START(4, 1, bl); ::encode(id, bl); ::encode(object, bl); ::encode(timestamp, bl); @@ -529,10 +529,11 @@ struct rgw_bi_log_entry { ::encode(bilog_flags, bl); ::encode(owner, bl); ::encode(owner_display_name, bl); + ::encode(zones_trace, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator &bl) { - DECODE_START(2, bl); + DECODE_START(4, bl); ::decode(id, bl); ::decode(object, bl); ::decode(timestamp, bl); @@ -552,6 +553,9 @@ struct rgw_bi_log_entry { ::decode(owner, bl); ::decode(owner_display_name, bl); } + if (struct_v >= 4) { + ::decode(zones_trace, bl); + } DECODE_FINISH(bl); } void dump(Formatter *f) const; @@ -597,26 +601,80 @@ struct rgw_bucket_category_stats { }; WRITE_CLASS_ENCODER(rgw_bucket_category_stats) +enum cls_rgw_reshard_status { + CLS_RGW_RESHARD_NONE = 0, + CLS_RGW_RESHARD_IN_PROGRESS = 1, + CLS_RGW_RESHARD_DONE = 2, +}; + +struct cls_rgw_bucket_instance_entry { + cls_rgw_reshard_status reshard_status{CLS_RGW_RESHARD_NONE}; + string new_bucket_instance_id; + int32_t num_shards{-1}; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode((uint8_t)reshard_status, bl); + ::encode(new_bucket_instance_id, bl); + ::encode(num_shards, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + uint8_t s; + ::decode(s, bl); + reshard_status = (cls_rgw_reshard_status)s; + ::decode(new_bucket_instance_id, bl); + ::decode(num_shards, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + static void generate_test_instances(list& o); + + void clear() { + reshard_status = CLS_RGW_RESHARD_NONE; + new_bucket_instance_id.clear(); + } + + void set_status(const string& new_instance_id, int32_t new_num_shards, cls_rgw_reshard_status s) { + reshard_status = s; + new_bucket_instance_id = new_instance_id; + num_shards = new_num_shards; + } + + bool resharding() const { + return reshard_status != CLS_RGW_RESHARD_NONE; + } + bool resharding_in_progress() const { + return reshard_status == CLS_RGW_RESHARD_IN_PROGRESS; + } +}; +WRITE_CLASS_ENCODER(cls_rgw_bucket_instance_entry) + struct rgw_bucket_dir_header { map stats; uint64_t tag_timeout; uint64_t ver; uint64_t master_ver; string max_marker; + cls_rgw_bucket_instance_entry new_instance; rgw_bucket_dir_header() : tag_timeout(0), ver(0), master_ver(0) {} void encode(bufferlist &bl) const { - ENCODE_START(5, 2, bl); + ENCODE_START(6, 2, bl); ::encode(stats, bl); ::encode(tag_timeout, bl); ::encode(ver, bl); ::encode(master_ver, bl); ::encode(max_marker, bl); + ::encode(new_instance, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl); + DECODE_START_LEGACY_COMPAT_LEN(6, 2, 2, bl); ::decode(stats, bl); if (struct_v > 2) { ::decode(tag_timeout, bl); @@ -632,10 +690,22 @@ struct rgw_bucket_dir_header { if (struct_v >= 5) { ::decode(max_marker, bl); } + if (struct_v >= 6) { + ::decode(new_instance, bl); + } else { + new_instance = cls_rgw_bucket_instance_entry(); + } DECODE_FINISH(bl); } void dump(Formatter *f) const; static void generate_test_instances(list& o); + + bool resharding() const { + return new_instance.resharding(); + } + bool resharding_in_progress() const { + return new_instance.resharding_in_progress(); + } }; WRITE_CLASS_ENCODER(rgw_bucket_dir_header) @@ -993,4 +1063,48 @@ struct cls_rgw_lc_obj_head }; WRITE_CLASS_ENCODER(cls_rgw_lc_obj_head) +struct cls_rgw_reshard_entry +{ + ceph::real_time time; + string tenant; + string bucket_name; + string bucket_id; + string new_instance_id; + uint32_t old_num_shards{0}; + uint32_t new_num_shards{0}; + + cls_rgw_reshard_entry() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(time, bl); + ::encode(tenant, bl); + ::encode(bucket_name, bl); + ::encode(bucket_id, bl); + ::encode(new_instance_id, bl); + ::encode(old_num_shards, bl); + ::encode(new_num_shards, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(time, bl); + ::decode(tenant, bl); + ::decode(bucket_name, bl); + ::decode(bucket_id, bl); + ::decode(new_instance_id, bl); + ::decode(old_num_shards, bl); + ::decode(new_num_shards, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter *f) const; + static void generate_test_instances(list& o); + + static void generate_key(const string& tenant, const string& bucket_name, string *key); + void get_key(string *key) const; +}; +WRITE_CLASS_ENCODER(cls_rgw_reshard_entry) + #endif diff --git a/ceph/src/cls/statelog/cls_statelog.cc b/ceph/src/cls/statelog/cls_statelog.cc index 74739c289..f404fa77b 100644 --- a/ceph/src/cls/statelog/cls_statelog.cc +++ b/ceph/src/cls/statelog/cls_statelog.cc @@ -1,20 +1,12 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include - -#include -#include #include -#include "include/types.h" -#include "include/utime.h" #include "objclass/objclass.h" -#include "cls_statelog_types.h" #include "cls_statelog_ops.h" -#include "global/global_context.h" CLS_VER(1,0) CLS_NAME(statelog) diff --git a/ceph/src/cls/statelog/cls_statelog_client.cc b/ceph/src/cls/statelog/cls_statelog_client.cc index 3ec31dac3..895e26a6f 100644 --- a/ceph/src/cls/statelog/cls_statelog_client.cc +++ b/ceph/src/cls/statelog/cls_statelog_client.cc @@ -1,7 +1,6 @@ #include -#include "include/types.h" -#include "cls/statelog/cls_statelog_ops.h" +#include "cls/statelog/cls_statelog_client.h" #include "include/rados/librados.hpp" diff --git a/ceph/src/cls/statelog/cls_statelog_client.h b/ceph/src/cls/statelog/cls_statelog_client.h index 7faf361e1..514c307be 100644 --- a/ceph/src/cls/statelog/cls_statelog_client.h +++ b/ceph/src/cls/statelog/cls_statelog_client.h @@ -1,9 +1,13 @@ #ifndef CEPH_CLS_STATELOG_CLIENT_H #define CEPH_CLS_STATELOG_CLIENT_H -#include "include/types.h" -#include "include/rados/librados.hpp" -#include "cls_statelog_types.h" +#include "cls_statelog_ops.h" + +namespace librados { + class ObjectWriteOperation; + class ObjectReadOperation; + class ObjectOperation; +} /* * log objclass diff --git a/ceph/src/cls/statelog/cls_statelog_ops.h b/ceph/src/cls/statelog/cls_statelog_ops.h index 2f21440f8..5a1622ea0 100644 --- a/ceph/src/cls/statelog/cls_statelog_ops.h +++ b/ceph/src/cls/statelog/cls_statelog_ops.h @@ -4,7 +4,6 @@ #ifndef CEPH_CLS_STATELOG_OPS_H #define CEPH_CLS_STATELOG_OPS_H -#include "include/types.h" #include "cls_statelog_types.h" struct cls_statelog_add_op { diff --git a/ceph/src/cls/timeindex/cls_timeindex.cc b/ceph/src/cls/timeindex/cls_timeindex.cc index dead05b68..202b65356 100644 --- a/ceph/src/cls/timeindex/cls_timeindex.cc +++ b/ceph/src/cls/timeindex/cls_timeindex.cc @@ -1,20 +1,12 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include - -#include -#include #include -#include "include/types.h" -#include "include/utime.h" #include "objclass/objclass.h" -#include "cls_timeindex_types.h" #include "cls_timeindex_ops.h" -#include "global/global_context.h" #include "include/compat.h" CLS_VER(1,0) diff --git a/ceph/src/cls/timeindex/cls_timeindex_client.cc b/ceph/src/cls/timeindex/cls_timeindex_client.cc index 3aa7adf02..502b9300e 100644 --- a/ceph/src/cls/timeindex/cls_timeindex_client.cc +++ b/ceph/src/cls/timeindex/cls_timeindex_client.cc @@ -3,10 +3,8 @@ #include -#include "include/types.h" #include "cls/timeindex/cls_timeindex_ops.h" #include "cls/timeindex/cls_timeindex_client.h" -#include "include/rados/librados.hpp" #include "include/compat.h" void cls_timeindex_add( diff --git a/ceph/src/cls/timeindex/cls_timeindex_client.h b/ceph/src/cls/timeindex/cls_timeindex_client.h index 71d71fea2..30efccdc8 100644 --- a/ceph/src/cls/timeindex/cls_timeindex_client.h +++ b/ceph/src/cls/timeindex/cls_timeindex_client.h @@ -4,10 +4,15 @@ #ifndef CEPH_CLS_TIMEINDEX_CLIENT_H #define CEPH_CLS_TIMEINDEX_CLIENT_H -#include "include/types.h" -#include "cls/timeindex/cls_timeindex_ops.h" #include "include/rados/librados.hpp" -#include "cls_timeindex_types.h" + +#include "cls_timeindex_ops.h" + +namespace librados { + class ObjectWriteOperation; + class ObjectReadOperation; + class IoCtx; +} /** * timeindex objclass diff --git a/ceph/src/cls/timeindex/cls_timeindex_ops.h b/ceph/src/cls/timeindex/cls_timeindex_ops.h index e5498f741..35c63b747 100644 --- a/ceph/src/cls/timeindex/cls_timeindex_ops.h +++ b/ceph/src/cls/timeindex/cls_timeindex_ops.h @@ -4,7 +4,6 @@ #ifndef CEPH_CLS_TIMEINDEX_OPS_H #define CEPH_CLS_TIMEINDEX_OPS_H -#include "include/types.h" #include "cls_timeindex_types.h" struct cls_timeindex_add_op { diff --git a/ceph/src/cls/user/cls_user.cc b/ceph/src/cls/user/cls_user.cc index 541525934..c616d1ae6 100644 --- a/ceph/src/cls/user/cls_user.cc +++ b/ceph/src/cls/user/cls_user.cc @@ -1,17 +1,11 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include - -#include -#include #include -#include "include/types.h" #include "include/utime.h" #include "objclass/objclass.h" -#include "cls_user_types.h" #include "cls_user_ops.h" CLS_VER(1,0) diff --git a/ceph/src/cls/user/cls_user_client.cc b/ceph/src/cls/user/cls_user_client.cc index 2625adda3..c77075dcb 100644 --- a/ceph/src/cls/user/cls_user_client.cc +++ b/ceph/src/cls/user/cls_user_client.cc @@ -3,8 +3,6 @@ #include -#include "include/types.h" -#include "cls/user/cls_user_ops.h" #include "cls/user/cls_user_client.h" #include "include/rados/librados.hpp" diff --git a/ceph/src/cls/user/cls_user_client.h b/ceph/src/cls/user/cls_user_client.h index 9465faa7c..5e5d3063d 100644 --- a/ceph/src/cls/user/cls_user_client.h +++ b/ceph/src/cls/user/cls_user_client.h @@ -4,11 +4,15 @@ #ifndef CEPH_CLS_USER_CLIENT_H #define CEPH_CLS_USER_CLIENT_H -#include "include/types.h" -#include "include/rados/librados.hpp" -#include "cls_user_types.h" +#include "cls_user_ops.h" #include "common/RefCountedObj.h" +namespace librados { + class ObjectWriteOperation; + class ObjectReadOperation; + class IoCtx; +} + class RGWGetUserHeader_CB : public RefCountedObject { public: ~RGWGetUserHeader_CB() override {} diff --git a/ceph/src/cls/user/cls_user_ops.cc b/ceph/src/cls/user/cls_user_ops.cc index 68fc84104..65d889bbc 100644 --- a/ceph/src/cls/user/cls_user_ops.cc +++ b/ceph/src/cls/user/cls_user_ops.cc @@ -1,7 +1,6 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "cls/user/cls_user_types.h" #include "cls/user/cls_user_ops.h" #include "common/Formatter.h" #include "common/ceph_json.h" diff --git a/ceph/src/cls/user/cls_user_ops.h b/ceph/src/cls/user/cls_user_ops.h index 0e90b22d1..2219a4959 100644 --- a/ceph/src/cls/user/cls_user_ops.h +++ b/ceph/src/cls/user/cls_user_ops.h @@ -4,9 +4,7 @@ #ifndef CEPH_CLS_USER_OPS_H #define CEPH_CLS_USER_OPS_H -#include "include/types.h" #include "cls_user_types.h" -#include "common/ceph_time.h" struct cls_user_set_buckets_op { list entries; diff --git a/ceph/src/cls/user/cls_user_types.cc b/ceph/src/cls/user/cls_user_types.cc index 34bcd9b5d..be3280ca2 100644 --- a/ceph/src/cls/user/cls_user_types.cc +++ b/ceph/src/cls/user/cls_user_types.cc @@ -4,6 +4,7 @@ #include "cls/user/cls_user_types.h" #include "common/Formatter.h" #include "common/ceph_json.h" +#include "include/utime.h" void cls_user_gen_test_bucket(cls_user_bucket *bucket, int i) { diff --git a/ceph/src/cls/version/cls_version.cc b/ceph/src/cls/version/cls_version.cc index 242acbc02..c68f8c4e1 100644 --- a/ceph/src/cls/version/cls_version.cc +++ b/ceph/src/cls/version/cls_version.cc @@ -1,20 +1,12 @@ // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include - -#include -#include #include -#include "include/types.h" -#include "include/utime.h" #include "objclass/objclass.h" -#include "cls/version/cls_version_types.h" + #include "cls/version/cls_version_ops.h" -#include "common/Clock.h" -#include "global/global_context.h" #include "include/compat.h" CLS_VER(1,0) diff --git a/ceph/src/cls/version/cls_version_client.cc b/ceph/src/cls/version/cls_version_client.cc index 4c463e3e3..36726d6cc 100644 --- a/ceph/src/cls/version/cls_version_client.cc +++ b/ceph/src/cls/version/cls_version_client.cc @@ -1,7 +1,6 @@ #include -#include "include/types.h" -#include "cls/version/cls_version_ops.h" +#include "cls/version/cls_version_client.h" #include "include/rados/librados.hpp" diff --git a/ceph/src/cls/version/cls_version_client.h b/ceph/src/cls/version/cls_version_client.h index d9e09415d..83a3d8c22 100644 --- a/ceph/src/cls/version/cls_version_client.h +++ b/ceph/src/cls/version/cls_version_client.h @@ -1,8 +1,14 @@ #ifndef CEPH_CLS_VERSION_CLIENT_H #define CEPH_CLS_VERSION_CLIENT_H -#include "include/types.h" -#include "include/rados/librados.hpp" +#include "cls_version_ops.h" + +namespace librados { + class ObjectWriteOperation; + class ObjectReadOperation; + class ObjectOperation; + class IoCtx; +} /* * version objclass diff --git a/ceph/src/cls/version/cls_version_ops.h b/ceph/src/cls/version/cls_version_ops.h index 86036bc79..6007e9ade 100644 --- a/ceph/src/cls/version/cls_version_ops.h +++ b/ceph/src/cls/version/cls_version_ops.h @@ -4,9 +4,6 @@ #ifndef CEPH_CLS_VERSION_OPS_H #define CEPH_CLS_VERSION_OPS_H -#include - -#include "include/types.h" #include "cls_version_types.h" struct cls_version_set_op { diff --git a/ceph/src/common/AsyncOpTracker.cc b/ceph/src/common/AsyncOpTracker.cc index 2219a7fd7..10a72d2b1 100644 --- a/ceph/src/common/AsyncOpTracker.cc +++ b/ceph/src/common/AsyncOpTracker.cc @@ -2,7 +2,6 @@ // vim: ts=8 sw=2 smarttab #include "common/AsyncOpTracker.h" -#include "include/assert.h" #include "include/Context.h" AsyncOpTracker::AsyncOpTracker() diff --git a/ceph/src/common/AsyncOpTracker.h b/ceph/src/common/AsyncOpTracker.h index fccc9f91d..f600cbd7f 100644 --- a/ceph/src/common/AsyncOpTracker.h +++ b/ceph/src/common/AsyncOpTracker.h @@ -4,7 +4,6 @@ #ifndef CEPH_ASYNC_OP_TRACKER_H #define CEPH_ASYNC_OP_TRACKER_H -#include "include/int_types.h" #include "common/Mutex.h" struct Context; diff --git a/ceph/src/common/AsyncReserver.h b/ceph/src/common/AsyncReserver.h index 467e25704..ae22b535d 100644 --- a/ceph/src/common/AsyncReserver.h +++ b/ceph/src/common/AsyncReserver.h @@ -15,11 +15,6 @@ #ifndef ASYNC_RESERVER_H #define ASYNC_RESERVER_H -#include -#include -#include - -#include "common/Mutex.h" #include "common/Finisher.h" #include "common/Formatter.h" diff --git a/ceph/src/common/BackTrace.cc b/ceph/src/common/BackTrace.cc index d68f43bd2..c179d1dac 100644 --- a/ceph/src/common/BackTrace.cc +++ b/ceph/src/common/BackTrace.cc @@ -1,11 +1,8 @@ - #include #include -#include #include #include "BackTrace.h" - #include "common/version.h" #define _STR(x) #x diff --git a/ceph/src/common/Checksummer.h b/ceph/src/common/Checksummer.h index 6611e8749..c303ae2dd 100644 --- a/ceph/src/common/Checksummer.h +++ b/ceph/src/common/Checksummer.h @@ -4,7 +4,6 @@ #ifndef CEPH_OS_BLUESTORE_CHECKSUMMER #define CEPH_OS_BLUESTORE_CHECKSUMMER -#include "include/buffer.h" #include "xxHash/xxhash.h" class Checksummer { diff --git a/ceph/src/common/Clock.cc b/ceph/src/common/Clock.cc index fc8fcb7c9..b4f074557 100644 --- a/ceph/src/common/Clock.cc +++ b/ceph/src/common/Clock.cc @@ -14,11 +14,6 @@ #include "common/Clock.h" -#include "common/ceph_context.h" -#include "common/config.h" -#include "include/utime.h" - -#include utime_t ceph_clock_now() { diff --git a/ceph/src/common/Cond.h b/ceph/src/common/Cond.h index 140227683..aa53b60f2 100644 --- a/ceph/src/common/Cond.h +++ b/ceph/src/common/Cond.h @@ -16,16 +16,8 @@ #ifndef CEPH_COND_H #define CEPH_COND_H -#include -#include - #include "include/Context.h" -#include "common/ceph_time.h" -#include "common/Mutex.h" -#include "common/Clock.h" - - class Cond { // my bits pthread_cond_t _c; diff --git a/ceph/src/common/ConfUtils.cc b/ceph/src/common/ConfUtils.cc index 135e7da17..db957760b 100644 --- a/ceph/src/common/ConfUtils.cc +++ b/ceph/src/common/ConfUtils.cc @@ -13,13 +13,8 @@ */ #include -#include #include #include -#include -#include -#include -#include #include #include @@ -28,7 +23,6 @@ #include "common/utf8.h" #include "common/ConfUtils.h" -using std::cerr; using std::ostringstream; using std::pair; using std::string; diff --git a/ceph/src/common/ContextCompletion.h b/ceph/src/common/ContextCompletion.h index a8b5b689f..37d82337e 100644 --- a/ceph/src/common/ContextCompletion.h +++ b/ceph/src/common/ContextCompletion.h @@ -3,7 +3,6 @@ #ifndef CEPH_ASYNC_COMPLETION_H #define CEPH_ASYNC_COMPLETION_H -#include "include/int_types.h" #include "include/Context.h" namespace ceph { diff --git a/ceph/src/common/Continuation.h b/ceph/src/common/Continuation.h index 394856973..aa3e1ed50 100644 --- a/ceph/src/common/Continuation.h +++ b/ceph/src/common/Continuation.h @@ -13,7 +13,6 @@ */ #include "include/Context.h" -#include /** * The Continuation interface is designed to help easily create multi-step diff --git a/ceph/src/common/Cycles.cc b/ceph/src/common/Cycles.cc index 656f08b40..b1888d34c 100644 --- a/ceph/src/common/Cycles.cc +++ b/ceph/src/common/Cycles.cc @@ -28,13 +28,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include - -#include "errno.h" #include "debug.h" -#include "Initialize.h" #include "Cycles.h" double Cycles::cycles_per_sec = 0; diff --git a/ceph/src/common/DecayCounter.h b/ceph/src/common/DecayCounter.h index 6a3ac4bca..e45aed8d2 100644 --- a/ceph/src/common/DecayCounter.h +++ b/ceph/src/common/DecayCounter.h @@ -17,8 +17,6 @@ #include "include/utime.h" -#include - /** * * TODO: normalize value based on some fucntion of half_life, diff --git a/ceph/src/common/EventTrace.cc b/ceph/src/common/EventTrace.cc index ab478158d..26d06bbef 100644 --- a/ceph/src/common/EventTrace.cc +++ b/ceph/src/common/EventTrace.cc @@ -16,12 +16,8 @@ */ #include "common/EventTrace.h" -#include "common/dout.h" #include "common/TracepointProvider.h" -#include "messages/MOSDOp.h" #include "messages/MOSDOpReply.h" -#include -#include #ifdef WITH_LTTNG #define TRACEPOINT_DEFINE diff --git a/ceph/src/common/EventTrace.h b/ceph/src/common/EventTrace.h index 91d4d5b12..7be1ffcd9 100644 --- a/ceph/src/common/EventTrace.h +++ b/ceph/src/common/EventTrace.h @@ -18,9 +18,7 @@ #ifndef _EventTrace_h_ #define _EventTrace_h_ -#include #include "msg/Message.h" -#include "common/ceph_context.h" #if defined(WITH_LTTNG) && defined(WITH_EVENTTRACE) diff --git a/ceph/src/common/Finisher.cc b/ceph/src/common/Finisher.cc index d7220d10c..5be9b04bb 100644 --- a/ceph/src/common/Finisher.cc +++ b/ceph/src/common/Finisher.cc @@ -1,10 +1,8 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "common/config.h" #include "Finisher.h" -#include "common/debug.h" #define dout_subsys ceph_subsys_finisher #undef dout_prefix #define dout_prefix *_dout << "finisher(" << this << ") " diff --git a/ceph/src/common/Finisher.h b/ceph/src/common/Finisher.h index 1629d915d..e1a4519c7 100644 --- a/ceph/src/common/Finisher.h +++ b/ceph/src/common/Finisher.h @@ -15,10 +15,8 @@ #ifndef CEPH_FINISHER_H #define CEPH_FINISHER_H -#include "include/atomic.h" #include "common/Mutex.h" #include "common/Cond.h" -#include "common/Thread.h" #include "common/perf_counters.h" class CephContext; diff --git a/ceph/src/common/Formatter.cc b/ceph/src/common/Formatter.cc index 00a9b3849..1a400aaa1 100644 --- a/ceph/src/common/Formatter.cc +++ b/ceph/src/common/Formatter.cc @@ -14,22 +14,13 @@ #define LARGE_SIZE 1024 -#include "assert.h" -#include "Formatter.h" #include "HTMLFormatter.h" #include "common/escape.h" #include "include/buffer.h" -#include -#include -#include -#include -#include -#include #include #include - // ----------------------- namespace ceph { diff --git a/ceph/src/common/Formatter.h b/ceph/src/common/Formatter.h index a23266ac4..aa695ba30 100644 --- a/ceph/src/common/Formatter.h +++ b/ceph/src/common/Formatter.h @@ -4,20 +4,15 @@ #define CEPH_FORMATTER_H #include "include/int_types.h" +#include "include/buffer_fwd.h" #include -#include #include #include #include -#include -#include #include -#include #include -#include "include/buffer_fwd.h" - namespace ceph { struct FormatterAttrs { diff --git a/ceph/src/common/Graylog.cc b/ceph/src/common/Graylog.cc index ff2935151..936605172 100644 --- a/ceph/src/common/Graylog.cc +++ b/ceph/src/common/Graylog.cc @@ -2,17 +2,10 @@ // vim: ts=8 sw=2 smarttab #include "Graylog.h" - -#include -#include - -#include - #include "common/Formatter.h" #include "common/LogEntry.h" #include "log/Entry.h" #include "log/SubsystemMap.h" -#include "include/uuid.h" namespace ceph { namespace logging { diff --git a/ceph/src/common/Graylog.h b/ceph/src/common/Graylog.h index 5452866ff..7e802a899 100644 --- a/ceph/src/common/Graylog.h +++ b/ceph/src/common/Graylog.h @@ -4,9 +4,6 @@ #ifndef __CEPH_LOG_GRAYLOG_H #define __CEPH_LOG_GRAYLOG_H - -#include - #include #include #include diff --git a/ceph/src/common/HTMLFormatter.cc b/ceph/src/common/HTMLFormatter.cc index 11004cc48..02ef744c4 100644 --- a/ceph/src/common/HTMLFormatter.cc +++ b/ceph/src/common/HTMLFormatter.cc @@ -14,8 +14,8 @@ #define LARGE_SIZE 1024 -#include "Formatter.h" #include "HTMLFormatter.h" +#include "Formatter.h" #include #include diff --git a/ceph/src/common/HTMLFormatter.h b/ceph/src/common/HTMLFormatter.h index 19d056f76..c59296922 100644 --- a/ceph/src/common/HTMLFormatter.h +++ b/ceph/src/common/HTMLFormatter.h @@ -3,10 +3,6 @@ #ifndef CEPH_HTML_FORMATTER_H #define CEPH_HTML_FORMATTER_H -#include -#include -#include - #include "Formatter.h" namespace ceph { diff --git a/ceph/src/common/HeartbeatMap.cc b/ceph/src/common/HeartbeatMap.cc index 9167ba679..ae1f8e8fa 100644 --- a/ceph/src/common/HeartbeatMap.cc +++ b/ceph/src/common/HeartbeatMap.cc @@ -12,20 +12,13 @@ * */ -#include -#include -#include -#include -#include -#include #include #include "HeartbeatMap.h" #include "ceph_context.h" #include "common/errno.h" -#include "common/valgrind.h" - #include "debug.h" + #define dout_subsys ceph_subsys_heartbeatmap #undef dout_prefix #define dout_prefix *_dout << "heartbeat_map " @@ -76,13 +69,13 @@ bool HeartbeatMap::_check(const heartbeat_handle_d *h, const char *who, time_t n bool healthy = true; time_t was; - was = h->timeout.read(); + was = h->timeout; if (was && was < now) { ldout(m_cct, 1) << who << " '" << h->name << "'" << " had timed out after " << h->grace << dendl; healthy = false; } - was = h->suicide_timeout.read(); + was = h->suicide_timeout; if (was && was < now) { ldout(m_cct, 1) << who << " '" << h->name << "'" << " had suicide timed out after " << h->suicide_grace << dendl; @@ -100,13 +93,13 @@ void HeartbeatMap::reset_timeout(heartbeat_handle_d *h, time_t grace, time_t sui time_t now = time(NULL); _check(h, "reset_timeout", now); - h->timeout.set(now + grace); + h->timeout = now + grace; h->grace = grace; if (suicide_grace) - h->suicide_timeout.set(now + suicide_grace); + h->suicide_timeout = now + suicide_grace; else - h->suicide_timeout.set(0); + h->suicide_timeout = 0; h->suicide_grace = suicide_grace; } @@ -115,8 +108,8 @@ void HeartbeatMap::clear_timeout(heartbeat_handle_d *h) ldout(m_cct, 20) << "clear_timeout '" << h->name << "'" << dendl; time_t now = time(NULL); _check(h, "clear_timeout", now); - h->timeout.set(0); - h->suicide_timeout.set(0); + h->timeout = 0; + h->suicide_timeout = 0; } bool HeartbeatMap::is_healthy() @@ -149,8 +142,8 @@ bool HeartbeatMap::is_healthy() } m_rwlock.put_read(); - m_unhealthy_workers.set(unhealthy); - m_total_workers.set(total); + m_unhealthy_workers = unhealthy; + m_total_workers = total; ldout(m_cct, 20) << "is_healthy = " << (healthy ? "healthy" : "NOT HEALTHY") << ", total workers: " << total << ", number of unhealthy: " << unhealthy << dendl; @@ -159,12 +152,12 @@ bool HeartbeatMap::is_healthy() int HeartbeatMap::get_unhealthy_workers() const { - return m_unhealthy_workers.read(); + return m_unhealthy_workers; } int HeartbeatMap::get_total_workers() const { - return m_total_workers.read(); + return m_total_workers; } void HeartbeatMap::check_touch_file() diff --git a/ceph/src/common/HeartbeatMap.h b/ceph/src/common/HeartbeatMap.h index 11efa9dd5..4e9b31466 100644 --- a/ceph/src/common/HeartbeatMap.h +++ b/ceph/src/common/HeartbeatMap.h @@ -15,13 +15,11 @@ #ifndef CEPH_HEARTBEATMAP_H #define CEPH_HEARTBEATMAP_H -#include - -#include #include -#include +#include +#include -#include "include/atomic.h" +#include #include "RWLock.h" @@ -43,7 +41,7 @@ namespace ceph { struct heartbeat_handle_d { const std::string name; pthread_t thread_id; - atomic_t timeout, suicide_timeout; + std::atomic timeout = { 0 }, suicide_timeout = { 0 }; time_t grace, suicide_grace; std::list::iterator list_item; @@ -83,8 +81,8 @@ class HeartbeatMap { RWLock m_rwlock; time_t m_inject_unhealthy_until; std::list m_workers; - atomic_t m_unhealthy_workers; - atomic_t m_total_workers; + std::atomic m_unhealthy_workers = { 0 }; + std::atomic m_total_workers = { 0 }; bool _check(const heartbeat_handle_d *h, const char *who, time_t now); }; diff --git a/ceph/src/common/LogClient.cc b/ceph/src/common/LogClient.cc index b99a8a246..07c53e80d 100644 --- a/ceph/src/common/LogClient.cc +++ b/ceph/src/common/LogClient.cc @@ -12,36 +12,18 @@ * */ - - -#include "include/types.h" +#include "common/LogClient.h" #include "include/str_map.h" -#include "include/uuid.h" - -#include "msg/Messenger.h" -#include "msg/Message.h" - #include "messages/MLog.h" #include "messages/MLogAck.h" #include "mon/MonMap.h" - -#include -#include -#include -#include +#include "common/Graylog.h" #ifdef DARWIN #include #include #endif // DARWIN -#include "common/Graylog.h" -// wipe the assert() introduced by boost headers included by Graylog.h -#include "include/assert.h" -#include "common/LogClient.h" - -#include "common/config.h" - #define dout_subsys ceph_subsys_monc int parse_log_client_options(CephContext *cct, @@ -241,6 +223,7 @@ void LogChannel::do_log(clog_type prio, const std::string& s) e.stamp = ceph_clock_now(); // seq and who should be set for syslog/graylog/log_to_mon e.who = parent->get_myinst(); + e.name = parent->get_myname(); e.seq = parent->get_next_seq(); e.prio = prio; e.msg = s; @@ -360,6 +343,11 @@ const entity_inst_t& LogClient::get_myinst() return messenger->get_myinst(); } +const EntityName& LogClient::get_myname() +{ + return cct->_conf->name; +} + bool LogClient::handle_log_ack(MLogAck *m) { Mutex::Locker l(log_lock); diff --git a/ceph/src/common/LogClient.h b/ceph/src/common/LogClient.h index 843b9bff0..56bb91ba9 100644 --- a/ceph/src/common/LogClient.h +++ b/ceph/src/common/LogClient.h @@ -15,13 +15,10 @@ #ifndef CEPH_LOGCLIENT_H #define CEPH_LOGCLIENT_H +#include #include "common/LogEntry.h" #include "common/Mutex.h" -#include -#include -#include - class LogClient; class MLog; class MLogAck; @@ -235,6 +232,7 @@ public: uint64_t get_next_seq(); const entity_inst_t& get_myinst(); + const EntityName& get_myname(); version_t queue(LogEntry &entry); private: diff --git a/ceph/src/common/LogEntry.cc b/ceph/src/common/LogEntry.cc index bc887e1b3..40bdbea2b 100644 --- a/ceph/src/common/LogEntry.cc +++ b/ceph/src/common/LogEntry.cc @@ -1,11 +1,8 @@ - #include - #include #include "LogEntry.h" #include "Formatter.h" - #include "include/stringify.h" // ---- @@ -23,6 +20,7 @@ void LogEntryKey::decode(bufferlist::iterator& bl) ::decode(who, bl); ::decode(stamp, bl); ::decode(seq, bl); + _calc_hash(); } void LogEntryKey::dump(Formatter *f) const @@ -184,7 +182,7 @@ void LogEntry::log_to_syslog(string level, string facility) void LogEntry::encode(bufferlist& bl, uint64_t features) const { - ENCODE_START(3, 2, bl); + ENCODE_START(4, 2, bl); __u16 t = prio; ::encode(who, bl, features); ::encode(stamp, bl); @@ -192,12 +190,13 @@ void LogEntry::encode(bufferlist& bl, uint64_t features) const ::encode(t, bl); ::encode(msg, bl); ::encode(channel, bl); + ::encode(name, bl); ENCODE_FINISH(bl); } void LogEntry::decode(bufferlist::iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl); + DECODE_START_LEGACY_COMPAT_LEN(4, 2, 2, bl); __u16 t; ::decode(who, bl); ::decode(stamp, bl); @@ -213,12 +212,16 @@ void LogEntry::decode(bufferlist::iterator& bl) // clue of what a 'channel' is. channel = CLOG_CHANNEL_CLUSTER; } + if (struct_v >= 4) { + ::decode(name, bl); + } DECODE_FINISH(bl); } void LogEntry::dump(Formatter *f) const { f->dump_stream("who") << who; + f->dump_stream("name") << name; f->dump_stream("stamp") << stamp; f->dump_unsigned("seq", seq); f->dump_string("channel", channel); @@ -248,6 +251,10 @@ void LogSummary::decode(bufferlist::iterator& bl) ::decode(version, bl); ::decode(tail, bl); DECODE_FINISH(bl); + keys.clear(); + for (auto& p : tail) { + keys.insert(p.key()); + } } void LogSummary::dump(Formatter *f) const diff --git a/ceph/src/common/LogEntry.h b/ceph/src/common/LogEntry.h index c3b9d2305..4feea3d41 100644 --- a/ceph/src/common/LogEntry.h +++ b/ceph/src/common/LogEntry.h @@ -15,10 +15,9 @@ #ifndef CEPH_LOGENTRY_H #define CEPH_LOGENTRY_H -#include "include/types.h" #include "include/utime.h" -#include "include/encoding.h" #include "msg/msg_types.h" // for entity_inst_t +#include "common/entity_name.h" namespace ceph { class Formatter; @@ -55,26 +54,51 @@ string clog_type_to_string(clog_type t); struct LogEntryKey { +private: + uint64_t _hash = 0; + + void _calc_hash() { + hash h; + _hash = seq + h(who); + } + entity_inst_t who; utime_t stamp; - uint64_t seq; + uint64_t seq = 0; - LogEntryKey() : seq(0) {} - LogEntryKey(const entity_inst_t& w, utime_t t, uint64_t s) : who(w), stamp(t), seq(s) {} +public: + LogEntryKey() {} + LogEntryKey(const entity_inst_t& w, utime_t t, uint64_t s) + : who(w), stamp(t), seq(s) { + _calc_hash(); + } + + uint64_t get_hash() const { + return _hash; + } void encode(bufferlist& bl, uint64_t features) const; void decode(bufferlist::iterator& bl); void dump(Formatter *f) const; static void generate_test_instances(list& o); + + friend bool operator==(const LogEntryKey& l, const LogEntryKey& r) { + return l.who == r.who && l.stamp == r.stamp && l.seq == r.seq; + } }; WRITE_CLASS_ENCODER_FEATURES(LogEntryKey) -static inline bool operator==(const LogEntryKey& l, const LogEntryKey& r) { - return l.who == r.who && l.stamp == r.stamp && l.seq == r.seq; -} +namespace std { + template<> struct hash { + size_t operator()(const LogEntryKey& r) const { + return r.get_hash(); + } + }; +} // namespace std struct LogEntry { entity_inst_t who; + EntityName name; utime_t stamp; uint64_t seq; clog_type prio; @@ -97,21 +121,22 @@ WRITE_CLASS_ENCODER_FEATURES(LogEntry) struct LogSummary { version_t version; list tail; + ceph::unordered_set keys; LogSummary() : version(0) {} void add(const LogEntry& e) { tail.push_back(e); - while (tail.size() > 50) + keys.insert(tail.back().key()); + } + void prune(size_t max) { + while (tail.size() > max) { + keys.erase(tail.front().key()); tail.pop_front(); + } } bool contains(const LogEntryKey& k) const { - for (list::const_iterator p = tail.begin(); - p != tail.end(); - ++p) - if (p->key() == k) - return true; - return false; + return keys.count(k); } void encode(bufferlist& bl, uint64_t features) const; @@ -121,7 +146,7 @@ struct LogSummary { }; WRITE_CLASS_ENCODER_FEATURES(LogSummary) -inline ostream& operator<<(ostream& out, clog_type t) +inline ostream& operator<<(ostream& out, const clog_type t) { switch (t) { case CLOG_DEBUG: @@ -141,7 +166,8 @@ inline ostream& operator<<(ostream& out, clog_type t) inline ostream& operator<<(ostream& out, const LogEntry& e) { - return out << e.stamp << " " << e.who << " " << e.seq << " : " + return out << e.stamp << " " << e.name << " " << e.who + << " " << e.seq << " : " << e.channel << " " << e.prio << " " << e.msg; } diff --git a/ceph/src/common/MemoryModel.cc b/ceph/src/common/MemoryModel.cc index fc14a0438..14d31cc9a 100644 --- a/ceph/src/common/MemoryModel.cc +++ b/ceph/src/common/MemoryModel.cc @@ -1,9 +1,5 @@ - -#include "acconfig.h" -#include "include/compat.h" -#include "include/types.h" #include "MemoryModel.h" -#include "common/config.h" +#include "include/compat.h" #include "debug.h" #if defined(__linux__) #include diff --git a/ceph/src/common/Mutex.cc b/ceph/src/common/Mutex.cc index c70724d2c..6ac022c8a 100644 --- a/ceph/src/common/Mutex.cc +++ b/ceph/src/common/Mutex.cc @@ -11,14 +11,10 @@ * Foundation. See file COPYING. * */ -#include #include "common/Mutex.h" #include "common/perf_counters.h" -#include "common/ceph_context.h" #include "common/config.h" -#include "include/stringify.h" -#include "include/utime.h" #include "common/Clock.h" #include "common/valgrind.h" diff --git a/ceph/src/common/OutputDataSocket.cc b/ceph/src/common/OutputDataSocket.cc index a1c368b40..f61c9c445 100644 --- a/ceph/src/common/OutputDataSocket.cc +++ b/ceph/src/common/OutputDataSocket.cc @@ -12,34 +12,17 @@ * */ -#include "include/int_types.h" - -#include "common/Thread.h" #include "common/OutputDataSocket.h" -#include "common/config.h" -#include "common/dout.h" #include "common/errno.h" -#include "common/perf_counters.h" #include "common/pipe.h" #include "common/safe_io.h" -#include "common/version.h" -#include "common/Formatter.h" +#include "include/compat.h" -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include "include/compat.h" +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" #define dout_subsys ceph_subsys_asok #undef dout_prefix diff --git a/ceph/src/common/OutputDataSocket.h b/ceph/src/common/OutputDataSocket.h index 44490679f..0bce1ded7 100644 --- a/ceph/src/common/OutputDataSocket.h +++ b/ceph/src/common/OutputDataSocket.h @@ -15,15 +15,8 @@ #ifndef CEPH_COMMON_OUTPUTDATASOCKET_H #define CEPH_COMMON_OUTPUTDATASOCKET_H -#include "common/Thread.h" -#include "common/Mutex.h" #include "common/Cond.h" -#include -#include -#include -#include "include/buffer.h" - class CephContext; class OutputDataSocket : public Thread diff --git a/ceph/src/common/PluginRegistry.cc b/ceph/src/common/PluginRegistry.cc index 07e73900c..cee379dbe 100644 --- a/ceph/src/common/PluginRegistry.cc +++ b/ceph/src/common/PluginRegistry.cc @@ -15,17 +15,13 @@ * */ -#include -#include - #include "PluginRegistry.h" #include "ceph_ver.h" -#include "common/ceph_context.h" #include "common/errno.h" -#include "include/str_list.h" - #include "common/debug.h" +#include + #define PLUGIN_PREFIX "libceph_" #define PLUGIN_SUFFIX ".so" #define PLUGIN_INIT_FUNCTION "__ceph_plugin_init" diff --git a/ceph/src/common/PluginRegistry.h b/ceph/src/common/PluginRegistry.h index 1b09570fa..c3655bb7d 100644 --- a/ceph/src/common/PluginRegistry.h +++ b/ceph/src/common/PluginRegistry.h @@ -18,9 +18,6 @@ #ifndef CEPH_COMMON_PLUGINREGISTRY_H #define CEPH_COMMON_PLUGINREGISTRY_H -#include -#include - #include "common/Mutex.h" class CephContext; diff --git a/ceph/src/common/PrebufferedStreambuf.h b/ceph/src/common/PrebufferedStreambuf.h index d56c9909f..b7fa21d68 100644 --- a/ceph/src/common/PrebufferedStreambuf.h +++ b/ceph/src/common/PrebufferedStreambuf.h @@ -1,7 +1,6 @@ #ifndef CEPH_COMMON_PREBUFFEREDSTREAMBUF_H #define CEPH_COMMON_PREBUFFEREDSTREAMBUF_H -#include #include /** diff --git a/ceph/src/common/Preforker.h b/ceph/src/common/Preforker.h index d3bbe4836..9fe34e5ea 100644 --- a/ceph/src/common/Preforker.h +++ b/ceph/src/common/Preforker.h @@ -3,15 +3,10 @@ #ifndef CEPH_COMMON_PREFORKER_H #define CEPH_COMMON_PREFORKER_H -#include "acconfig.h" -#include #include #include -#include -#include #include #include -#include #include "include/assert.h" #include "common/safe_io.h" diff --git a/ceph/src/common/PrioritizedQueue.h b/ceph/src/common/PrioritizedQueue.h index a1f23f1f8..8d9cd95b2 100644 --- a/ceph/src/common/PrioritizedQueue.h +++ b/ceph/src/common/PrioritizedQueue.h @@ -18,9 +18,6 @@ #include "common/Formatter.h" #include "common/OpQueue.h" -#include -#include - /** * Manages queue for normal and strict priority items * diff --git a/ceph/src/common/QueueRing.h b/ceph/src/common/QueueRing.h index 830f80f84..42582d24f 100644 --- a/ceph/src/common/QueueRing.h +++ b/ceph/src/common/QueueRing.h @@ -1,12 +1,12 @@ #ifndef QUEUE_RING_H #define QUEUE_RING_H -#include -#include #include "common/Mutex.h" #include "common/Cond.h" - +#include +#include +#include template class QueueRing { @@ -43,18 +43,20 @@ class QueueRing { std::vector buckets; int num_buckets; - atomic_t cur_read_bucket; - atomic_t cur_write_bucket; + + std::atomic cur_read_bucket = { 0 }; + std::atomic cur_write_bucket = { 0 }; + public: QueueRing(int n) : buckets(n), num_buckets(n) { } void enqueue(const T& entry) { - buckets[cur_write_bucket.inc() % num_buckets].enqueue(entry); + buckets[++cur_write_bucket % num_buckets].enqueue(entry); }; void dequeue(T *entry) { - buckets[cur_read_bucket.inc() % num_buckets].dequeue(entry); + buckets[++cur_read_bucket % num_buckets].dequeue(entry); } }; diff --git a/ceph/src/common/RWLock.h b/ceph/src/common/RWLock.h index befc5a53c..fd8a2665e 100644 --- a/ceph/src/common/RWLock.h +++ b/ceph/src/common/RWLock.h @@ -21,15 +21,16 @@ #include #include #include "lockdep.h" -#include "include/atomic.h" #include "common/valgrind.h" +#include + class RWLock final { mutable pthread_rwlock_t L; std::string name; mutable int id; - mutable atomic_t nrlock, nwlock; + mutable std::atomic nrlock = { 0 }, nwlock = { 0 }; bool track, lockdep; std::string unique_name(const char* name) const; @@ -39,7 +40,7 @@ public: const RWLock& operator=(const RWLock& other) = delete; RWLock(const std::string &n, bool track_lock=true, bool ld=true, bool prioritize_write=false) - : name(n), id(-1), nrlock(0), nwlock(0), track(track_lock), + : name(n), id(-1), track(track_lock), lockdep(ld) { #if defined(PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) if (prioritize_write) { @@ -65,12 +66,12 @@ public: bool is_locked() const { assert(track); - return (nrlock.read() > 0) || (nwlock.read() > 0); + return (nrlock > 0) || (nwlock > 0); } bool is_wlocked() const { assert(track); - return (nwlock.read() > 0); + return (nwlock > 0); } ~RWLock() { // The following check is racy but we are about to destroy @@ -85,11 +86,11 @@ public: void unlock(bool lockdep=true) const { if (track) { - if (nwlock.read() > 0) { - nwlock.dec(); + if (nwlock > 0) { + nwlock--; } else { - assert(nrlock.read() > 0); - nrlock.dec(); + assert(nrlock > 0); + nrlock--; } } if (lockdep && this->lockdep && g_lockdep) @@ -105,12 +106,12 @@ public: assert(r == 0); if (lockdep && g_lockdep) id = lockdep_locked(name.c_str(), id); if (track) - nrlock.inc(); + nrlock++; } bool try_get_read() const { if (pthread_rwlock_tryrdlock(&L) == 0) { if (track) - nrlock.inc(); + nrlock++; if (lockdep && g_lockdep) id = lockdep_locked(name.c_str(), id); return true; } @@ -129,7 +130,7 @@ public: if (lockdep && this->lockdep && g_lockdep) id = lockdep_locked(name.c_str(), id); if (track) - nwlock.inc(); + nwlock++; } bool try_get_write(bool lockdep=true) { @@ -137,7 +138,7 @@ public: if (lockdep && this->lockdep && g_lockdep) id = lockdep_locked(name.c_str(), id); if (track) - nwlock.inc(); + nwlock++; return true; } return false; diff --git a/ceph/src/common/RefCountedObj.h b/ceph/src/common/RefCountedObj.h index 6099bfff7..9c0dad1d3 100644 --- a/ceph/src/common/RefCountedObj.h +++ b/ceph/src/common/RefCountedObj.h @@ -17,27 +17,24 @@ #include "common/Mutex.h" #include "common/Cond.h" -#include "include/atomic.h" #include "common/ceph_context.h" #include "common/valgrind.h" -#include - // re-include our assert to clobber the system one; fix dout: #include "include/assert.h" struct RefCountedObject { private: - mutable atomic_t nref; + mutable std::atomic nref; CephContext *cct; public: RefCountedObject(CephContext *c = NULL, int n=1) : nref(n), cct(c) {} virtual ~RefCountedObject() { - assert(nref.read() == 0); + assert(nref == 0); } const RefCountedObject *get() const { - int v = nref.inc(); + int v = ++nref; if (cct) lsubdout(cct, refs, 1) << "RefCountedObject::get " << this << " " << (v - 1) << " -> " << v @@ -45,7 +42,7 @@ public: return this; } RefCountedObject *get() { - int v = nref.inc(); + int v = ++nref; if (cct) lsubdout(cct, refs, 1) << "RefCountedObject::get " << this << " " << (v - 1) << " -> " << v @@ -54,7 +51,7 @@ public: } void put() const { CephContext *local_cct = cct; - int v = nref.dec(); + int v = --nref; if (v == 0) { ANNOTATE_HAPPENS_AFTER(&nref); ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref); @@ -72,7 +69,7 @@ public: } uint64_t get_nref() const { - return nref.read(); + return nref; } }; @@ -122,10 +119,10 @@ struct RefCountedCond : public RefCountedObject { * */ struct RefCountedWaitObject { - atomic_t nref; + std::atomic nref = { 1 }; RefCountedCond *c; - RefCountedWaitObject() : nref(1) { + RefCountedWaitObject() { c = new RefCountedCond; } virtual ~RefCountedWaitObject() { @@ -133,7 +130,7 @@ struct RefCountedWaitObject { } RefCountedWaitObject *get() { - nref.inc(); + nref++; return this; } @@ -141,7 +138,7 @@ struct RefCountedWaitObject { bool ret = false; RefCountedCond *cond = c; cond->get(); - if (nref.dec() == 0) { + if (--nref == 0) { cond->done(); delete this; ret = true; @@ -154,7 +151,7 @@ struct RefCountedWaitObject { RefCountedCond *cond = c; cond->get(); - if (nref.dec() == 0) { + if (--nref == 0) { cond->done(); delete this; } else { diff --git a/ceph/src/common/SloppyCRCMap.h b/ceph/src/common/SloppyCRCMap.h index 78c470c18..d8d156112 100644 --- a/ceph/src/common/SloppyCRCMap.h +++ b/ceph/src/common/SloppyCRCMap.h @@ -7,10 +7,6 @@ #include "include/encoding.h" #include "common/Formatter.h" -#include -#include -#include - /** * SloppyCRCMap * diff --git a/ceph/src/common/SubProcess.h b/ceph/src/common/SubProcess.h index 2295aade4..ce9559c5e 100644 --- a/ceph/src/common/SubProcess.h +++ b/ceph/src/common/SubProcess.h @@ -17,23 +17,17 @@ #ifndef SUB_PROCESS_H #define SUB_PROCESS_H -#include #include - -#include -#include #include -#include -#include -#include -#include - #include #include #include - #include #include +#if defined(__FreeBSD__) +#include +#include +#endif /** * SubProcess: diff --git a/ceph/src/common/TextTable.h b/ceph/src/common/TextTable.h index 60c982a7e..12e8ca1f5 100644 --- a/ceph/src/common/TextTable.h +++ b/ceph/src/common/TextTable.h @@ -17,8 +17,6 @@ #include #include -#include -#include #include "include/assert.h" /** diff --git a/ceph/src/common/Thread.cc b/ceph/src/common/Thread.cc index 3e8d34346..a58c7ba25 100644 --- a/ceph/src/common/Thread.cc +++ b/ceph/src/common/Thread.cc @@ -19,16 +19,6 @@ #include "common/signal.h" #include "common/io_priority.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include #ifdef HAVE_SCHED #include #endif diff --git a/ceph/src/common/Throttle.cc b/ceph/src/common/Throttle.cc index 56579ca8d..7ddf4883b 100644 --- a/ceph/src/common/Throttle.cc +++ b/ceph/src/common/Throttle.cc @@ -1,14 +1,12 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include -#include - #include "common/Throttle.h" -#include "common/dout.h" -#include "common/ceph_context.h" #include "common/perf_counters.h" +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" + #define dout_subsys ceph_subsys_throttle #undef dout_prefix @@ -59,7 +57,7 @@ Throttle::Throttle(CephContext *cct, const std::string& n, int64_t m, bool _use_ logger = b.create_perf_counters(); cct->get_perfcounters_collection()->add(logger); - logger->set(l_throttle_max, max.read()); + logger->set(l_throttle_max, max); } } @@ -83,13 +81,13 @@ Throttle::~Throttle() void Throttle::_reset_max(int64_t m) { assert(lock.is_locked()); - if ((int64_t)max.read() == m) + if (static_cast(max) == m) return; if (!cond.empty()) cond.front()->SignalOne(); if (logger) logger->set(l_throttle_max, m); - max.set((size_t)m); + max = m; } bool Throttle::_wait(int64_t c) @@ -126,7 +124,7 @@ bool Throttle::_wait(int64_t c) bool Throttle::wait(int64_t m) { - if (0 == max.read() && 0 == m) { + if (0 == max && 0 == m) { return false; } @@ -141,31 +139,31 @@ bool Throttle::wait(int64_t m) int64_t Throttle::take(int64_t c) { - if (0 == max.read()) { + if (0 == max) { return 0; } assert(c >= 0); ldout(cct, 10) << "take " << c << dendl; { Mutex::Locker l(lock); - count.add(c); + count += c; } if (logger) { logger->inc(l_throttle_take); logger->inc(l_throttle_take_sum, c); - logger->set(l_throttle_val, count.read()); + logger->set(l_throttle_val, count); } - return count.read(); + return count; } bool Throttle::get(int64_t c, int64_t m) { - if (0 == max.read() && 0 == m) { + if (0 == max && 0 == m) { return false; } assert(c >= 0); - ldout(cct, 10) << "get " << c << " (" << count.read() << " -> " << (count.read() + c) << ")" << dendl; + ldout(cct, 10) << "get " << c << " (" << count.load() << " -> " << (count.load() + c) << ")" << dendl; if (logger) { logger->inc(l_throttle_get_started); } @@ -177,12 +175,12 @@ bool Throttle::get(int64_t c, int64_t m) _reset_max(m); } waited = _wait(c); - count.add(c); + count += c; } if (logger) { logger->inc(l_throttle_get); logger->inc(l_throttle_get_sum, c); - logger->set(l_throttle_val, count.read()); + logger->set(l_throttle_val, count); } return waited; } @@ -192,7 +190,7 @@ bool Throttle::get(int64_t c, int64_t m) */ bool Throttle::get_or_fail(int64_t c) { - if (0 == max.read()) { + if (0 == max) { return true; } @@ -205,13 +203,13 @@ bool Throttle::get_or_fail(int64_t c) } return false; } else { - ldout(cct, 10) << "get_or_fail " << c << " success (" << count.read() << " -> " << (count.read() + c) << ")" << dendl; - count.add(c); + ldout(cct, 10) << "get_or_fail " << c << " success (" << count.load() << " -> " << (count.load() + c) << ")" << dendl; + count += c; if (logger) { logger->inc(l_throttle_get_or_fail_success); logger->inc(l_throttle_get); logger->inc(l_throttle_get_sum, c); - logger->set(l_throttle_val, count.read()); + logger->set(l_throttle_val, count); } return true; } @@ -219,25 +217,25 @@ bool Throttle::get_or_fail(int64_t c) int64_t Throttle::put(int64_t c) { - if (0 == max.read()) { + if (0 == max) { return 0; } assert(c >= 0); - ldout(cct, 10) << "put " << c << " (" << count.read() << " -> " << (count.read()-c) << ")" << dendl; + ldout(cct, 10) << "put " << c << " (" << count.load() << " -> " << (count.load()-c) << ")" << dendl; Mutex::Locker l(lock); if (c) { if (!cond.empty()) cond.front()->SignalOne(); - assert(((int64_t)count.read()) >= c); //if count goes negative, we failed somewhere! - count.sub(c); + assert(static_cast(count) >= c); // if count goes negative, we failed somewhere! + count -= c; if (logger) { logger->inc(l_throttle_put); logger->inc(l_throttle_put_sum, c); - logger->set(l_throttle_val, count.read()); + logger->set(l_throttle_val, count); } } - return count.read(); + return count; } void Throttle::reset() @@ -245,7 +243,7 @@ void Throttle::reset() Mutex::Locker l(lock); if (!cond.empty()) cond.front()->SignalOne(); - count.set(0); + count = 0; if (logger) { logger->set(l_throttle_val, 0); } diff --git a/ceph/src/common/Throttle.h b/ceph/src/common/Throttle.h index e4119a3b9..9f166cd48 100644 --- a/ceph/src/common/Throttle.h +++ b/ceph/src/common/Throttle.h @@ -4,14 +4,14 @@ #ifndef CEPH_THROTTLE_H #define CEPH_THROTTLE_H -#include "Mutex.h" -#include "Cond.h" -#include #include +#include +#include +#include #include #include -#include -#include "include/atomic.h" + +#include "Cond.h" #include "include/Context.h" class CephContext; @@ -29,7 +29,7 @@ class Throttle { CephContext *cct; const std::string name; PerfCounters *logger; - ceph::atomic_t count, max; + std::atomic count = { 0 }, max = { 0 }; Mutex lock; list cond; const bool use_perf; @@ -41,8 +41,8 @@ public: private: void _reset_max(int64_t m); bool _should_wait(int64_t c) const { - int64_t m = max.read(); - int64_t cur = count.read(); + int64_t m = max; + int64_t cur = count; return m && ((c <= m && cur + c > m) || // normally stay under max @@ -57,20 +57,20 @@ public: * @returns the number of taken slots */ int64_t get_current() const { - return count.read(); + return count; } /** * get the max number of slots * @returns the max number of slots */ - int64_t get_max() const { return max.read(); } + int64_t get_max() const { return max; } /** * return true if past midpoint */ bool past_midpoint() const { - return count.read() >= max.read() / 2; + return count >= max / 2; } /** diff --git a/ceph/src/common/Timer.cc b/ceph/src/common/Timer.cc index fb7a1bfbc..ef76a9e41 100644 --- a/ceph/src/common/Timer.cc +++ b/ceph/src/common/Timer.cc @@ -13,21 +13,13 @@ */ #include "Cond.h" -#include "Mutex.h" -#include "Thread.h" #include "Timer.h" -#include "common/config.h" -#include "include/Context.h" #define dout_subsys ceph_subsys_timer #undef dout_prefix #define dout_prefix *_dout << "timer(" << this << ")." -#include -#include -#include -#include class SafeTimerThread : public Thread { diff --git a/ceph/src/common/Timer.h b/ceph/src/common/Timer.h index 6ac916d9e..078a172b2 100644 --- a/ceph/src/common/Timer.h +++ b/ceph/src/common/Timer.h @@ -17,9 +17,6 @@ #include "Cond.h" #include "Mutex.h" -#include "RWLock.h" - -#include class CephContext; class Context; diff --git a/ceph/src/common/TracepointProvider.h b/ceph/src/common/TracepointProvider.h index 9efc482c6..97d3a0f76 100644 --- a/ceph/src/common/TracepointProvider.h +++ b/ceph/src/common/TracepointProvider.h @@ -4,14 +4,9 @@ #ifndef CEPH_TRACEPOINT_PROVIDER_H #define CEPH_TRACEPOINT_PROVIDER_H -#include "include/int_types.h" -#include "common/ceph_context.h" #include "common/config_obs.h" #include "common/Mutex.h" #include -#include -#include -#include struct md_config_t; diff --git a/ceph/src/common/TrackedOp.cc b/ceph/src/common/TrackedOp.cc index 58df25326..ecaa196af 100644 --- a/ceph/src/common/TrackedOp.cc +++ b/ceph/src/common/TrackedOp.cc @@ -11,13 +11,6 @@ */ #include "TrackedOp.h" -#include "common/Formatter.h" -#include -#include -#include "common/debug.h" -#include "common/config.h" -#include "msg/Message.h" -#include "include/assert.h" #define dout_context cct #define dout_subsys ceph_subsys_optracker @@ -246,7 +239,7 @@ bool OpTracker::register_inflight_op(TrackedOp *i) if (!tracking_enabled) return false; - uint64_t current_seq = seq.inc(); + uint64_t current_seq = ++seq; uint32_t shard_index = current_seq % num_optracker_shards; ShardedTrackingData* sdata = sharded_in_flight_list[shard_index]; assert(NULL != sdata); diff --git a/ceph/src/common/TrackedOp.h b/ceph/src/common/TrackedOp.h index 899e0b6fe..1ee81075d 100644 --- a/ceph/src/common/TrackedOp.h +++ b/ceph/src/common/TrackedOp.h @@ -13,17 +13,10 @@ #ifndef TRACKEDREQUEST_H_ #define TRACKEDREQUEST_H_ -#include -#include -#include -#include -#include "include/utime.h" -#include "common/Mutex.h" +#include #include "common/histogram.h" -#include "common/zipkin_trace.h" #include "msg/Message.h" -#include "include/memory.h" #include "common/RWLock.h" #define OPTRACKER_PREALLOC_EVENTS 20 @@ -70,7 +63,7 @@ public: struct ShardedTrackingData; class OpTracker { friend class OpHistory; - atomic64_t seq; + std::atomic seq = { 0 }; vector sharded_in_flight_list; uint32_t num_optracker_shards; OpHistory history; diff --git a/ceph/src/common/WorkQueue.cc b/ceph/src/common/WorkQueue.cc index ec5f8a147..1d2672312 100644 --- a/ceph/src/common/WorkQueue.cc +++ b/ceph/src/common/WorkQueue.cc @@ -12,17 +12,9 @@ * */ +#include "WorkQueue.h" #include "include/compat.h" - -#include - -#include "include/types.h" -#include "include/utime.h" #include "common/errno.h" -#include "WorkQueue.h" - -#include "common/config.h" -#include "common/HeartbeatMap.h" #define dout_subsys ceph_subsys_tp #undef dout_prefix @@ -296,9 +288,6 @@ ShardedThreadPool::ShardedThreadPool(CephContext *pcct_, string nm, string tn, lockname(name + "::lock"), shardedpool_lock(lockname.c_str()), num_threads(pnum_threads), - stop_threads(0), - pause_threads(0), - drain_threads(0), num_paused(0), num_drained(0), wq(NULL) {} @@ -314,28 +303,28 @@ void ShardedThreadPool::shardedthreadpool_worker(uint32_t thread_index) ss << name << " thread " << name; heartbeat_handle_d *hb = cct->get_heartbeat_map()->add_worker(ss.str(), pthread_self()); - while (!stop_threads.read()) { - if(pause_threads.read()) { + while (!stop_threads) { + if (pause_threads) { shardedpool_lock.Lock(); ++num_paused; wait_cond.Signal(); - while(pause_threads.read()) { + while (pause_threads) { cct->get_heartbeat_map()->reset_timeout( - hb, - wq->timeout_interval, wq->suicide_interval); + hb, + wq->timeout_interval, wq->suicide_interval); shardedpool_cond.WaitInterval(shardedpool_lock, - utime_t( + utime_t( cct->_conf->threadpool_empty_queue_max_wait, 0)); } --num_paused; shardedpool_lock.Unlock(); } - if (drain_threads.read()) { + if (drain_threads) { shardedpool_lock.Lock(); if (wq->is_shard_empty(thread_index)) { ++num_drained; wait_cond.Signal(); - while (drain_threads.read()) { + while (drain_threads) { cct->get_heartbeat_map()->reset_timeout( hb, wq->timeout_interval, wq->suicide_interval); @@ -388,7 +377,7 @@ void ShardedThreadPool::start() void ShardedThreadPool::stop() { ldout(cct,10) << "stop" << dendl; - stop_threads.set(1); + stop_threads = true; assert(wq != NULL); wq->return_waiting_threads(); for (vector::iterator p = threads_shardedpool.begin(); @@ -405,7 +394,7 @@ void ShardedThreadPool::pause() { ldout(cct,10) << "pause" << dendl; shardedpool_lock.Lock(); - pause_threads.set(1); + pause_threads = true; assert(wq != NULL); wq->return_waiting_threads(); while (num_threads != num_paused){ @@ -419,7 +408,7 @@ void ShardedThreadPool::pause_new() { ldout(cct,10) << "pause_new" << dendl; shardedpool_lock.Lock(); - pause_threads.set(1); + pause_threads = true; assert(wq != NULL); wq->return_waiting_threads(); shardedpool_lock.Unlock(); @@ -430,7 +419,7 @@ void ShardedThreadPool::unpause() { ldout(cct,10) << "unpause" << dendl; shardedpool_lock.Lock(); - pause_threads.set(0); + pause_threads = false; shardedpool_cond.Signal(); shardedpool_lock.Unlock(); ldout(cct,10) << "unpaused" << dendl; @@ -440,13 +429,13 @@ void ShardedThreadPool::drain() { ldout(cct,10) << "drain" << dendl; shardedpool_lock.Lock(); - drain_threads.set(1); + drain_threads = true; assert(wq != NULL); wq->return_waiting_threads(); while (num_threads != num_drained) { wait_cond.Wait(shardedpool_lock); } - drain_threads.set(0); + drain_threads = false; shardedpool_cond.Signal(); shardedpool_lock.Unlock(); ldout(cct,10) << "drained" << dendl; diff --git a/ceph/src/common/WorkQueue.h b/ceph/src/common/WorkQueue.h index 6e29da6fd..c817e74ec 100644 --- a/ceph/src/common/WorkQueue.h +++ b/ceph/src/common/WorkQueue.h @@ -15,13 +15,12 @@ #ifndef CEPH_WORKQUEUE_H #define CEPH_WORKQUEUE_H -#include "Mutex.h" #include "Cond.h" -#include "Thread.h" #include "include/unordered_map.h" -#include "common/config_obs.h" #include "common/HeartbeatMap.h" +#include + class CephContext; /// Pool of threads that share work submitted to multiple work queues. @@ -623,9 +622,11 @@ class ShardedThreadPool { Cond shardedpool_cond; Cond wait_cond; uint32_t num_threads; - atomic_t stop_threads; - atomic_t pause_threads; - atomic_t drain_threads; + + std::atomic stop_threads = { false }; + std::atomic pause_threads = { false }; + std::atomic drain_threads = { false }; + uint32_t num_paused; uint32_t num_drained; diff --git a/ceph/src/common/addr_parsing.c b/ceph/src/common/addr_parsing.c index ae7555765..506944029 100644 --- a/ceph/src/common/addr_parsing.c +++ b/ceph/src/common/addr_parsing.c @@ -12,7 +12,6 @@ * */ -#include #include #include #include diff --git a/ceph/src/common/address_helper.cc b/ceph/src/common/address_helper.cc index 9e46b4a99..8f625f8db 100644 --- a/ceph/src/common/address_helper.cc +++ b/ceph/src/common/address_helper.cc @@ -5,21 +5,12 @@ * Author: matt */ -#include -#include #include -#include -#include - -using namespace std; - -#include "common/config.h" -#include "boost/regex.hpp" - #include "common/address_helper.h" +#include "boost/regex.hpp" -#include +using namespace std; // decode strings like "tcp://:" int entity_addr_from_url(entity_addr_t *addr /* out */, const char *url) diff --git a/ceph/src/common/admin_socket.cc b/ceph/src/common/admin_socket.cc index 711d2040b..2bb767edc 100644 --- a/ceph/src/common/admin_socket.cc +++ b/ceph/src/common/admin_socket.cc @@ -12,36 +12,19 @@ * */ -#include "include/int_types.h" - -#include "common/Thread.h" #include "common/admin_socket.h" #include "common/admin_socket_client.h" -#include "common/config.h" -#include "common/cmdparse.h" -#include "common/dout.h" #include "common/errno.h" -#include "common/perf_counters.h" #include "common/pipe.h" #include "common/safe_io.h" #include "common/version.h" -#include "common/Formatter.h" +#include "include/compat.h" -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include "include/compat.h" +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" #define dout_subsys ceph_subsys_asok #undef dout_prefix @@ -509,10 +492,13 @@ public: } else { JSONFormatter jf; jf.open_object_section("version"); - if (command == "version") + if (command == "version") { jf.dump_string("version", ceph_version_to_str()); - else if (command == "git_version") + jf.dump_string("release", ceph_release_name(ceph_release())); + jf.dump_string("release_type", ceph_release_type()); + } else if (command == "git_version") { jf.dump_string("git_version", git_version_to_str()); + } ostringstream ss; jf.close_section(); jf.flush(ss); diff --git a/ceph/src/common/admin_socket.h b/ceph/src/common/admin_socket.h index 44b8a52be..e526ba37c 100644 --- a/ceph/src/common/admin_socket.h +++ b/ceph/src/common/admin_socket.h @@ -15,13 +15,6 @@ #ifndef CEPH_COMMON_ADMIN_SOCKET_H #define CEPH_COMMON_ADMIN_SOCKET_H -#include "common/Thread.h" -#include "common/Mutex.h" - -#include -#include -#include "include/buffer_fwd.h" -#include "common/cmdparse.h" #include "common/Cond.h" class AdminSocket; diff --git a/ceph/src/common/admin_socket_client.cc b/ceph/src/common/admin_socket_client.cc index 31346b98c..32eb66479 100644 --- a/ceph/src/common/admin_socket_client.cc +++ b/ceph/src/common/admin_socket_client.cc @@ -12,31 +12,12 @@ * */ -#include "include/int_types.h" - #include "common/admin_socket.h" -#include "common/ceph_context.h" #include "common/errno.h" #include "common/safe_io.h" #include "common/admin_socket_client.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include using std::ostringstream; diff --git a/ceph/src/common/admin_socket_client.h b/ceph/src/common/admin_socket_client.h index b46ed24ff..dcfab2b8b 100644 --- a/ceph/src/common/admin_socket_client.h +++ b/ceph/src/common/admin_socket_client.h @@ -15,7 +15,6 @@ #ifndef CEPH_COMMON_ADMIN_SOCKET_CLIENT_H #define CEPH_COMMON_ADMIN_SOCKET_CLIENT_H -#include #include /* This is a simple client that talks to an AdminSocket using blocking I/O. diff --git a/ceph/src/common/aix_errno.cc b/ceph/src/common/aix_errno.cc index 48ef72826..07f6a1452 100644 --- a/ceph/src/common/aix_errno.cc +++ b/ceph/src/common/aix_errno.cc @@ -17,7 +17,7 @@ // converts from linux errno values to host values -__s32 ceph_to_host_errno(__s32 r) +__s32 ceph_to_hostos_errno(__s32 r) { if (r < -34) { switch (r) { @@ -222,4 +222,10 @@ __s32 ceph_to_host_errno(__s32 r) return r; // otherwise return original value } +// converts Host OS errno values to linux/Ceph values +// XXX Currently not worked out +__s32 hostos_to_ceph_errno(__s32 r) +{ + return r; +} diff --git a/ceph/src/common/assert.cc b/ceph/src/common/assert.cc index d4dd048c2..7f8bb5814 100644 --- a/ceph/src/common/assert.cc +++ b/ceph/src/common/assert.cc @@ -12,18 +12,7 @@ * */ -#include "BackTrace.h" -#include "common/ceph_context.h" -#include "common/config.h" #include "common/debug.h" -#include "common/Clock.h" -#include "include/assert.h" - -#include -#include -#include -#include -#include namespace ceph { static CephContext *g_assert_context = NULL; diff --git a/ceph/src/common/backport14.h b/ceph/src/common/backport14.h new file mode 100644 index 000000000..d56e24c3e --- /dev/null +++ b/ceph/src/common/backport14.h @@ -0,0 +1,84 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include +#include + +#ifndef CEPH_COMMON_BACKPORT14_H +#define CEPH_COMMON_BACKPORT14_H + +// Library code from C++14 that can be implemented in C++11. + +namespace ceph { +template +using remove_extent_t = typename std::remove_extent::type; +template +using remove_reference_t = typename std::remove_reference::type; +template +using result_of_t = typename std::result_of::type; + +namespace _backport14 { +template +struct uniquity { + using datum = std::unique_ptr; +}; + +template +struct uniquity { + using array = std::unique_ptr; +}; + +template +struct uniquity { + using verboten = void; +}; + +template +inline typename uniquity::datum make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +template +inline typename uniquity::array make_unique(std::size_t n) { + return std::unique_ptr(new remove_extent_t[n]()); +} + +template +typename uniquity::verboten +make_unique(Args&&...) = delete; + +// The constexpr variant of std::max(). +template +constexpr const T& max(const T& a, const T& b) { + return a < b ? b : a; +} +} // namespace _backport14 + +namespace _backport17 { +template +constexpr auto size(const C& c) -> decltype(c.size()) { + return c.size(); +} + +template +constexpr std::size_t size(const T (&array)[N]) noexcept { + return N; +} +} // namespace _backport17 +using _backport14::make_unique; +using _backport17::size; +using _backport14::max; +} // namespace ceph + +#endif // CEPH_COMMON_BACKPORT14_H diff --git a/ceph/src/common/bit_str.cc b/ceph/src/common/bit_str.cc index b3d1d0148..1f9ec3bc4 100644 --- a/ceph/src/common/bit_str.cc +++ b/ceph/src/common/bit_str.cc @@ -14,7 +14,6 @@ #include "common/bit_str.h" #include "common/Formatter.h" #include "include/assert.h" -#include "common/debug.h" static void _dump_bit_str( uint64_t bits, diff --git a/ceph/src/common/bit_str.h b/ceph/src/common/bit_str.h index 9f0cb7f6a..02c7db951 100644 --- a/ceph/src/common/bit_str.h +++ b/ceph/src/common/bit_str.h @@ -14,9 +14,7 @@ #ifndef CEPH_COMMON_BIT_STR_H #define CEPH_COMMON_BIT_STR_H -#include #include -#include namespace ceph { class Formatter; diff --git a/ceph/src/common/bit_vector.hpp b/ceph/src/common/bit_vector.hpp index c15b0927e..6a6e6b7d0 100644 --- a/ceph/src/common/bit_vector.hpp +++ b/ceph/src/common/bit_vector.hpp @@ -13,13 +13,7 @@ #include "common/Formatter.h" #include "include/assert.h" -#include "include/buffer.h" #include "include/encoding.h" -#include -#include -#include -#include -#include namespace ceph { diff --git a/ceph/src/common/blkdev.cc b/ceph/src/common/blkdev.cc index 11bd95410..d95a397a8 100644 --- a/ceph/src/common/blkdev.cc +++ b/ceph/src/common/blkdev.cc @@ -9,15 +9,11 @@ * Foundation. See file COPYING. * */ + #include -#include #include #include -#include -#include -#include #include -#include #include "include/uuid.h" #ifdef __linux__ @@ -336,7 +332,7 @@ int get_device_by_uuid(uuid_d dev_uuid, const char* label, char* partition, { return -EOPNOTSUPP; } -int get_device_by_fd(int fd, char* partition, char* device) +int get_device_by_fd(int fd, char *partition, char *device, size_t max) { return -EOPNOTSUPP; } @@ -367,7 +363,7 @@ int get_device_by_uuid(uuid_d dev_uuid, const char* label, char* partition, return -EOPNOTSUPP; } -int get_device_by_fd(int fd, char* partition, char* device) +int get_device_by_fd(int fd, char *partition, char *device, size_t max) { return -EOPNOTSUPP; } diff --git a/ceph/src/common/bloom_filter.cc b/ceph/src/common/bloom_filter.cc index 6bc54bc77..95516e6fd 100644 --- a/ceph/src/common/bloom_filter.cc +++ b/ceph/src/common/bloom_filter.cc @@ -2,8 +2,6 @@ // vim: ts=8 sw=2 smarttab #include "common/bloom_filter.hpp" -#include "common/Formatter.h" -#include "include/buffer.h" MEMPOOL_DEFINE_FACTORY(unsigned char, byte, bloom_filter); diff --git a/ceph/src/common/bloom_filter.hpp b/ceph/src/common/bloom_filter.hpp index 9007f111c..a76109fc6 100644 --- a/ceph/src/common/bloom_filter.hpp +++ b/ceph/src/common/bloom_filter.hpp @@ -22,13 +22,7 @@ #ifndef COMMON_BLOOM_FILTER_HPP #define COMMON_BLOOM_FILTER_HPP -#include -#include #include -#include -#include -#include -#include #include "include/mempool.h" #include "include/encoding.h" diff --git a/ceph/src/common/buffer.cc b/ceph/src/common/buffer.cc index bf4b0af25..44ce5b016 100644 --- a/ceph/src/common/buffer.cc +++ b/ceph/src/common/buffer.cc @@ -12,6 +12,12 @@ * */ +#include +#include +#include + +#include + #include "include/compat.h" #include "include/mempool.h" #include "armor.h" @@ -23,24 +29,15 @@ #include "common/likely.h" #include "common/valgrind.h" #include "common/deleter.h" -#include "include/atomic.h" #include "common/RWLock.h" #include "include/types.h" -#include "include/compat.h" -#include "include/inline_memory.h" #include "include/scope_guard.h" + #if defined(HAVE_XIO) #include "msg/xio/XioMsg.h" #endif -#include -#include -#include -#include -#include - -#include -#include +using namespace ceph; #define CEPH_BUFFER_ALLOC_UNIT (MIN(CEPH_PAGE_SIZE, 4096)) #define CEPH_BUFFER_APPEND_SIZE (CEPH_BUFFER_ALLOC_UNIT - sizeof(raw_combined)) @@ -54,71 +51,73 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; # define bendl std::endl; } #endif - static atomic_t buffer_total_alloc; - static atomic64_t buffer_history_alloc_bytes; - static atomic64_t buffer_history_alloc_num; + static std::atomic buffer_total_alloc { 0 }; + static std::atomic buffer_history_alloc_bytes { 0 }; + static std::atomic buffer_history_alloc_num { 0 }; + const bool buffer_track_alloc = get_env_bool("CEPH_BUFFER_TRACK"); namespace { void inc_total_alloc(unsigned len) { if (buffer_track_alloc) - buffer_total_alloc.add(len); + buffer_total_alloc += len; } void dec_total_alloc(unsigned len) { if (buffer_track_alloc) - buffer_total_alloc.sub(len); + buffer_total_alloc -= len; } void inc_history_alloc(uint64_t len) { if (buffer_track_alloc) { - buffer_history_alloc_bytes.add(len); - buffer_history_alloc_num.inc(); + buffer_history_alloc_bytes += len; + buffer_history_alloc_num++; } } - } - + } // namespace int buffer::get_total_alloc() { - return buffer_total_alloc.read(); + return buffer_total_alloc; } uint64_t buffer::get_history_alloc_bytes() { - return buffer_history_alloc_bytes.read(); + return buffer_history_alloc_bytes; } uint64_t buffer::get_history_alloc_num() { - return buffer_history_alloc_num.read(); + return buffer_history_alloc_num; } - static atomic_t buffer_cached_crc; - static atomic_t buffer_cached_crc_adjusted; - static atomic_t buffer_missed_crc; + static std::atomic buffer_cached_crc { 0 }; + static std::atomic buffer_cached_crc_adjusted { 0 }; + static std::atomic buffer_missed_crc { 0 }; + static bool buffer_track_crc = get_env_bool("CEPH_BUFFER_TRACK"); void buffer::track_cached_crc(bool b) { buffer_track_crc = b; } int buffer::get_cached_crc() { - return buffer_cached_crc.read(); + return buffer_cached_crc; } int buffer::get_cached_crc_adjusted() { - return buffer_cached_crc_adjusted.read(); + return buffer_cached_crc_adjusted; } int buffer::get_missed_crc() { - return buffer_missed_crc.read(); + return buffer_missed_crc; } - static atomic_t buffer_c_str_accesses; + static std::atomic buffer_c_str_accesses { 0 }; + static bool buffer_track_c_str = get_env_bool("CEPH_BUFFER_TRACK"); void buffer::track_c_str(bool b) { buffer_track_c_str = b; } int buffer::get_c_str_accesses() { - return buffer_c_str_accesses.read(); + return buffer_c_str_accesses; } - static atomic_t buffer_max_pipe_size; + static std::atomic buffer_max_pipe_size { 0 }; int update_max_pipe_size() { #ifdef CEPH_HAVE_SETPIPE_SZ char buf[32]; @@ -135,18 +134,18 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; size_t size = strict_strtol(buf, 10, &err); if (!err.empty()) return -EIO; - buffer_max_pipe_size.set(size); + buffer_max_pipe_size = size; #endif return 0; } size_t get_max_pipe_size() { #ifdef CEPH_HAVE_SETPIPE_SZ - size_t size = buffer_max_pipe_size.read(); + size_t size = buffer_max_pipe_size; if (size) return size; if (update_max_pipe_size() == 0) - return buffer_max_pipe_size.read(); + return buffer_max_pipe_size; #endif // this is the max size hardcoded in linux before 2.6.35 return 65536; @@ -171,18 +170,47 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; public: char *data; unsigned len; - atomic_t nref; + std::atomic nref { 0 }; + int mempool = mempool::mempool_buffer_anon; mutable std::atomic_flag crc_spinlock = ATOMIC_FLAG_INIT; map, pair > crc_map; explicit raw(unsigned l) - : data(NULL), len(l), nref(0) - { } + : data(NULL), len(l), nref(0) { + mempool::get_pool(mempool::pool_index_t(mempool)).adjust_count(1, len); + } raw(char *c, unsigned l) - : data(c), len(l), nref(0) - { } - virtual ~raw() {} + : data(c), len(l), nref(0) { + mempool::get_pool(mempool::pool_index_t(mempool)).adjust_count(1, len); + } + virtual ~raw() { + mempool::get_pool(mempool::pool_index_t(mempool)).adjust_count( + -1, -(int)len); + } + + void _set_len(unsigned l) { + mempool::get_pool(mempool::pool_index_t(mempool)).adjust_count( + -1, -(int)len); + len = l; + mempool::get_pool(mempool::pool_index_t(mempool)).adjust_count(1, len); + } + + void reassign_to_mempool(int pool) { + if (pool == mempool) { + return; + } + mempool::get_pool(mempool::pool_index_t(mempool)).adjust_count( + -1, -(int)len); + mempool = pool; + mempool::get_pool(mempool::pool_index_t(pool)).adjust_count(1, len); + } + + void try_assign_to_mempool(int pool) { + if (mempool == mempool::mempool_buffer_anon) { + reassign_to_mempool(pool); + } + } // no copying. // cppcheck-suppress noExplicitConstructor @@ -244,8 +272,6 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; } }; - MEMPOOL_DEFINE_FACTORY(char, char, buffer_data); - /* * raw_combined is always placed within a single allocation along * with the data buffer. the data goes at the beginning, and @@ -274,8 +300,14 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; alignof(buffer::raw_combined)); size_t datalen = ROUND_UP_TO(len, alignof(buffer::raw_combined)); - char *ptr = mempool::buffer_data::alloc_char.allocate_aligned( - rawlen + datalen, align); +#ifdef DARWIN + char *ptr = (char *) valloc(rawlen + datalen); +#else + char *ptr = 0; + int r = ::posix_memalign((void**)(void*)&ptr, align, rawlen + datalen); + if (r) + throw bad_alloc(); +#endif /* DARWIN */ if (!ptr) throw bad_alloc(); @@ -286,11 +318,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; static void operator delete(void *ptr) { raw_combined *raw = (raw_combined *)ptr; - size_t rawlen = ROUND_UP_TO(sizeof(buffer::raw_combined), - alignof(buffer::raw_combined)); - size_t datalen = ROUND_UP_TO(raw->len, alignof(buffer::raw_combined)); - mempool::buffer_data::alloc_char.deallocate_aligned( - raw->data, rawlen + datalen); + ::free((void *)raw->data); } }; @@ -355,7 +383,13 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; raw_posix_aligned(unsigned l, unsigned _align) : raw(l) { align = _align; assert((align >= sizeof(void *)) && (align & (align - 1)) == 0); - data = mempool::buffer_data::alloc_char.allocate_aligned(len, align); +#ifdef DARWIN + data = (char *) valloc(len); +#else + int r = ::posix_memalign((void**)(void*)&data, align, len); + if (r) + throw bad_alloc(); +#endif /* DARWIN */ if (!data) throw bad_alloc(); inc_total_alloc(len); @@ -363,7 +397,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " l=" << l << ", align=" << align << " total_alloc=" << buffer::get_total_alloc() << bendl; } ~raw_posix_aligned() override { - mempool::buffer_data::alloc_char.deallocate_aligned(data, len); + ::free(data); dec_total_alloc(len); bdout << "raw_posix_aligned " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl; } @@ -466,7 +500,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; return r; } // update length with actual amount read - len = r; + _set_len(r); return 0; } @@ -589,7 +623,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; explicit raw_char(unsigned l) : raw(l) { if (len) - data = mempool::buffer_data::alloc_char.allocate(len); + data = new char[len]; else data = 0; inc_total_alloc(len); @@ -601,8 +635,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; bdout << "raw_char " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl; } ~raw_char() override { - if (data) - mempool::buffer_data::alloc_char.deallocate(data, len); + delete[] data; dec_total_alloc(len); bdout << "raw_char " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl; } @@ -611,6 +644,25 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; } }; + class buffer::raw_claimed_char : public buffer::raw { + public: + MEMPOOL_CLASS_HELPERS(); + + explicit raw_claimed_char(unsigned l, char *b) : raw(b, l) { + inc_total_alloc(len); + bdout << "raw_claimed_char " << this << " alloc " << (void *)data + << " " << l << " " << buffer::get_total_alloc() << bendl; + } + ~raw_claimed_char() override { + dec_total_alloc(len); + bdout << "raw_claimed_char " << this << " free " << (void *)data + << " " << buffer::get_total_alloc() << bendl; + } + raw* clone_empty() override { + return new raw_char(len); + } + }; + class buffer::raw_unshareable : public buffer::raw { public: MEMPOOL_CLASS_HELPERS(); @@ -719,7 +771,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; return buffer::create_aligned(len, sizeof(size_t)); } buffer::raw* buffer::claim_char(unsigned len, char *buf) { - return new raw_char(len, buf); + return new raw_claimed_char(len, buf); } buffer::raw* buffer::create_malloc(unsigned len) { return new raw_malloc(len); @@ -779,25 +831,25 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; buffer::ptr::ptr(raw *r) : _raw(r), _off(0), _len(r->len) // no lock needed; this is an unref raw. { - r->nref.inc(); + r->nref++; bdout << "ptr " << this << " get " << _raw << bendl; } buffer::ptr::ptr(unsigned l) : _off(0), _len(l) { _raw = create(l); - _raw->nref.inc(); + _raw->nref++; bdout << "ptr " << this << " get " << _raw << bendl; } buffer::ptr::ptr(const char *d, unsigned l) : _off(0), _len(l) // ditto. { _raw = copy(d, l); - _raw->nref.inc(); + _raw->nref++; bdout << "ptr " << this << " get " << _raw << bendl; } buffer::ptr::ptr(const ptr& p) : _raw(p._raw), _off(p._off), _len(p._len) { if (_raw) { - _raw->nref.inc(); + _raw->nref++; bdout << "ptr " << this << " get " << _raw << bendl; } } @@ -811,13 +863,13 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; { assert(o+l <= p._len); assert(_raw); - _raw->nref.inc(); + _raw->nref++; bdout << "ptr " << this << " get " << _raw << bendl; } buffer::ptr& buffer::ptr::operator= (const ptr& p) { if (p._raw) { - p._raw->nref.inc(); + p._raw->nref++; bdout << "ptr " << this << " get " << _raw << bendl; } buffer::raw *raw = p._raw; @@ -856,8 +908,8 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; if (_raw && !_raw->is_shareable()) { buffer::raw *tr = _raw; _raw = tr->clone(); - _raw->nref.set(1); - if (unlikely(tr->nref.dec() == 0)) { + _raw->nref = 1; + if (unlikely(--tr->nref == 0)) { ANNOTATE_HAPPENS_AFTER(&tr->nref); ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&tr->nref); delete tr; @@ -885,7 +937,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; { if (_raw) { bdout << "ptr " << this << " release " << _raw << bendl; - if (_raw->nref.dec() == 0) { + if (--_raw->nref == 0) { //cout << "hosing raw " << (void*)_raw << " len " << _raw->len << std::endl; ANNOTATE_HAPPENS_AFTER(&_raw->nref); ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&_raw->nref); @@ -902,25 +954,25 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; const char *buffer::ptr::c_str() const { assert(_raw); if (buffer_track_c_str) - buffer_c_str_accesses.inc(); + buffer_c_str_accesses++; return _raw->get_data() + _off; } char *buffer::ptr::c_str() { assert(_raw); if (buffer_track_c_str) - buffer_c_str_accesses.inc(); + buffer_c_str_accesses++; return _raw->get_data() + _off; } const char *buffer::ptr::end_c_str() const { assert(_raw); if (buffer_track_c_str) - buffer_c_str_accesses.inc(); + buffer_c_str_accesses++; return _raw->get_data() + _off + _len; } char *buffer::ptr::end_c_str() { assert(_raw); if (buffer_track_c_str) - buffer_c_str_accesses.inc(); + buffer_c_str_accesses++; return _raw->get_data() + _off + _len; } @@ -946,7 +998,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; const char *buffer::ptr::raw_c_str() const { assert(_raw); return _raw->data; } unsigned buffer::ptr::raw_length() const { assert(_raw); return _raw->len; } - int buffer::ptr::raw_nref() const { assert(_raw); return _raw->nref.read(); } + int buffer::ptr::raw_nref() const { assert(_raw); return _raw->nref; } void buffer::ptr::copy_out(unsigned o, unsigned l, char *dest) const { assert(_raw); @@ -956,9 +1008,8 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; maybe_inline_memcpy(dest, src, l, 8); } - unsigned buffer::ptr::wasted() + unsigned buffer::ptr::wasted() const { - assert(_raw); return _raw->len - _len; } @@ -1441,6 +1492,7 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; { std::swap(_len, other._len); std::swap(_memcopy_count, other._memcopy_count); + std::swap(_mempool, other._mempool); _buffers.swap(other._buffers); append_buffer.swap(other.append_buffer); //last_p.swap(other.last_p); @@ -1613,6 +1665,28 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; return is_aligned(CEPH_PAGE_SIZE); } + void buffer::list::reassign_to_mempool(int pool) + { + _mempool = pool; + if (append_buffer.get_raw()) { + append_buffer.get_raw()->reassign_to_mempool(pool); + } + for (auto& p : _buffers) { + p.get_raw()->reassign_to_mempool(pool); + } + } + + void buffer::list::try_assign_to_mempool(int pool) + { + _mempool = pool; + if (append_buffer.get_raw()) { + append_buffer.get_raw()->try_assign_to_mempool(pool); + } + for (auto& p : _buffers) { + p.get_raw()->try_assign_to_mempool(pool); + } + } + void buffer::list::rebuild() { if (_len == 0) { @@ -1700,6 +1774,17 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; return rebuild_aligned(CEPH_PAGE_SIZE); } + void buffer::list::reserve(size_t prealloc) + { + if (append_buffer.unused_tail_length() < prealloc) { + append_buffer = buffer::create(prealloc); + if (_mempool >= 0) { + append_buffer.get_raw()->reassign_to_mempool(_mempool); + } + append_buffer.set_length(0); // unused, so far. + } + } + // sort-of-like-assignment-op void buffer::list::claim(list& bl, unsigned int flags) { @@ -1730,6 +1815,16 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; bl.last_p = bl.begin(); } + void buffer::list::claim_append_piecewise(list& bl) + { + // steal the other guy's buffers + for (std::list::const_iterator i = bl.buffers().begin(); + i != bl.buffers().end(); i++) { + append(*i, 0, i->length()); + } + bl.clear(); + } + void buffer::list::copy(unsigned off, unsigned len, char *dest) const { if (off + len > length()) @@ -1785,6 +1880,9 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; // make a new append_buffer! append_buffer = raw_combined::create(CEPH_BUFFER_APPEND_SIZE); append_buffer.set_length(0); // unused, so far. + if (_mempool >= 0) { + append_buffer.get_raw()->reassign_to_mempool(_mempool); + } } append(append_buffer, append_buffer.append(c) - 1, 1); // add segment to the list } @@ -1812,6 +1910,9 @@ static std::atomic_flag buffer_debug_lock = ATOMIC_FLAG_INIT; sizeof(raw_combined); append_buffer = raw_combined::create(alen); append_buffer.set_length(0); // unused, so far. + if (_mempool >= 0) { + append_buffer.get_raw()->reassign_to_mempool(_mempool); + } } } @@ -2381,7 +2482,7 @@ __u32 buffer::list::crc32c(__u32 crc) const // got it already crc = ccrc.second; if (buffer_track_crc) - buffer_cached_crc.inc(); + buffer_cached_crc++; } else { /* If we have cached crc32c(buf, v) for initial value v, * we can convert this to a different initial value v' by: @@ -2393,11 +2494,11 @@ __u32 buffer::list::crc32c(__u32 crc) const */ crc = ccrc.second ^ ceph_crc32c(ccrc.first ^ crc, NULL, it->length()); if (buffer_track_crc) - buffer_cached_crc_adjusted.inc(); + buffer_cached_crc_adjusted++; } } else { if (buffer_track_crc) - buffer_missed_crc.inc(); + buffer_missed_crc++; uint32_t base = crc; crc = ceph_crc32c(crc, (unsigned char*)it->c_str(), it->length()); r->set_crc(ofs, make_pair(base, crc)); @@ -2502,8 +2603,27 @@ void buffer::list::hexdump(std::ostream &out, bool trailing_newline) const out.flags(original_flags); } + +buffer::list buffer::list::static_from_mem(char* c, size_t l) { + list bl; + bl.push_back(ptr(create_static(l, c))); + return bl; +} + +buffer::list buffer::list::static_from_cstring(char* c) { + return static_from_mem(c, std::strlen(c)); +} + +buffer::list buffer::list::static_from_string(string& s) { + // C++14 just has string::data return a char* from a non-const + // string. + return static_from_mem(const_cast(s.data()), s.length()); + // But the way buffer::list mostly doesn't work in a sane way with + // const makes me generally sad. +} + std::ostream& buffer::operator<<(std::ostream& out, const buffer::raw &r) { - return out << "buffer::raw(" << (void*)r.data << " len " << r.len << " nref " << r.nref.read() << ")"; + return out << "buffer::raw(" << (void*)r.data << " len " << r.len << " nref " << r.nref.load() << ")"; } std::ostream& buffer::operator<<(std::ostream& out, const buffer::ptr& bp) { @@ -2546,6 +2666,8 @@ MEMPOOL_DEFINE_OBJECT_FACTORY(buffer::raw_posix_aligned, MEMPOOL_DEFINE_OBJECT_FACTORY(buffer::raw_pipe, buffer_raw_pipe, buffer_meta); #endif MEMPOOL_DEFINE_OBJECT_FACTORY(buffer::raw_char, buffer_raw_char, buffer_meta); +MEMPOOL_DEFINE_OBJECT_FACTORY(buffer::raw_claimed_char, buffer_raw_claimed_char, + buffer_meta); MEMPOOL_DEFINE_OBJECT_FACTORY(buffer::raw_unshareable, buffer_raw_unshareable, buffer_meta); MEMPOOL_DEFINE_OBJECT_FACTORY(buffer::raw_static, buffer_raw_static, diff --git a/ceph/src/common/ceph_argparse.cc b/ceph/src/common/ceph_argparse.cc index 2d73da9dd..355224d0a 100644 --- a/ceph/src/common/ceph_argparse.cc +++ b/ceph/src/common/ceph_argparse.cc @@ -13,23 +13,10 @@ */ #include "auth/Auth.h" -#include "common/ConfUtils.h" #include "common/ceph_argparse.h" -#include "common/common_init.h" #include "common/config.h" -#include "common/strtol.h" #include "common/version.h" -#include "include/intarith.h" #include "include/str_list.h" -#include "msg/msg_types.h" - -#include -#include -#include -#include -#include -#include -#include /* * Ceph argument parsing library diff --git a/ceph/src/common/ceph_argparse.h b/ceph/src/common/ceph_argparse.h index 3cf8b7a03..9e33d939b 100644 --- a/ceph/src/common/ceph_argparse.h +++ b/ceph/src/common/ceph_argparse.h @@ -23,13 +23,10 @@ * stuff to live. */ -#include -#include #include #include #include "common/entity_name.h" -#include "msg/msg_types.h" /////////////////////// Types /////////////////////// class CephInitParameters diff --git a/ceph/src/common/ceph_context.cc b/ceph/src/common/ceph_context.cc index 29aaa86bd..dde6854ef 100644 --- a/ceph/src/common/ceph_context.cc +++ b/ceph/src/common/ceph_context.cc @@ -13,37 +13,21 @@ * */ -#include - #include #include "include/mempool.h" #include "common/admin_socket.h" #include "common/perf_counters.h" -#include "common/Thread.h" #include "common/code_environment.h" -#include "common/ceph_context.h" #include "common/ceph_crypto.h" -#include "common/config.h" -#include "common/debug.h" #include "common/HeartbeatMap.h" #include "common/errno.h" -#include "common/lockdep.h" -#include "common/Formatter.h" #include "common/Graylog.h" -#include "log/Log.h" #include "auth/Crypto.h" #include "include/str_list.h" -#include "common/Mutex.h" -#include "common/Cond.h" #include "common/PluginRegistry.h" -#include "common/valgrind.h" - -#include -#include - -#include "include/Spinlock.h" +using ceph::bufferlist; using ceph::HeartbeatMap; namespace { @@ -496,6 +480,35 @@ void CephContext::do_command(std::string command, cmdmap_t& cmdmap, f->dump_string("option", *p); } f->close_section(); // unknown + } else if (command == "config diff get") { + std::string setting; + if (!cmd_getval(this, cmdmap, "var", setting)) { + f->dump_string("error", "syntax error: 'config diff get '"); + } else { + md_config_t def_conf; + def_conf.set_val("cluster", _conf->cluster); + def_conf.name = _conf->name; + def_conf.set_val("host", _conf->host); + def_conf.apply_changes(NULL); + + map> diff; + set unknown; + def_conf.diff(_conf, &diff, &unknown, setting); + f->open_object_section("diff"); + f->open_object_section("current"); + + for (const auto& p : diff) { + f->dump_string(p.first.c_str(), p.second.second); + } + f->close_section(); //-- current + + f->open_object_section("defaults"); + for (const auto& p : diff) { + f->dump_string(p.first.c_str(), p.second.first); + } + f->close_section(); //-- defaults + f->close_section(); //-- diff + } } else if (command == "log flush") { _log->flush(); } @@ -582,6 +595,9 @@ CephContext::CephContext(uint32_t module_type_, int init_flags_) _admin_socket->register_command("config diff", "config diff", _admin_hook, "dump diff of current config and default config"); + _admin_socket->register_command("config diff get", + "config diff get name=var,type=CephString", _admin_hook, + "dump diff get : dump diff of current and default config setting "); _admin_socket->register_command("log flush", "log flush", _admin_hook, "flush log entries to log file"); _admin_socket->register_command("log dump", "log dump", _admin_hook, "dump recent log entries to log file"); _admin_socket->register_command("log reopen", "log reopen", _admin_hook, "reopen log file"); @@ -610,16 +626,19 @@ CephContext::~CephContext() delete _plugin_registry; _admin_socket->unregister_command("perfcounters_dump"); - _admin_socket->unregister_command("perf dump"); _admin_socket->unregister_command("1"); + _admin_socket->unregister_command("perf dump"); _admin_socket->unregister_command("perfcounters_schema"); - _admin_socket->unregister_command("perf schema"); + _admin_socket->unregister_command("perf histogram dump"); _admin_socket->unregister_command("2"); + _admin_socket->unregister_command("perf schema"); + _admin_socket->unregister_command("perf histogram schema"); _admin_socket->unregister_command("perf reset"); _admin_socket->unregister_command("config show"); _admin_socket->unregister_command("config set"); _admin_socket->unregister_command("config get"); _admin_socket->unregister_command("config diff"); + _admin_socket->unregister_command("config diff get"); _admin_socket->unregister_command("log flush"); _admin_socket->unregister_command("log dump"); _admin_socket->unregister_command("log reopen"); @@ -664,7 +683,7 @@ CephContext::~CephContext() } void CephContext::put() { - if (nref.dec() == 0) { + if (--nref == 0) { ANNOTATE_HAPPENS_AFTER(&nref); ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref); delete this; diff --git a/ceph/src/common/ceph_context.h b/ceph/src/common/ceph_context.h index 0026b6851..64aec93f7 100644 --- a/ceph/src/common/ceph_context.h +++ b/ceph/src/common/ceph_context.h @@ -15,18 +15,13 @@ #ifndef CEPH_CEPHCONTEXT_H #define CEPH_CEPHCONTEXT_H -#include -#include -#include +#include #include +#include -#include "include/assert.h" -#include "include/buffer_fwd.h" -#include "include/atomic.h" #include "common/cmdparse.h" -#include "include/Spinlock.h" #include "crush/CrushLocation.h" -#include +#include "include/Spinlock.h" class AdminSocket; class CephContextServiceThread; @@ -46,8 +41,6 @@ namespace ceph { } } -using ceph::bufferlist; - /* A CephContext represents the context held by a single library user. * There can be multiple CephContexts in the same process. * @@ -62,10 +55,10 @@ public: // ref count! private: ~CephContext(); - atomic_t nref; + std::atomic nref; public: CephContext *get() { - nref.inc(); + ++nref; return this; } void put(); @@ -125,7 +118,7 @@ public: * process an admin socket command */ void do_command(std::string command, cmdmap_t& cmdmap, std::string format, - bufferlist *out); + ceph::bufferlist *out); template void lookup_or_create_singleton_object(T*& p, const std::string &name) { diff --git a/ceph/src/common/ceph_crypto.cc b/ceph/src/common/ceph_crypto.cc index 67db50314..849d5fe70 100644 --- a/ceph/src/common/ceph_crypto.cc +++ b/ceph/src/common/ceph_crypto.cc @@ -12,15 +12,8 @@ * */ -#include "include/int_types.h" #include "common/config.h" -#include "common/ceph_context.h" #include "ceph_crypto.h" -#include "auth/Crypto.h" - -#include -#include - #ifdef USE_CRYPTOPP void ceph::crypto::init(CephContext *cct) diff --git a/ceph/src/common/ceph_crypto_cms.cc b/ceph/src/common/ceph_crypto_cms.cc index 043376b4a..109f702bf 100644 --- a/ceph/src/common/ceph_crypto_cms.cc +++ b/ceph/src/common/ceph_crypto_cms.cc @@ -36,31 +36,18 @@ #include "common/config.h" +#include "common/debug.h" #ifdef USE_NSS - #include #include #include #include - #endif -#include -#include - - -#include "include/buffer.h" - -#include "common/debug.h" - -#include "ceph_crypto_cms.h" - #define dout_subsys ceph_subsys_crypto - #ifndef USE_NSS - int ceph_decode_cms(CephContext *cct, bufferlist& cms_bl, bufferlist& decoded_bl) { return -ENOTSUP; @@ -68,7 +55,6 @@ int ceph_decode_cms(CephContext *cct, bufferlist& cms_bl, bufferlist& decoded_bl #else - static int cms_verbose = 0; static SECStatus @@ -356,5 +342,4 @@ int ceph_decode_cms(CephContext *cct, bufferlist& cms_bl, bufferlist& decoded_bl return ret; } - #endif diff --git a/ceph/src/common/ceph_json.cc b/ceph/src/common/ceph_json.cc index 52be8421b..e326fdebc 100644 --- a/ceph/src/common/ceph_json.cc +++ b/ceph/src/common/ceph_json.cc @@ -1,13 +1,9 @@ -#include -#include -#include -#include - #include "common/ceph_json.h" #include "include/utime.h" // for testing DELETE ME #include +#include using namespace std; using namespace json_spirit; diff --git a/ceph/src/common/ceph_json.h b/ceph/src/common/ceph_json.h index 18cf06fd4..cd868a88f 100644 --- a/ceph/src/common/ceph_json.h +++ b/ceph/src/common/ceph_json.h @@ -1,9 +1,7 @@ #ifndef CEPH_JSON_H #define CEPH_JSON_H -#include #include -#include #ifdef _ASSERT_H #define NEED_ASSERT_H @@ -19,7 +17,6 @@ #include "Formatter.h" - using namespace json_spirit; @@ -210,8 +207,8 @@ void decode_json_obj(vector& l, JSONObj *obj) } } -template -void decode_json_obj(map& m, JSONObj *obj) +template > +void decode_json_obj(map& m, JSONObj *obj) { m.clear(); @@ -384,11 +381,11 @@ static void encode_json(const char *name, const std::vector& l, ceph::Formatt f->close_section(); } -template -static void encode_json(const char *name, const std::map& m, ceph::Formatter *f) +template > +static void encode_json(const char *name, const std::map& m, ceph::Formatter *f) { f->open_array_section(name); - for (typename std::map::const_iterator i = m.begin(); i != m.end(); ++i) { + for (typename std::map::const_iterator i = m.begin(); i != m.end(); ++i) { f->open_object_section("entry"); encode_json("key", i->first, f); encode_json("val", i->second, f); diff --git a/ceph/src/common/ceph_strings.cc b/ceph/src/common/ceph_strings.cc index 1fec2f7b0..ac1e8fd64 100644 --- a/ceph/src/common/ceph_strings.cc +++ b/ceph/src/common/ceph_strings.cc @@ -2,6 +2,7 @@ * Ceph string constants */ #include "include/types.h" +#include "include/ceph_features.h" const char *ceph_entity_type_name(int type) { @@ -44,9 +45,159 @@ const char *ceph_osd_state_name(int s) return "nearfull"; case CEPH_OSD_BACKFILLFULL: return "backfillfull"; + case CEPH_OSD_DESTROYED: + return "destroyed"; + case CEPH_OSD_NOUP: + return "noup"; + case CEPH_OSD_NODOWN: + return "nodown"; + case CEPH_OSD_NOIN: + return "noin"; + case CEPH_OSD_NOOUT: + return "noout"; default: return "???"; - } + } +} + +const char *ceph_release_name(int r) +{ + switch (r) { + case CEPH_RELEASE_ARGONAUT: + return "argonaut"; + case CEPH_RELEASE_BOBTAIL: + return "bobtail"; + case CEPH_RELEASE_CUTTLEFISH: + return "cuttlefish"; + case CEPH_RELEASE_DUMPLING: + return "dumpling"; + case CEPH_RELEASE_EMPEROR: + return "emperor"; + case CEPH_RELEASE_FIREFLY: + return "firefly"; + case CEPH_RELEASE_GIANT: + return "giant"; + case CEPH_RELEASE_HAMMER: + return "hammer"; + case CEPH_RELEASE_INFERNALIS: + return "infernalis"; + case CEPH_RELEASE_JEWEL: + return "jewel"; + case CEPH_RELEASE_KRAKEN: + return "kraken"; + case CEPH_RELEASE_LUMINOUS: + return "luminous"; + case CEPH_RELEASE_MIMIC: + return "mimic"; + default: + return "unknown"; + } +} + +int ceph_release_from_name(const char *s) +{ + if (!s) { + return -1; + } + if (strcmp(s, "mimic") == 0) { + return CEPH_RELEASE_MIMIC; + } + if (strcmp(s, "luminous") == 0) { + return CEPH_RELEASE_LUMINOUS; + } + if (strcmp(s, "kraken") == 0) { + return CEPH_RELEASE_KRAKEN; + } + if (strcmp(s, "jewel") == 0) { + return CEPH_RELEASE_JEWEL; + } + if (strcmp(s, "infernalis") == 0) { + return CEPH_RELEASE_INFERNALIS; + } + if (strcmp(s, "hammer") == 0) { + return CEPH_RELEASE_HAMMER; + } + if (strcmp(s, "giant") == 0) { + return CEPH_RELEASE_GIANT; + } + if (strcmp(s, "firefly") == 0) { + return CEPH_RELEASE_FIREFLY; + } + if (strcmp(s, "emperor") == 0) { + return CEPH_RELEASE_EMPEROR; + } + if (strcmp(s, "dumpling") == 0) { + return CEPH_RELEASE_DUMPLING; + } + if (strcmp(s, "cuttlefish") == 0) { + return CEPH_RELEASE_CUTTLEFISH; + } + if (strcmp(s, "bobtail") == 0) { + return CEPH_RELEASE_BOBTAIL; + } + if (strcmp(s, "argonaut") == 0) { + return CEPH_RELEASE_ARGONAUT; + } + return -1; +} + +uint64_t ceph_release_features(int r) +{ + uint64_t req = 0; + + req |= CEPH_FEATURE_CRUSH_TUNABLES; + if (r <= CEPH_RELEASE_CUTTLEFISH) + return req; + + req |= CEPH_FEATURE_CRUSH_TUNABLES2 | + CEPH_FEATURE_OSDHASHPSPOOL; + if (r <= CEPH_RELEASE_EMPEROR) + return req; + + req |= CEPH_FEATURE_CRUSH_TUNABLES3 | + CEPH_FEATURE_OSD_PRIMARY_AFFINITY | + CEPH_FEATURE_OSD_CACHEPOOL; + if (r <= CEPH_RELEASE_GIANT) + return req; + + req |= CEPH_FEATURE_CRUSH_V4; + if (r <= CEPH_RELEASE_INFERNALIS) + return req; + + req |= CEPH_FEATURE_CRUSH_TUNABLES5; + if (r <= CEPH_RELEASE_JEWEL) + return req; + + req |= CEPH_FEATURE_MSG_ADDR2; + if (r <= CEPH_RELEASE_KRAKEN) + return req; + + req |= CEPH_FEATUREMASK_CRUSH_CHOOSE_ARGS; // and overlaps + if (r <= CEPH_RELEASE_LUMINOUS) + return req; + + return req; +} + +/* return oldest/first release that supports these features */ +int ceph_release_from_features(uint64_t features) +{ + int r = 1; + while (true) { + uint64_t need = ceph_release_features(r); + if ((need & features) != need || + r == CEPH_RELEASE_MAX) { + r--; + need = ceph_release_features(r); + /* we want the first release that looks like this */ + while (r > 1 && ceph_release_features(r - 1) == need) { + r--; + } + break; + } + ++r; + } + return r; } const char *ceph_osd_watch_op_name(int o) diff --git a/ceph/src/common/ceph_time.cc b/ceph/src/common/ceph_time.cc index 552b45a4e..be7c5f889 100644 --- a/ceph/src/common/ceph_time.cc +++ b/ceph/src/common/ceph_time.cc @@ -13,7 +13,6 @@ */ // For ceph_timespec -#include "include/types.h" #include "ceph_time.h" #include "config.h" diff --git a/ceph/src/common/ceph_time.h b/ceph/src/common/ceph_time.h index c4937111b..8479a0d54 100644 --- a/ceph/src/common/ceph_time.h +++ b/ceph/src/common/ceph_time.h @@ -16,7 +16,6 @@ #define COMMON_CEPH_TIME_H #include -#include #include "include/encoding.h" diff --git a/ceph/src/common/ceph_timer.h b/ceph/src/common/ceph_timer.h index 6323be66a..4b7438672 100644 --- a/ceph/src/common/ceph_timer.h +++ b/ceph/src/common/ceph_timer.h @@ -16,14 +16,9 @@ #define COMMON_CEPH_TIMER_H #include -#include -#include #include - #include -#include "ceph_time.h" - namespace ceph { /// Newly constructed timer should be suspended at point of diff --git a/ceph/src/common/cmdparse.cc b/ceph/src/common/cmdparse.cc index 3fdf94c73..5a8e78e08 100644 --- a/ceph/src/common/cmdparse.cc +++ b/ceph/src/common/cmdparse.cc @@ -12,10 +12,6 @@ * */ -#include -#include "common/cmdparse.h" -#include "common/Formatter.h" -#include "include/str_list.h" #include "json_spirit/json_spirit.h" #include "common/debug.h" @@ -319,7 +315,7 @@ cmd_vartype_stringify(const cmd_vartype &v) void -handle_bad_get(CephContext *cct, string k, const char *tname) +handle_bad_get(CephContext *cct, const string& k, const char *tname) { ostringstream errstr; int status; @@ -335,3 +331,47 @@ handle_bad_get(CephContext *cct, string k, const char *tname) if (status == 0) free((char *)typestr); } + +long parse_pos_long(const char *s, std::ostream *pss) +{ + if (*s == '-' || *s == '+') { + if (pss) + *pss << "expected numerical value, got: " << s; + return -EINVAL; + } + + string err; + long r = strict_strtol(s, 10, &err); + if ((r == 0) && !err.empty()) { + if (pss) + *pss << err; + return -1; + } + if (r < 0) { + if (pss) + *pss << "unable to parse positive integer '" << s << "'"; + return -1; + } + return r; +} + +int parse_osd_id(const char *s, std::ostream *pss) +{ + // osd.NNN? + if (strncmp(s, "osd.", 4) == 0) { + s += 4; + } + + // NNN? + ostringstream ss; + long id = parse_pos_long(s, &ss); + if (id < 0) { + *pss << ss.str(); + return id; + } + if (id > 0xffff) { + *pss << "osd id " << id << " is too large"; + return -ERANGE; + } + return id; +} diff --git a/ceph/src/common/cmdparse.h b/ceph/src/common/cmdparse.h index 104848dc2..35afc24ab 100644 --- a/ceph/src/common/cmdparse.h +++ b/ceph/src/common/cmdparse.h @@ -3,12 +3,11 @@ #ifndef CEPH_COMMON_CMDPARSE_H #define CEPH_COMMON_CMDPARSE_H -#include -#include -#include -#include #include #include +#include +#include +#include "include/assert.h" // boost clobbers this #include "common/Formatter.h" #include "common/BackTrace.h" @@ -42,13 +41,13 @@ void dump_cmddesc_to_json(ceph::Formatter *jf, bool cmdmap_from_json(std::vector cmd, cmdmap_t *mapp, std::stringstream &ss); void cmdmap_dump(const cmdmap_t &cmdmap, ceph::Formatter *f); -void handle_bad_get(CephContext *cct, std::string k, const char *name); +void handle_bad_get(CephContext *cct, const std::string& k, const char *name); std::string cmd_vartype_stringify(const cmd_vartype& v); template bool -cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, std::string k, T& val) +cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, const std::string& k, T& val) { if (cmdmap.count(k)) { try { @@ -65,7 +64,7 @@ cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, std::string k, T& val) template void -cmd_getval(CephContext *cct, cmdmap_t& cmdmap, std::string k, T& val, T defval) +cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, const std::string& k, T& val, const T& defval) { if (!cmd_getval(cct, cmdmap, k, val)) val = defval; @@ -73,8 +72,12 @@ cmd_getval(CephContext *cct, cmdmap_t& cmdmap, std::string k, T& val, T defval) template void -cmd_putval(CephContext *cct, cmdmap_t& cmdmap, std::string k, T val) +cmd_putval(CephContext *cct, cmdmap_t& cmdmap, const std::string& k, const T& val) { cmdmap[k] = val; } + +extern int parse_osd_id(const char *s, std::ostream *pss); +extern long parse_pos_long(const char *s, std::ostream *pss = NULL); + #endif diff --git a/ceph/src/common/code_environment.cc b/ceph/src/common/code_environment.cc index 662fa36c9..7b106d585 100644 --- a/ceph/src/common/code_environment.cc +++ b/ceph/src/common/code_environment.cc @@ -11,15 +11,10 @@ * Foundation. See file COPYING. * */ -#include "acconfig.h" #include "common/code_environment.h" -#include #include -#include -#include -#include #ifdef HAVE_SYS_PRCTL_H #include @@ -41,7 +36,7 @@ extern "C" const char *code_environment_to_str(enum code_environment_t e) } } -std::ostream &operator<<(std::ostream &oss, enum code_environment_t e) +std::ostream &operator<<(std::ostream &oss, const enum code_environment_t e) { oss << code_environment_to_str(e); return oss; @@ -61,6 +56,24 @@ int get_process_name(char *buf, int len) return prctl(PR_GET_NAME, buf); } +#elif defined(HAVE_GETPROGNAME) + +int get_process_name(char *buf, int len) +{ + if (len <= 0) { + return -EINVAL; + } + + const char *progname = getprogname(); + if (progname == nullptr || *progname == '\0') { + return -ENOSYS; + } + + strncpy(buf, progname, len - 1); + buf[len - 1] = '\0'; + return 0; +} + #else int get_process_name(char *buf, int len) diff --git a/ceph/src/common/code_environment.h b/ceph/src/common/code_environment.h index e21f0eff4..b94ba52ca 100644 --- a/ceph/src/common/code_environment.h +++ b/ceph/src/common/code_environment.h @@ -28,14 +28,14 @@ enum code_environment_t { extern "C" code_environment_t g_code_env; extern "C" const char *code_environment_to_str(enum code_environment_t e); -std::ostream &operator<<(std::ostream &oss, enum code_environment_t e); +std::ostream &operator<<(std::ostream &oss, const enum code_environment_t e); extern "C" int get_process_name(char *buf, int len); std::string get_process_name_cpp(); #else extern code_environment_t g_code_env; -const char *code_environment_to_str(enum code_environment_t e); +const char *code_environment_to_str(const enum code_environment_t e); extern int get_process_name(char *buf, int len); #endif diff --git a/ceph/src/common/cohort_lru.h b/ceph/src/common/cohort_lru.h index 8a8b76699..13c760f76 100644 --- a/ceph/src/common/cohort_lru.h +++ b/ceph/src/common/cohort_lru.h @@ -13,16 +13,8 @@ #ifndef COHORT_LRU_H #define COHORT_LRU_H -#include -#include #include -#include -#include -#include -#include -#include -#include -#include + #include "common/likely.h" #ifndef CACHE_LINE_SIZE diff --git a/ceph/src/common/common_init.cc b/ceph/src/common/common_init.cc index d796e933c..a62f67e2e 100644 --- a/ceph/src/common/common_init.cc +++ b/ceph/src/common/common_init.cc @@ -14,22 +14,9 @@ #include "common/admin_socket.h" #include "common/ceph_argparse.h" -#include "common/ceph_context.h" -#include "common/ceph_crypto.h" -#include "common/code_environment.h" #include "common/common_init.h" -#include "common/config.h" -#include "common/dout.h" -#include "common/errno.h" -#include "common/safe_io.h" #include "common/valgrind.h" -#include "common/version.h" -#include "common/strtol.h" #include "common/zipkin_trace.h" -#include "include/color.h" - -#include -#include #define dout_subsys ceph_subsys_ diff --git a/ceph/src/common/common_init.h b/ceph/src/common/common_init.h index 6ef4a90f5..4c3c200bf 100644 --- a/ceph/src/common/common_init.h +++ b/ceph/src/common/common_init.h @@ -16,9 +16,6 @@ #define CEPH_COMMON_INIT_H #include -#include -#include -#include #include "common/code_environment.h" diff --git a/ceph/src/common/config.cc b/ceph/src/common/config.cc index 768a552cc..8c026f89a 100644 --- a/ceph/src/common/config.cc +++ b/ceph/src/common/config.cc @@ -12,36 +12,17 @@ * */ -#include "auth/Auth.h" -#include "common/ConfUtils.h" #include "common/ceph_argparse.h" #include "common/common_init.h" #include "common/config.h" #include "common/config_validators.h" -#include "common/static_assert.h" -#include "common/strtol.h" -#include "common/version.h" #include "include/str_list.h" -#include "include/types.h" #include "include/stringify.h" -#include "msg/msg_types.h" #include "osd/osd_types.h" #include "common/errno.h" #include "common/hostname.h" -#include "include/assert.h" - -#include -#include -#include -#include -#include -#include - -#include -#include #include -#include /* Don't use standard Ceph logging in this file. * We can't use logging until it's initialized, and a lot of the necessary @@ -57,10 +38,8 @@ using std::map; using std::list; -using std::multimap; using std::ostringstream; using std::pair; -using std::set; using std::string; const char *CEPH_CONF_FILE_DEFAULT = "$data_dir/config, /etc/ceph/$cluster.conf, ~/.ceph/$cluster.conf, $cluster.conf" @@ -1342,15 +1321,35 @@ bool md_config_t::expand_meta(std::string &origval, } void md_config_t::diff( + const md_config_t *other, + map > *diff, + set *unknown) +{ + diff_helper(other, diff, unknown); +} +void md_config_t::diff( + const md_config_t *other, + map > *diff, + set *unknown, const string& setting) +{ + diff_helper(other, diff, unknown, setting); +} + +void md_config_t::diff_helper( const md_config_t *other, map > *diff, - set *unknown) + set *unknown, const string& setting) { Mutex::Locker l(lock); char local_buf[4096]; char other_buf[4096]; - for (auto& opt: *config_options) { + for (auto& opt : *config_options) { + if (!setting.empty()) { + if (setting != opt.name) { + continue; + } + } memset(local_buf, 0, sizeof(local_buf)); memset(other_buf, 0, sizeof(other_buf)); @@ -1370,6 +1369,10 @@ void md_config_t::diff( if (strcmp(local_val, other_val)) diff->insert(make_pair(opt.name, make_pair(local_val, other_val))); + else if (!setting.empty()) { + diff->insert(make_pair(opt.name, make_pair(local_val, other_val))); + break; + } } } diff --git a/ceph/src/common/config.h b/ceph/src/common/config.h index bbabc14a8..0d32fb3b9 100644 --- a/ceph/src/common/config.h +++ b/ceph/src/common/config.h @@ -15,24 +15,11 @@ #ifndef CEPH_CONFIG_H #define CEPH_CONFIG_H -#include -#include -#include -#include -#include -#include - #include "common/ConfUtils.h" #include "common/entity_name.h" #include "common/Mutex.h" #include "log/SubsystemMap.h" #include "common/config_obs.h" -#include "msg/msg_types.h" - -enum { - CEPH_DEFAULT_CRUSH_REPLICATED_RULESET, - CEPH_DEFAULT_CRUSH_ERASURE_RULESET, -}; #define OSD_REP_PRIMARY 0 #define OSD_REP_SPLAY 1 @@ -239,6 +226,12 @@ public: void diff(const md_config_t *other, map > *diff, set *unknown); + /// obtain a diff between config values and another md_config_t + /// values for a specific setting. + void diff(const md_config_t *other, + map> *diff, set *unknown, + const string& setting); + /// print/log warnings/errors from parsing the config void complain_about_parse_errors(CephContext *cct); @@ -270,6 +263,11 @@ private: bool expand_meta(std::string &val, std::ostream *oss) const; + + void diff_helper(const md_config_t* other, + map>* diff, + set* unknown, const string& setting = string{}); + public: // for global_init bool early_expand_meta(std::string &val, std::ostream *oss) const { diff --git a/ceph/src/common/config_opts.h b/ceph/src/common/config_opts.h index eff246e57..443ef8c1a 100644 --- a/ceph/src/common/config_opts.h +++ b/ceph/src/common/config_opts.h @@ -211,7 +211,7 @@ OPTION(ms_bind_retry_delay, OPT_INT, 5) // Delay between attemps to bind OPTION(ms_bind_retry_count, OPT_INT, 6) // If binding fails, how many times do we retry to bind OPTION(ms_bind_retry_delay, OPT_INT, 6) // Delay between attemps to bind #endif -OPTION(ms_bind_before_connect, OPT_BOOL, true) +OPTION(ms_bind_before_connect, OPT_BOOL, false) OPTION(ms_rwthread_stack_bytes, OPT_U64, 1024 << 10) OPTION(ms_tcp_read_timeout, OPT_U64, 900) OPTION(ms_pq_max_tokens_per_priority, OPT_U64, 16777216) @@ -233,7 +233,6 @@ OPTION(ms_async_set_affinity, OPT_BOOL, true) // If ms_async_affinity_cores is empty, all threads will be bind to current running // core OPTION(ms_async_affinity_cores, OPT_STR, "") -OPTION(ms_async_send_inline, OPT_BOOL, false) OPTION(ms_async_rdma_device_name, OPT_STR, "") OPTION(ms_async_rdma_enable_hugepage, OPT_BOOL, false) OPTION(ms_async_rdma_buffer_size, OPT_INT, 128 << 10) @@ -244,6 +243,7 @@ OPTION(ms_async_rdma_polling_us, OPT_U32, 1000) OPTION(ms_async_rdma_local_gid, OPT_STR, "") // GID format: "fe80:0000:0000:0000:7efe:90ff:fe72:6efe", no zero folding OPTION(ms_async_rdma_roce_ver, OPT_INT, 1) // 0=RoCEv1, 1=RoCEv2, 2=RoCEv1.5 OPTION(ms_async_rdma_sl, OPT_INT, 3) // in RoCE, this means PCP +OPTION(ms_async_rdma_dscp, OPT_INT, 96) // in RoCE, this means DSCP OPTION(ms_dpdk_port_id, OPT_INT, 0) SAFE_OPTION(ms_dpdk_coremask, OPT_STR, "1") // it is modified in unittest so that use SAFE_OPTION to declare @@ -264,7 +264,6 @@ OPTION(inject_early_sigterm, OPT_BOOL, false) OPTION(mon_data, OPT_STR, "/var/lib/ceph/mon/$cluster-$id") OPTION(mon_initial_members, OPT_STR, "") // list of initial cluster mon ids; if specified, need majority to form initial quorum and create new cluster -OPTION(mon_sync_fs_threshold, OPT_INT, 5) // sync() when writing this many objects; 0 to disable. OPTION(mon_compact_on_start, OPT_BOOL, false) // compact leveldb on ceph-mon start OPTION(mon_compact_on_bootstrap, OPT_BOOL, false) // trigger leveldb compaction on bootstrap OPTION(mon_compact_on_trim, OPT_BOOL, true) // compact (a prefix) when we trim old states @@ -272,6 +271,7 @@ OPTION(mon_osd_cache_size, OPT_INT, 10) // the size of osdmaps cache, not to re OPTION(mon_cpu_threads, OPT_INT, 4) OPTION(mon_osd_mapping_pgs_per_chunk, OPT_INT, 4096) +OPTION(mon_osd_max_creating_pgs, OPT_INT, 1024) OPTION(mon_tick_interval, OPT_INT, 5) OPTION(mon_session_timeout, OPT_INT, 300) // must send keepalive or subscribe OPTION(mon_subscribe_interval, OPT_DOUBLE, 24*3600) // for legacy clients only @@ -288,7 +288,8 @@ OPTION(mon_osd_down_out_interval, OPT_INT, 600) // seconds OPTION(mon_osd_down_out_subtree_limit, OPT_STR, "rack") // smallest crush unit/type that we will not automatically mark out OPTION(mon_osd_min_up_ratio, OPT_DOUBLE, .3) // min osds required to be up to mark things down OPTION(mon_osd_min_in_ratio, OPT_DOUBLE, .75) // min osds required to be in to mark things out -OPTION(mon_osd_max_op_age, OPT_DOUBLE, 32) // max op age before we get concerned (make it a power of 2) +OPTION(mon_osd_warn_op_age, OPT_DOUBLE, 32) // max op age before we generate a warning (make it a power of 2) +OPTION(mon_osd_err_op_age_ratio, OPT_DOUBLE, 128) // when to generate an error, as multiple of mon_osd_warn_op_age OPTION(mon_osd_max_split_count, OPT_INT, 32) // largest number of PGs per "involved" OSD to let split create OPTION(mon_osd_allow_primary_temp, OPT_BOOL, false) // allow primary_temp to be set in the osdmap OPTION(mon_osd_allow_primary_affinity, OPT_BOOL, false) // allow primary_affinity to be set in the osdmap @@ -308,6 +309,7 @@ OPTION(mon_clock_drift_warn_backoff, OPT_FLOAT, 5) // exponential backoff for cl OPTION(mon_timecheck_interval, OPT_FLOAT, 300.0) // on leader, timecheck (clock drift check) interval (seconds) OPTION(mon_timecheck_skew_interval, OPT_FLOAT, 30.0) // on leader, timecheck (clock drift check) interval when in presence of a skew (seconds) OPTION(mon_pg_stuck_threshold, OPT_INT, 300) // number of seconds after which pgs can be considered inactive, unclean, or stale (see doc/control.rst under dump_stuck for more info) +OPTION(mon_health_max_detail, OPT_INT, 50) // max detailed pgs to report in health detail OPTION(mon_pg_min_inactive, OPT_U64, 1) // the number of PGs which have to be inactive longer than 'mon_pg_stuck_threshold' before health goes into ERR. 0 means disabled, never go into ERR. OPTION(mon_pg_warn_min_per_osd, OPT_INT, 30) // min # pgs per (in) osd before we warn the admin OPTION(mon_pg_warn_max_per_osd, OPT_INT, 300) // max # pgs per (in) osd before we warn the admin @@ -319,7 +321,7 @@ OPTION(mon_cache_target_full_warn_ratio, OPT_FLOAT, .66) // position between poo OPTION(mon_osd_full_ratio, OPT_FLOAT, .95) // what % full makes an OSD "full" OPTION(mon_osd_backfillfull_ratio, OPT_FLOAT, .90) // what % full makes an OSD backfill full (backfill halted) OPTION(mon_osd_nearfull_ratio, OPT_FLOAT, .85) // what % full makes an OSD near full -OPTION(mon_osd_initial_require_min_compat_client, OPT_STR, "hammer") +OPTION(mon_osd_initial_require_min_compat_client, OPT_STR, "jewel") OPTION(mon_allow_pool_delete, OPT_BOOL, false) // allow pool deletion OPTION(mon_fake_pool_delete, OPT_BOOL, false) // fake pool deletion (add _DELETED suffix) OPTION(mon_globalid_prealloc, OPT_U32, 10000) // how many globalids to prealloc @@ -337,10 +339,9 @@ OPTION(mon_max_log_epochs, OPT_INT, 500) OPTION(mon_max_mdsmap_epochs, OPT_INT, 500) OPTION(mon_max_osd, OPT_INT, 10000) OPTION(mon_probe_timeout, OPT_DOUBLE, 2.0) -OPTION(mon_slurp_timeout, OPT_DOUBLE, 10.0) -OPTION(mon_slurp_bytes, OPT_INT, 256*1024) // limit size of slurp messages OPTION(mon_client_bytes, OPT_U64, 100ul << 20) // client msg data allowed in memory (in bytes) OPTION(mon_mgr_proxy_client_bytes_ratio, OPT_FLOAT, .3) // ratio of mon_client_bytes that can be consumed by proxied mgr commands before we error out to client +OPTION(mon_log_max_summary, OPT_U64, 50) OPTION(mon_daemon_bytes, OPT_U64, 400ul << 20) // mds, osd message memory cap (in bytes) OPTION(mon_max_log_entries_per_event, OPT_INT, 4096) OPTION(mon_reweight_min_pgs_per_osd, OPT_U64, 10) // min pgs per osd for reweight-by-pg command @@ -365,9 +366,6 @@ OPTION(mon_config_key_max_entry_size, OPT_INT, 4096) // max num bytes per config OPTION(mon_sync_timeout, OPT_DOUBLE, 60.0) OPTION(mon_sync_max_payload_size, OPT_U32, 1048576) // max size for a sync chunk payload (say, 1MB) OPTION(mon_sync_debug, OPT_BOOL, false) // enable sync-specific debug -OPTION(mon_sync_debug_leader, OPT_INT, -1) // monitor to be used as the sync leader -OPTION(mon_sync_debug_provider, OPT_INT, -1) // monitor to be used as the sync provider -OPTION(mon_sync_debug_provider_fallback, OPT_INT, -1) // monitor to be used as fallback if sync provider fails OPTION(mon_inject_sync_get_chunk_delay, OPT_DOUBLE, 0) // inject N second delay on each get_chunk request OPTION(mon_osd_min_down_reporters, OPT_INT, 2) // number of OSDs from different subtrees who need to report a down OSD for it to count OPTION(mon_osd_reporter_subtree_level , OPT_STR, "host") // in which level of parent bucket the reporters are counted @@ -383,6 +381,8 @@ OPTION(mon_debug_dump_transactions, OPT_BOOL, false) OPTION(mon_debug_dump_json, OPT_BOOL, false) OPTION(mon_debug_dump_location, OPT_STR, "/var/log/ceph/$cluster-$name.tdump") OPTION(mon_debug_no_require_luminous, OPT_BOOL, false) +OPTION(mon_debug_no_require_bluestore_for_ec_overwrites, OPT_BOOL, false) +OPTION(mon_debug_no_initial_persistent_features, OPT_BOOL, false) OPTION(mon_inject_transaction_delay_max, OPT_DOUBLE, 10.0) // seconds OPTION(mon_inject_transaction_delay_probability, OPT_DOUBLE, 0) // range [0, 1] @@ -515,7 +515,11 @@ OPTION(mds_beacon_interval, OPT_FLOAT, 4) OPTION(mds_beacon_grace, OPT_FLOAT, 15) OPTION(mds_enforce_unique_name, OPT_BOOL, true) OPTION(mds_blacklist_interval, OPT_FLOAT, 24.0*60.0) // how long to blacklist failed nodes + OPTION(mds_session_timeout, OPT_FLOAT, 60) // cap bits and leases time out if client idle +OPTION(mds_session_blacklist_on_timeout, OPT_BOOL, true) // whether to blacklist clients whose sessions are dropped due to timeout +OPTION(mds_session_blacklist_on_evict, OPT_BOOL, true) // whether to blacklist clients whose sessions are dropped via admin commands + OPTION(mds_sessionmap_keys_per_op, OPT_U32, 1024) // how many sessions should I try to load/store in a single OMAP operation? OPTION(mds_revoke_cap_timeout, OPT_FLOAT, 60) // detect clients which aren't revoking caps OPTION(mds_recall_state_timeout, OPT_FLOAT, 60) // detect clients which aren't trimming caps @@ -628,6 +632,9 @@ OPTION(mds_max_scrub_ops_in_progress, OPT_INT, 5) // the number of simultaneous // Maximum number of damaged frags/dentries before whole MDS rank goes damaged OPTION(mds_damage_table_max_entries, OPT_INT, 10000) +// Maximum increment for client writable range, counted by number of objects +OPTION(mds_client_writeable_range_max_inc_objs, OPT_U32, 1024) + // verify backend can support configured max object name length OPTION(osd_check_max_object_name_len_on_startup, OPT_BOOL, true) @@ -677,12 +684,12 @@ OPTION(osd_client_message_size_cap, OPT_U64, 500*1024L*1024L) // client data all OPTION(osd_client_message_cap, OPT_U64, 100) // num client messages allowed in-memory OPTION(osd_pg_bits, OPT_INT, 6) // bits per osd OPTION(osd_pgp_bits, OPT_INT, 6) // bits per osd +OPTION(osd_crush_update_weight_set, OPT_BOOL, true) // update weight set while updating weights OPTION(osd_crush_chooseleaf_type, OPT_INT, 1) // 1 = host OPTION(osd_pool_use_gmt_hitset, OPT_BOOL, true) // try to use gmt for hitset archive names if all osds in cluster support it. OPTION(osd_crush_update_on_start, OPT_BOOL, true) OPTION(osd_crush_initial_weight, OPT_DOUBLE, -1) // if >=0, the initial weight is for newly added osds. -OPTION(osd_pool_default_crush_rule, OPT_INT, -1) // deprecated for osd_pool_default_crush_replicated_ruleset -OPTION(osd_pool_default_crush_replicated_ruleset, OPT_INT, CEPH_DEFAULT_CRUSH_REPLICATED_RULESET) +OPTION(osd_pool_default_crush_rule, OPT_INT, -1) OPTION(osd_pool_erasure_code_stripe_unit, OPT_U32, 4096) // in bytes OPTION(osd_pool_default_size, OPT_INT, 3) OPTION(osd_pool_default_min_size, OPT_INT, 0) // 0 means no specific default; ceph will use size-size/2 @@ -736,17 +743,17 @@ OPTION(osd_tier_default_cache_hit_set_grade_decay_rate, OPT_INT, 20) OPTION(osd_tier_default_cache_hit_set_search_last_n, OPT_INT, 1) OPTION(osd_map_dedup, OPT_BOOL, true) -OPTION(osd_map_max_advance, OPT_INT, 150) // make this < cache_size! -OPTION(osd_map_cache_size, OPT_INT, 200) -OPTION(osd_map_message_max, OPT_INT, 100) // max maps per MOSDMap message -OPTION(osd_map_share_max_epochs, OPT_INT, 100) // cap on # of inc maps we send to peers, clients +OPTION(osd_map_max_advance, OPT_INT, 40) // make this < cache_size! +OPTION(osd_map_cache_size, OPT_INT, 50) +OPTION(osd_map_message_max, OPT_INT, 40) // max maps per MOSDMap message +OPTION(osd_map_share_max_epochs, OPT_INT, 40) // cap on # of inc maps we send to peers, clients OPTION(osd_inject_bad_map_crc_probability, OPT_FLOAT, 0) OPTION(osd_inject_failure_on_pg_removal, OPT_BOOL, false) // shutdown the OSD if stuatus flipping more than max_markdown_count times in recent max_markdown_period seconds OPTION(osd_max_markdown_period , OPT_INT, 600) OPTION(osd_max_markdown_count, OPT_INT, 5) -OPTION(osd_op_threads, OPT_INT, 2) // 0 == no threading +OPTION(osd_peering_wq_threads, OPT_INT, 2) OPTION(osd_peering_wq_batch_size, OPT_U64, 20) OPTION(osd_op_pq_max_tokens_per_priority, OPT_U64, 4194304) OPTION(osd_op_pq_min_cost, OPT_U64, 65536) @@ -754,8 +761,12 @@ OPTION(osd_disk_threads, OPT_INT, 1) OPTION(osd_disk_thread_ioprio_class, OPT_STR, "") // rt realtime be best effort idle OPTION(osd_disk_thread_ioprio_priority, OPT_INT, -1) // 0-7 OPTION(osd_recover_clone_overlap, OPT_BOOL, true) // preserve clone_overlap during recovery/migration -OPTION(osd_op_num_threads_per_shard, OPT_INT, 2) -OPTION(osd_op_num_shards, OPT_INT, 5) +OPTION(osd_op_num_threads_per_shard, OPT_INT, 0) +OPTION(osd_op_num_threads_per_shard_hdd, OPT_INT, 1) +OPTION(osd_op_num_threads_per_shard_ssd, OPT_INT, 2) +OPTION(osd_op_num_shards, OPT_INT, 0) +OPTION(osd_op_num_shards_hdd, OPT_INT, 5) +OPTION(osd_op_num_shards_ssd, OPT_INT, 8) OPTION(osd_op_queue, OPT_STR, "wpq") // PrioritzedQueue (prio), Weighted Priority Queue (wpq), or debug_random OPTION(osd_op_queue_cut_off, OPT_STR, "low") // Min priority to go to strict queue. (low, high, debug_random) @@ -776,7 +787,7 @@ OPTION(osd_op_thread_timeout, OPT_INT, 15) OPTION(osd_op_thread_suicide_timeout, OPT_INT, 150) OPTION(osd_recovery_thread_timeout, OPT_INT, 30) OPTION(osd_recovery_thread_suicide_timeout, OPT_INT, 300) -OPTION(osd_recovery_sleep, OPT_FLOAT, 0) // seconds to sleep between recovery ops +OPTION(osd_recovery_sleep, OPT_FLOAT, 0.01) // seconds to sleep between recovery ops OPTION(osd_snap_trim_sleep, OPT_DOUBLE, 0) OPTION(osd_scrub_invalid_stats, OPT_BOOL, true) OPTION(osd_remove_thread_timeout, OPT_INT, 60*60) @@ -791,6 +802,7 @@ OPTION(osd_heartbeat_interval, OPT_INT, 6) // (seconds) how often we ping OPTION(osd_heartbeat_grace, OPT_INT, 20) OPTION(osd_heartbeat_min_peers, OPT_INT, 10) // minimum number of peers OPTION(osd_heartbeat_use_min_delay_socket, OPT_BOOL, false) // prio the heartbeat tcp socket and set dscp as CS6 on it if true +OPTION(osd_heartbeat_min_size, OPT_INT, 2000) // the minimum size of OSD heartbeat messages to send // max number of parallel snap trims/pg OPTION(osd_pg_max_concurrent_snap_trims, OPT_U64, 2) @@ -855,7 +867,7 @@ OPTION(osd_default_notify_timeout, OPT_U32, 30) // default notify timeout in sec OPTION(osd_kill_backfill_at, OPT_INT, 0) // Bounds how infrequently a new map epoch will be persisted for a pg -OPTION(osd_pg_epoch_persisted_max_stale, OPT_U32, 150) // make this < map_cache_size! +OPTION(osd_pg_epoch_persisted_max_stale, OPT_U32, 40) // make this < map_cache_size! OPTION(osd_min_pg_log_entries, OPT_U32, 3000) // number of entries to keep in the pg log when trimming it OPTION(osd_max_pg_log_entries, OPT_U32, 10000) // max entries, say when degraded, before we trim @@ -885,7 +897,6 @@ OPTION(osd_debug_reject_backfill_probability, OPT_DOUBLE, 0) OPTION(osd_debug_inject_copyfrom_error, OPT_BOOL, false) // inject failure during copyfrom completion OPTION(osd_debug_misdirected_ops, OPT_BOOL, false) OPTION(osd_debug_skip_full_check_in_recovery, OPT_BOOL, false) -OPTION(osd_enxio_on_misdirected_op, OPT_BOOL, false) OPTION(osd_debug_verify_cached_snaps, OPT_BOOL, false) OPTION(osd_enable_op_tracker, OPT_BOOL, true) // enable/disable OSD op tracking OPTION(osd_num_op_tracker_shard, OPT_U32, 32) // The number of shards for holding the ops @@ -899,6 +910,7 @@ OPTION(osd_fast_fail_on_connection_refused, OPT_BOOL, true) // immediately mark OPTION(osd_pg_object_context_cache_count, OPT_INT, 64) OPTION(osd_tracing, OPT_BOOL, false) // true if LTTng-UST tracepoints should be enabled +OPTION(osd_function_tracing, OPT_BOOL, false) // true if function instrumentation should use LTTng OPTION(osd_fast_info, OPT_BOOL, true) // use fast info attr, if we can @@ -932,7 +944,9 @@ OPTION(rocksdb_separate_wal_dir, OPT_BOOL, false) // use $path.wal for wal SAFE_OPTION(rocksdb_db_paths, OPT_STR, "") // path,size( path,size)* OPTION(rocksdb_log_to_ceph_log, OPT_BOOL, true) // log to ceph log OPTION(rocksdb_cache_size, OPT_U64, 128*1024*1024) // default rocksdb cache size +OPTION(rocksdb_cache_row_ratio, OPT_FLOAT, .2) // ratio of cache for row (vs block) OPTION(rocksdb_cache_shard_bits, OPT_INT, 4) // rocksdb block cache shard bits, 4 bit -> 16 shards +OPTION(rocksdb_cache_type, OPT_STR, "lru") // 'lru' or 'clock' OPTION(rocksdb_block_size, OPT_INT, 4*1024) // default rocksdb block size OPTION(rocksdb_perf, OPT_BOOL, false) // Enabling this will have 5-10% impact on performance for the stats collection OPTION(rocksdb_collect_compaction_stats, OPT_BOOL, false) //For rocksdb, this behavior will be an overhead of 5%~10%, collected only rocksdb_perf is enabled. @@ -978,8 +992,9 @@ OPTION(osd_recovery_op_warn_multiple, OPT_U32, 16) // Max time to wait between notifying mon of shutdown and shutting down OPTION(osd_mon_shutdown_timeout, OPT_DOUBLE, 5) +OPTION(osd_shutdown_pgref_assert, OPT_BOOL, false) // crash if the OSD has stray PG refs on shutdown -OPTION(osd_max_object_size, OPT_U64, 100*1024L*1024L*1024L) // OSD's maximum object size +OPTION(osd_max_object_size, OPT_U64, 128*1024L*1024L) // OSD's maximum object size OPTION(osd_max_object_name_len, OPT_U32, 2048) // max rados object name len OPTION(osd_max_object_namespace_len, OPT_U32, 256) // max rados object namespace len OPTION(osd_max_attr_name_len, OPT_U32, 100) // max rados attr name len; cannot go higher than 100 chars for file system backends @@ -990,9 +1005,6 @@ OPTION(osd_max_omap_bytes_per_request, OPT_U64, 1<<30) OPTION(osd_objectstore, OPT_STR, "filestore") // ObjectStore backend type OPTION(osd_objectstore_tracing, OPT_BOOL, false) // true if LTTng-UST tracepoints should be enabled -// Override maintaining compatibility with older OSDs -// Set to true for testing. Users should NOT set this. -OPTION(osd_debug_override_acting_compat, OPT_BOOL, false) OPTION(osd_objectstore_fuse, OPT_BOOL, false) OPTION(osd_bench_small_size_max_iops, OPT_U32, 100) // 100 IOPS @@ -1118,18 +1130,20 @@ OPTION(bluestore_extent_map_shard_target_size, OPT_U32, 500) OPTION(bluestore_extent_map_shard_min_size, OPT_U32, 150) OPTION(bluestore_extent_map_shard_target_size_slop, OPT_DOUBLE, .2) OPTION(bluestore_extent_map_inline_shard_prealloc_size, OPT_U32, 256) -OPTION(bluestore_cache_trim_interval, OPT_DOUBLE, .1) +OPTION(bluestore_cache_trim_interval, OPT_DOUBLE, .2) OPTION(bluestore_cache_trim_max_skip_pinned, OPT_U32, 64) // skip this many onodes pinned in cache before we give up OPTION(bluestore_cache_type, OPT_STR, "2q") // lru, 2q OPTION(bluestore_2q_cache_kin_ratio, OPT_DOUBLE, .5) // kin page slot size / max page slot size OPTION(bluestore_2q_cache_kout_ratio, OPT_DOUBLE, .5) // number of kout page slot / total number of page slot OPTION(bluestore_cache_size, OPT_U64, 1024*1024*1024) -OPTION(bluestore_cache_meta_ratio, OPT_DOUBLE, .9) +OPTION(bluestore_cache_meta_ratio, OPT_DOUBLE, .7) +OPTION(bluestore_cache_kv_ratio, OPT_DOUBLE, .2) OPTION(bluestore_kvbackend, OPT_STR, "rocksdb") OPTION(bluestore_allocator, OPT_STR, "bitmap") // stupid | bitmap OPTION(bluestore_freelist_blocks_per_key, OPT_INT, 128) OPTION(bluestore_bitmapallocator_blocks_per_zone, OPT_INT, 1024) // must be power of 2 aligned, e.g., 512, 1024, 2048... OPTION(bluestore_bitmapallocator_span_size, OPT_INT, 1024) // must be power of 2 aligned, e.g., 512, 1024, 2048... +OPTION(bluestore_max_deferred_txc, OPT_U64, 32) OPTION(bluestore_rocksdb_options, OPT_STR, "compression=kNoCompression,max_write_buffer_number=4,min_write_buffer_number_to_merge=1,recycle_log_file_num=4,write_buffer_size=268435456,writable_file_max_buffer_size=0,compaction_readahead_size=2097152") OPTION(bluestore_fsck_on_mount, OPT_BOOL, false) OPTION(bluestore_fsck_on_mount_deep, OPT_BOOL, true) @@ -1140,7 +1154,7 @@ OPTION(bluestore_fsck_on_mkfs_deep, OPT_BOOL, false) OPTION(bluestore_sync_submit_transaction, OPT_BOOL, false) // submit kv txn in queueing thread (not kv_sync_thread) OPTION(bluestore_throttle_bytes, OPT_U64, 64*1024*1024) OPTION(bluestore_throttle_deferred_bytes, OPT_U64, 128*1024*1024) -OPTION(bluestore_throttle_cost_per_io_hdd, OPT_U64, 1500000) +OPTION(bluestore_throttle_cost_per_io_hdd, OPT_U64, 670000) OPTION(bluestore_throttle_cost_per_io_ssd, OPT_U64, 4000) OPTION(bluestore_throttle_cost_per_io, OPT_U64, 0) OPTION(bluestore_deferred_batch_ops, OPT_U64, 0) @@ -1160,6 +1174,9 @@ OPTION(bluestore_debug_prefragment_max, OPT_INT, 1048576) OPTION(bluestore_debug_inject_read_err, OPT_BOOL, false) OPTION(bluestore_debug_randomize_serial_transaction, OPT_INT, 0) OPTION(bluestore_debug_omit_block_device_write, OPT_BOOL, false) +OPTION(bluestore_debug_fsck_abort, OPT_BOOL, false) +OPTION(bluestore_debug_omit_kv_commit, OPT_BOOL, false) +OPTION(bluestore_debug_permit_any_bdev_label, OPT_BOOL, false) OPTION(bluestore_shard_finishers, OPT_BOOL, false) OPTION(kstore_max_ops, OPT_U64, 512) @@ -1205,7 +1222,7 @@ OPTION(filestore_index_retry_probability, OPT_DOUBLE, 0) // Allow object read error injection OPTION(filestore_debug_inject_read_err, OPT_BOOL, false) -OPTION(filestore_debug_omap_check, OPT_BOOL, 0) // Expensive debugging check on sync +OPTION(filestore_debug_omap_check, OPT_BOOL, false) // Expensive debugging check on sync OPTION(filestore_omap_header_cache_size, OPT_INT, 1024) // Use omap for xattrs for attrs over @@ -1330,7 +1347,7 @@ OPTION(journal_discard, OPT_BOOL, false) //using ssd disk as journal, whether su OPTION(fio_dir, OPT_STR, "/tmp/fio") // fio data directory for fio-objectstore -OPTION(rados_mon_op_timeout, OPT_DOUBLE, 0) // how many seconds to wait for a response from the monitor before returning an error from a rados operation. 0 means on limit. +OPTION(rados_mon_op_timeout, OPT_DOUBLE, 0) // how many seconds to wait for a response from the monitor before returning an error from a rados operation. 0 means no limit. OPTION(rados_osd_op_timeout, OPT_DOUBLE, 0) // how many seconds to wait for a response from osds before returning an error from a rados operation. 0 means no limit. OPTION(rados_tracing, OPT_BOOL, false) // true if LTTng-UST tracepoints should be enabled @@ -1360,12 +1377,16 @@ OPTION(rbd_request_timed_out_seconds, OPT_INT, 30) // number of seconds before m OPTION(rbd_skip_partial_discard, OPT_BOOL, false) // when trying to discard a range inside an object, set to true to skip zeroing the range. OPTION(rbd_enable_alloc_hint, OPT_BOOL, true) // when writing a object, it will issue a hint to osd backend to indicate the expected size object need OPTION(rbd_tracing, OPT_BOOL, false) // true if LTTng-UST tracepoints should be enabled +OPTION(rbd_blkin_trace_all, OPT_BOOL, false) // create a blkin trace for all RBD requests OPTION(rbd_validate_pool, OPT_BOOL, true) // true if empty pools should be validated for RBD compatibility OPTION(rbd_validate_names, OPT_BOOL, true) // true if image specs should be validated OPTION(rbd_auto_exclusive_lock_until_manual_request, OPT_BOOL, true) // whether to automatically acquire/release exclusive lock until it is explicitly requested, i.e. before we know the user of librbd is properly using the lock API OPTION(rbd_mirroring_resync_after_disconnect, OPT_BOOL, false) // automatically start image resync after mirroring is disconnected due to being laggy OPTION(rbd_mirroring_replay_delay, OPT_INT, 0) // time-delay in seconds for rbd-mirror asynchronous replication +OPTION(rbd_default_pool, OPT_STR, "rbd") // default pool for storing images +OPTION_VALIDATOR(rbd_default_pool) + /* * The following options change the behavior for librbd's image creation methods that * don't require all of the parameters. These are provided so that older programs @@ -1387,6 +1408,7 @@ OPTION(rbd_default_order, OPT_INT, 22) OPTION(rbd_default_stripe_count, OPT_U64, 0) // changing requires stripingv2 feature OPTION(rbd_default_stripe_unit, OPT_U64, 0) // changing to non-object size requires stripingv2 feature OPTION(rbd_default_data_pool, OPT_STR, "") // optional default pool for storing image data blocks +OPTION_VALIDATOR(rbd_default_data_pool) /** * RBD features are only applicable for v2 images. This setting accepts either @@ -1545,6 +1567,7 @@ OPTION(rgw_op_thread_suicide_timeout, OPT_INT, 0) OPTION(rgw_thread_pool_size, OPT_INT, 100) OPTION(rgw_num_control_oids, OPT_INT, 8) OPTION(rgw_num_rados_handles, OPT_U32, 1) +OPTION(rgw_verify_ssl, OPT_BOOL, true) // should http_client try to verify ssl when sent https request /* The following are tunables for caches of RGW NFS (and other file * client) objects. @@ -1634,7 +1657,7 @@ OPTION(rgw_bucket_default_quota_max_size, OPT_LONGLONG, -1) // Max size of objec OPTION(rgw_expose_bucket, OPT_BOOL, false) // Return the bucket name in the 'Bucket' response header -OPTION(rgw_frontends, OPT_STR, "fastcgi, civetweb port=7480") // rgw front ends +OPTION(rgw_frontends, OPT_STR, "civetweb port=7480") // rgw front ends OPTION(rgw_user_quota_bucket_sync_interval, OPT_INT, 180) // time period for accumulating modified buckets before syncing stats OPTION(rgw_user_quota_sync_interval, OPT_INT, 3600 * 24) // time period for accumulating modified buckets before syncing entire user stats @@ -1679,10 +1702,10 @@ OPTION(rgw_shard_warning_threshold, OPT_DOUBLE, 90) // pct of safe max OPTION(rgw_swift_versioning_enabled, OPT_BOOL, false) // whether swift object versioning feature is enabled OPTION(mgr_module_path, OPT_STR, CEPH_PKGLIBDIR "/mgr") // where to load python modules from -OPTION(mgr_modules, OPT_STR, "rest") // Which modules to load +OPTION(mgr_modules, OPT_STR, "restful") // Which modules to load OPTION(mgr_data, OPT_STR, "/var/lib/ceph/mgr/$cluster-$id") // where to find keyring etc -OPTION(mgr_beacon_period, OPT_INT, 5) // How frequently to send beacon -OPTION(mgr_stats_period, OPT_INT, 5) // How frequently to send stats +OPTION(mgr_tick_period, OPT_INT, 2) // How frequently to tick +OPTION(mgr_stats_period, OPT_INT, 5) // How frequently clients send stats OPTION(mgr_client_bytes, OPT_U64, 128*1048576) // bytes from clients OPTION(mgr_client_messages, OPT_U64, 512) // messages from clients OPTION(mgr_osd_bytes, OPT_U64, 512*1048576) // bytes from osds @@ -1727,3 +1750,10 @@ OPTION(internal_safe_to_start_threads, OPT_BOOL, false) OPTION(debug_deliberately_leak_memory, OPT_BOOL, false) OPTION(rgw_swift_custom_header, OPT_STR, "") // option to enable swift custom headers + +/* resharding tunables */ +OPTION(rgw_reshard_num_logs, OPT_INT, 16) +OPTION(rgw_reshard_bucket_lock_duration, OPT_INT, 120) // duration of lock on bucket obj during resharding +OPTION(rgw_dynamic_resharding, OPT_BOOL, true) +OPTION(rgw_max_objs_per_shard, OPT_INT, 100000) +OPTION(rgw_reshard_thread_interval, OPT_U32, 60 * 10) // maximum time between rounds of reshard thread processing diff --git a/ceph/src/common/config_validators.cc b/ceph/src/common/config_validators.cc index 0f224f94b..ebd3eb37a 100644 --- a/ceph/src/common/config_validators.cc +++ b/ceph/src/common/config_validators.cc @@ -3,12 +3,30 @@ #include "common/config_validators.h" #include "include/stringify.h" -#include "include/rbd/features.h" -#include -#include -#include + #include #include +#include + +int validate(md_config_t::option_rbd_default_pool_t *, + std::string *value, std::string *error_message) { + boost::regex pattern("^[^@/]+$"); + if (!boost::regex_match (*value, pattern)) { + *value = "rbd"; + *error_message = "invalid RBD default pool, resetting to 'rbd'"; + } + return 0; +} + +int validate(md_config_t::option_rbd_default_data_pool_t *, + std::string *value, std::string *error_message) { + boost::regex pattern("^[^@/]*$"); + if (!boost::regex_match (*value, pattern)) { + *value = ""; + *error_message = "ignoring invalid RBD data pool"; + } + return 0; +} int validate(md_config_t::option_rbd_default_features_t *, std::string *value, std::string *error_message) { diff --git a/ceph/src/common/config_validators.h b/ceph/src/common/config_validators.h index 22cf6f086..f647369ec 100644 --- a/ceph/src/common/config_validators.h +++ b/ceph/src/common/config_validators.h @@ -11,6 +11,10 @@ * Global config value validators for the Ceph project */ +int validate(md_config_t::option_rbd_default_pool_t *type, + std::string *value, std::string *error_message); +int validate(md_config_t::option_rbd_default_data_pool_t *type, + std::string *value, std::string *error_message); int validate(md_config_t::option_rbd_default_features_t *type, std::string *value, std::string *error_message); diff --git a/ceph/src/common/crc32c.cc b/ceph/src/common/crc32c.cc index 5e857abb8..a30d38664 100644 --- a/ceph/src/common/crc32c.cc +++ b/ceph/src/common/crc32c.cc @@ -2,13 +2,11 @@ // vim: ts=8 sw=2 smarttab #include "include/crc32c.h" - #include "arch/probe.h" #include "arch/intel.h" #include "arch/arm.h" #include "arch/ppc.h" #include "common/sctp_crc32.h" -#include "common/crc32c_intel_baseline.h" #include "common/crc32c_intel_fast.h" #include "common/crc32c_aarch64.h" #include "common/crc32c_ppc.h" @@ -52,3 +50,189 @@ ceph_crc32c_func_t ceph_choose_crc32(void) */ ceph_crc32c_func_t ceph_crc32c_func = ceph_choose_crc32(); + +/* + * Look: http://crcutil.googlecode.com/files/crc-doc.1.0.pdf + * Here is implementation that goes 1 logical step further, + * it splits calculating CRC into jumps of length 1, 2, 4, 8, .... + * Each jump is performed on single input bit separately, xor-ed after that. + * + * This function is unused. It is here to show how crc_turbo_table was obtained. + */ +void create_turbo_table(uint32_t table[32][32]) +{ + //crc_turbo_struct table; + for (int bit = 0 ; bit < 32 ; bit++) { + table[0][bit] = ceph_crc32c_sctp(1UL << bit, nullptr, 1); + } + for (int range = 1; range <32 ; range++) { + for (int bit = 0 ; bit < 32 ; bit++) { + uint32_t crc_x = table[range-1][bit]; + uint32_t crc_y = 0; + for (int b = 0 ; b < 32 ; b++) { + if ( (crc_x & (1UL << b)) != 0 ) { + crc_y = crc_y ^ table[range-1][b]; + } + } + table[range][bit] = crc_y; + } + } +} + +static uint32_t crc_turbo_table[32][32] = +{ + {0xf26b8303, 0xe13b70f7, 0xc79a971f, 0x8ad958cf, 0x105ec76f, 0x20bd8ede, 0x417b1dbc, 0x82f63b78, + 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000}, + {0x13a29877, 0x274530ee, 0x4e8a61dc, 0x9d14c3b8, 0x3fc5f181, 0x7f8be302, 0xff17c604, 0xfbc3faf9, + 0xf26b8303, 0xe13b70f7, 0xc79a971f, 0x8ad958cf, 0x105ec76f, 0x20bd8ede, 0x417b1dbc, 0x82f63b78, + 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000}, + {0xdd45aab8, 0xbf672381, 0x7b2231f3, 0xf64463e6, 0xe964b13d, 0xd725148b, 0xaba65fe7, 0x52a0c93f, + 0xa541927e, 0x4f6f520d, 0x9edea41a, 0x38513ec5, 0x70a27d8a, 0xe144fb14, 0xc76580d9, 0x8b277743, + 0x13a29877, 0x274530ee, 0x4e8a61dc, 0x9d14c3b8, 0x3fc5f181, 0x7f8be302, 0xff17c604, 0xfbc3faf9, + 0xf26b8303, 0xe13b70f7, 0xc79a971f, 0x8ad958cf, 0x105ec76f, 0x20bd8ede, 0x417b1dbc, 0x82f63b78}, + {0x493c7d27, 0x9278fa4e, 0x211d826d, 0x423b04da, 0x847609b4, 0x0d006599, 0x1a00cb32, 0x34019664, + 0x68032cc8, 0xd0065990, 0xa5e0c5d1, 0x4e2dfd53, 0x9c5bfaa6, 0x3d5b83bd, 0x7ab7077a, 0xf56e0ef4, + 0xef306b19, 0xdb8ca0c3, 0xb2f53777, 0x6006181f, 0xc00c303e, 0x85f4168d, 0x0e045beb, 0x1c08b7d6, + 0x38116fac, 0x7022df58, 0xe045beb0, 0xc5670b91, 0x8f2261d3, 0x1ba8b557, 0x37516aae, 0x6ea2d55c}, + {0xf20c0dfe, 0xe1f46d0d, 0xc604aceb, 0x89e52f27, 0x162628bf, 0x2c4c517e, 0x5898a2fc, 0xb13145f8, + 0x678efd01, 0xcf1dfa02, 0x9bd782f5, 0x3243731b, 0x6486e636, 0xc90dcc6c, 0x97f7ee29, 0x2a03aaa3, + 0x54075546, 0xa80eaa8c, 0x55f123e9, 0xabe247d2, 0x5228f955, 0xa451f2aa, 0x4d4f93a5, 0x9a9f274a, + 0x30d23865, 0x61a470ca, 0xc348e194, 0x837db5d9, 0x03171d43, 0x062e3a86, 0x0c5c750c, 0x18b8ea18}, + {0x3da6d0cb, 0x7b4da196, 0xf69b432c, 0xe8daf0a9, 0xd45997a3, 0xad5f59b7, 0x5f52c59f, 0xbea58b3e, + 0x78a7608d, 0xf14ec11a, 0xe771f4c5, 0xcb0f9f7b, 0x93f34807, 0x220ae6ff, 0x4415cdfe, 0x882b9bfc, + 0x15bb4109, 0x2b768212, 0x56ed0424, 0xadda0848, 0x5e586661, 0xbcb0ccc2, 0x7c8def75, 0xf91bdeea, + 0xf7dbcb25, 0xea5be0bb, 0xd15bb787, 0xa75b19ff, 0x4b5a450f, 0x96b48a1e, 0x288562cd, 0x510ac59a}, + {0x740eef02, 0xe81dde04, 0xd5d7caf9, 0xae43e303, 0x596bb0f7, 0xb2d761ee, 0x6042b52d, 0xc0856a5a, + 0x84e6a245, 0x0c21327b, 0x184264f6, 0x3084c9ec, 0x610993d8, 0xc21327b0, 0x81ca3991, 0x067805d3, + 0x0cf00ba6, 0x19e0174c, 0x33c02e98, 0x67805d30, 0xcf00ba60, 0x9bed0231, 0x32367293, 0x646ce526, + 0xc8d9ca4c, 0x945fe269, 0x2d53b223, 0x5aa76446, 0xb54ec88c, 0x6f71e7e9, 0xdee3cfd2, 0xb82be955}, + {0x6992cea2, 0xd3259d44, 0xa3a74c79, 0x42a2ee03, 0x8545dc06, 0x0f67cefd, 0x1ecf9dfa, 0x3d9f3bf4, + 0x7b3e77e8, 0xf67cefd0, 0xe915a951, 0xd7c72453, 0xaa623e57, 0x51280a5f, 0xa25014be, 0x414c5f8d, + 0x8298bf1a, 0x00dd08c5, 0x01ba118a, 0x03742314, 0x06e84628, 0x0dd08c50, 0x1ba118a0, 0x37423140, + 0x6e846280, 0xdd08c500, 0xbffdfcf1, 0x7a178f13, 0xf42f1e26, 0xedb24abd, 0xde88e38b, 0xb8fdb1e7}, + {0xdcb17aa4, 0xbc8e83b9, 0x7cf17183, 0xf9e2e306, 0xf629b0fd, 0xe9bf170b, 0xd69258e7, 0xa8c8c73f, + 0x547df88f, 0xa8fbf11e, 0x541b94cd, 0xa837299a, 0x558225c5, 0xab044b8a, 0x53e4e1e5, 0xa7c9c3ca, + 0x4a7ff165, 0x94ffe2ca, 0x2c13b365, 0x582766ca, 0xb04ecd94, 0x6571edd9, 0xcae3dbb2, 0x902bc195, + 0x25bbf5db, 0x4b77ebb6, 0x96efd76c, 0x2833d829, 0x5067b052, 0xa0cf60a4, 0x4472b7b9, 0x88e56f72}, + {0xbd6f81f8, 0x7f337501, 0xfe66ea02, 0xf921a2f5, 0xf7af331b, 0xeab210c7, 0xd088577f, 0xa4fcd80f, + 0x4c15c6ef, 0x982b8dde, 0x35bb6d4d, 0x6b76da9a, 0xd6edb534, 0xa8371c99, 0x55824fc3, 0xab049f86, + 0x53e549fd, 0xa7ca93fa, 0x4a795105, 0x94f2a20a, 0x2c0932e5, 0x581265ca, 0xb024cb94, 0x65a5e1d9, + 0xcb4bc3b2, 0x937bf195, 0x231b95db, 0x46372bb6, 0x8c6e576c, 0x1d30d829, 0x3a61b052, 0x74c360a4}, + {0xfe314258, 0xf98ef241, 0xf6f19273, 0xe80f5217, 0xd5f2d2df, 0xae09d34f, 0x59ffd06f, 0xb3ffa0de, + 0x6213374d, 0xc4266e9a, 0x8da0abc5, 0x1ead217b, 0x3d5a42f6, 0x7ab485ec, 0xf5690bd8, 0xef3e6141, + 0xdb90b473, 0xb2cd1e17, 0x60764adf, 0xc0ec95be, 0x84355d8d, 0x0d86cdeb, 0x1b0d9bd6, 0x361b37ac, + 0x6c366f58, 0xd86cdeb0, 0xb535cb91, 0x6f87e1d3, 0xdf0fc3a6, 0xbbf3f1bd, 0x720b958b, 0xe4172b16}, + {0xf7506984, 0xeb4ca5f9, 0xd3753d03, 0xa3060cf7, 0x43e06f1f, 0x87c0de3e, 0x0a6dca8d, 0x14db951a, + 0x29b72a34, 0x536e5468, 0xa6dca8d0, 0x48552751, 0x90aa4ea2, 0x24b8ebb5, 0x4971d76a, 0x92e3aed4, + 0x202b2b59, 0x405656b2, 0x80acad64, 0x04b52c39, 0x096a5872, 0x12d4b0e4, 0x25a961c8, 0x4b52c390, + 0x96a58720, 0x28a778b1, 0x514ef162, 0xa29de2c4, 0x40d7b379, 0x81af66f2, 0x06b2bb15, 0x0d65762a}, + {0xc2a5b65e, 0x80a71a4d, 0x04a2426b, 0x094484d6, 0x128909ac, 0x25121358, 0x4a2426b0, 0x94484d60, + 0x2d7cec31, 0x5af9d862, 0xb5f3b0c4, 0x6e0b1779, 0xdc162ef2, 0xbdc02b15, 0x7e6c20db, 0xfcd841b6, + 0xfc5cf59d, 0xfd559dcb, 0xff474d67, 0xfb62ec3f, 0xf329ae8f, 0xe3bf2bef, 0xc292212f, 0x80c834af, + 0x047c1faf, 0x08f83f5e, 0x11f07ebc, 0x23e0fd78, 0x47c1faf0, 0x8f83f5e0, 0x1aeb9d31, 0x35d73a62}, + {0xe040e0ac, 0xc56db7a9, 0x8f3719a3, 0x1b8245b7, 0x37048b6e, 0x6e0916dc, 0xdc122db8, 0xbdc82d81, + 0x7e7c2df3, 0xfcf85be6, 0xfc1cc13d, 0xfdd5f48b, 0xfe479fe7, 0xf963493f, 0xf72ae48f, 0xebb9bfef, + 0xd29f092f, 0xa0d264af, 0x4448bfaf, 0x88917f5e, 0x14ce884d, 0x299d109a, 0x533a2134, 0xa6744268, + 0x4904f221, 0x9209e442, 0x21ffbe75, 0x43ff7cea, 0x87fef9d4, 0x0a118559, 0x14230ab2, 0x28461564}, + {0xc7cacead, 0x8a79ebab, 0x111fa1a7, 0x223f434e, 0x447e869c, 0x88fd0d38, 0x14166c81, 0x282cd902, + 0x5059b204, 0xa0b36408, 0x448abee1, 0x89157dc2, 0x17c68d75, 0x2f8d1aea, 0x5f1a35d4, 0xbe346ba8, + 0x7984a1a1, 0xf3094342, 0xe3fef075, 0xc211961b, 0x81cf5ac7, 0x0672c37f, 0x0ce586fe, 0x19cb0dfc, + 0x33961bf8, 0x672c37f0, 0xce586fe0, 0x995ca931, 0x37552493, 0x6eaa4926, 0xdd54924c, 0xbf455269}, + {0x04fcdcbf, 0x09f9b97e, 0x13f372fc, 0x27e6e5f8, 0x4fcdcbf0, 0x9f9b97e0, 0x3adb5931, 0x75b6b262, + 0xeb6d64c4, 0xd336bf79, 0xa3810803, 0x42ee66f7, 0x85dccdee, 0x0e55ed2d, 0x1cabda5a, 0x3957b4b4, + 0x72af6968, 0xe55ed2d0, 0xcf51d351, 0x9b4fd053, 0x3373d657, 0x66e7acae, 0xcdcf595c, 0x9e72c449, + 0x3909fe63, 0x7213fcc6, 0xe427f98c, 0xcda385e9, 0x9eab7d23, 0x38ba8cb7, 0x7175196e, 0xe2ea32dc}, + {0x6bafcc21, 0xd75f9842, 0xab534675, 0x534afa1b, 0xa695f436, 0x48c79e9d, 0x918f3d3a, 0x26f20c85, + 0x4de4190a, 0x9bc83214, 0x327c12d9, 0x64f825b2, 0xc9f04b64, 0x960ce039, 0x29f5b683, 0x53eb6d06, + 0xa7d6da0c, 0x4a41c2e9, 0x948385d2, 0x2ceb7d55, 0x59d6faaa, 0xb3adf554, 0x62b79c59, 0xc56f38b2, + 0x8f320795, 0x1b8879db, 0x3710f3b6, 0x6e21e76c, 0xdc43ced8, 0xbd6beb41, 0x7f3ba073, 0xfe7740e6}, + {0x140441c6, 0x2808838c, 0x50110718, 0xa0220e30, 0x45a86a91, 0x8b50d522, 0x134ddcb5, 0x269bb96a, + 0x4d3772d4, 0x9a6ee5a8, 0x3131bda1, 0x62637b42, 0xc4c6f684, 0x8c619bf9, 0x1d2f4103, 0x3a5e8206, + 0x74bd040c, 0xe97a0818, 0xd71866c1, 0xabdcbb73, 0x52550017, 0xa4aa002e, 0x4cb876ad, 0x9970ed5a, + 0x370dac45, 0x6e1b588a, 0xdc36b114, 0xbd8114d9, 0x7eee5f43, 0xfddcbe86, 0xfe550bfd, 0xf946610b}, + {0x68175a0a, 0xd02eb414, 0xa5b11ed9, 0x4e8e4b43, 0x9d1c9686, 0x3fd55bfd, 0x7faab7fa, 0xff556ff4, + 0xfb46a919, 0xf36124c3, 0xe32e3f77, 0xc3b0081f, 0x828c66cf, 0x00f4bb6f, 0x01e976de, 0x03d2edbc, + 0x07a5db78, 0x0f4bb6f0, 0x1e976de0, 0x3d2edbc0, 0x7a5db780, 0xf4bb6f00, 0xec9aa8f1, 0xdcd92713, + 0xbc5e38d7, 0x7d50075f, 0xfaa00ebe, 0xf0ac6b8d, 0xe4b4a1eb, 0xcc853527, 0x9ce61cbf, 0x3c204f8f}, + {0xe1ff3667, 0xc6121a3f, 0x89c8428f, 0x167cf3ef, 0x2cf9e7de, 0x59f3cfbc, 0xb3e79f78, 0x62234801, + 0xc4469002, 0x8d6156f5, 0x1f2edb1b, 0x3e5db636, 0x7cbb6c6c, 0xf976d8d8, 0xf701c741, 0xebeff873, + 0xd2338617, 0xa18b7adf, 0x46fa834f, 0x8df5069e, 0x1e067bcd, 0x3c0cf79a, 0x7819ef34, 0xf033de68, + 0xe58bca21, 0xcefbe2b3, 0x981bb397, 0x35db11df, 0x6bb623be, 0xd76c477c, 0xab34f809, 0x538586e3}, + {0x8b7230ec, 0x13081729, 0x26102e52, 0x4c205ca4, 0x9840b948, 0x356d0461, 0x6ada08c2, 0xd5b41184, + 0xae8455f9, 0x58e4dd03, 0xb1c9ba06, 0x667f02fd, 0xccfe05fa, 0x9c107d05, 0x3dcc8cfb, 0x7b9919f6, + 0xf73233ec, 0xeb881129, 0xd2fc54a3, 0xa014dfb7, 0x45c5c99f, 0x8b8b933e, 0x12fb508d, 0x25f6a11a, + 0x4bed4234, 0x97da8468, 0x2a597e21, 0x54b2fc42, 0xa965f884, 0x572787f9, 0xae4f0ff2, 0x59726915}, + {0x56175f20, 0xac2ebe40, 0x5db10a71, 0xbb6214e2, 0x73285f35, 0xe650be6a, 0xc94d0a25, 0x977662bb, + 0x2b00b387, 0x5601670e, 0xac02ce1c, 0x5de9eac9, 0xbbd3d592, 0x724bddd5, 0xe497bbaa, 0xccc301a5, + 0x9c6a75bb, 0x3d389d87, 0x7a713b0e, 0xf4e2761c, 0xec289ac9, 0xddbd4363, 0xbe96f037, 0x78c1969f, + 0xf1832d3e, 0xe6ea2c8d, 0xc8382feb, 0x959c2927, 0x2ed424bf, 0x5da8497e, 0xbb5092fc, 0x734d5309}, + {0xb9a3dcd0, 0x76abcf51, 0xed579ea2, 0xdf434bb5, 0xbb6ae19b, 0x7339b5c7, 0xe6736b8e, 0xc90aa1ed, + 0x97f9352b, 0x2a1e1ca7, 0x543c394e, 0xa878729c, 0x551c93c9, 0xaa392792, 0x519e39d5, 0xa33c73aa, + 0x439491a5, 0x8729234a, 0x0bbe3065, 0x177c60ca, 0x2ef8c194, 0x5df18328, 0xbbe30650, 0x722a7a51, + 0xe454f4a2, 0xcd459fb5, 0x9f67499b, 0x3b22e5c7, 0x7645cb8e, 0xec8b971c, 0xdcfb58c9, 0xbc1ac763}, + {0xdd2d789e, 0xbfb687cd, 0x7a81796b, 0xf502f2d6, 0xefe9935d, 0xda3f504b, 0xb192d667, 0x66c9da3f, + 0xcd93b47e, 0x9ecb1e0d, 0x387a4aeb, 0x70f495d6, 0xe1e92bac, 0xc63e21a9, 0x899035a3, 0x16cc1db7, + 0x2d983b6e, 0x5b3076dc, 0xb660edb8, 0x692dad81, 0xd25b5b02, 0xa15ac0f5, 0x4759f71b, 0x8eb3ee36, + 0x188baa9d, 0x3117553a, 0x622eaa74, 0xc45d54e8, 0x8d56df21, 0x1f41c8b3, 0x3e839166, 0x7d0722cc}, + {0x44036c4a, 0x8806d894, 0x15e1c7d9, 0x2bc38fb2, 0x57871f64, 0xaf0e3ec8, 0x5bf00b61, 0xb7e016c2, + 0x6a2c5b75, 0xd458b6ea, 0xad5d1b25, 0x5f5640bb, 0xbeac8176, 0x78b5741d, 0xf16ae83a, 0xe739a685, + 0xcb9f3bfb, 0x92d20107, 0x204874ff, 0x4090e9fe, 0x8121d3fc, 0x07afd109, 0x0f5fa212, 0x1ebf4424, + 0x3d7e8848, 0x7afd1090, 0xf5fa2120, 0xee1834b1, 0xd9dc1f93, 0xb65449d7, 0x6944e55f, 0xd289cabe}, + {0x4612657d, 0x8c24cafa, 0x1da5e305, 0x3b4bc60a, 0x76978c14, 0xed2f1828, 0xdfb246a1, 0xba88fbb3, + 0x70fd8197, 0xe1fb032e, 0xc61a70ad, 0x89d897ab, 0x165d59a7, 0x2cbab34e, 0x5975669c, 0xb2eacd38, + 0x6039ec81, 0xc073d902, 0x850bc4f5, 0x0ffbff1b, 0x1ff7fe36, 0x3feffc6c, 0x7fdff8d8, 0xffbff1b0, + 0xfa939591, 0xf0cb5dd3, 0xe47acd57, 0xcd19ec5f, 0x9fdfae4f, 0x3a532a6f, 0x74a654de, 0xe94ca9bc}, + {0x584d5569, 0xb09aaad2, 0x64d92355, 0xc9b246aa, 0x9688fba5, 0x28fd81bb, 0x51fb0376, 0xa3f606ec, + 0x42007b29, 0x8400f652, 0x0ded9a55, 0x1bdb34aa, 0x37b66954, 0x6f6cd2a8, 0xded9a550, 0xb85f3c51, + 0x75520e53, 0xeaa41ca6, 0xd0a44fbd, 0xa4a4e98b, 0x4ca5a5e7, 0x994b4bce, 0x377ae16d, 0x6ef5c2da, + 0xddeb85b4, 0xbe3b7d99, 0x799a8dc3, 0xf3351b86, 0xe38641fd, 0xc2e0f50b, 0x802d9ce7, 0x05b74f3f}, + {0xe8cd33e2, 0xd4761135, 0xad00549b, 0x5fecdfc7, 0xbfd9bf8e, 0x7a5f09ed, 0xf4be13da, 0xec905145, + 0xdcccd47b, 0xbc75de07, 0x7d07caff, 0xfa0f95fe, 0xf1f35d0d, 0xe60acceb, 0xc9f9ef27, 0x961fa8bf, + 0x29d3278f, 0x53a64f1e, 0xa74c9e3c, 0x4b754a89, 0x96ea9512, 0x28395cd5, 0x5072b9aa, 0xa0e57354, + 0x44269059, 0x884d20b2, 0x15763795, 0x2aec6f2a, 0x55d8de54, 0xabb1bca8, 0x528f0fa1, 0xa51e1f42}, + {0x82f63b78, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, + 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, + 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, + 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000}, + {0x417b1dbc, 0x82f63b78, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, + 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, + 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, + 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000}, + {0x105ec76f, 0x20bd8ede, 0x417b1dbc, 0x82f63b78, 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000}, + {0xf26b8303, 0xe13b70f7, 0xc79a971f, 0x8ad958cf, 0x105ec76f, 0x20bd8ede, 0x417b1dbc, 0x82f63b78, + 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000} +}; + +uint32_t ceph_crc32c_zeros(uint32_t crc, unsigned len) +{ + int range = 0; + unsigned remainder = len & 15; + len = len >> 4; + range = 4; + while (len != 0) { + uint32_t crc1 = 0; + if ((len & 1) == 1) { + uint32_t* ptr = crc_turbo_table/*.val*/[range]; + while (crc != 0) { + uint32_t mask = ~((crc & 1) - 1); + crc1 = crc1 ^ (mask & *ptr); + crc = crc >> 1; + ptr++; + } + crc = crc1; + } + len = len >> 1; + range++; + } + if (remainder > 0) + crc = ceph_crc32c(crc, nullptr, remainder); + return crc; +} diff --git a/ceph/src/common/crc32c_aarch64.h b/ceph/src/common/crc32c_aarch64.h index 3727f545c..51f0542fe 100644 --- a/ceph/src/common/crc32c_aarch64.h +++ b/ceph/src/common/crc32c_aarch64.h @@ -1,6 +1,7 @@ #ifndef CEPH_COMMON_CRC32C_AARCH64_H #define CEPH_COMMON_CRC32C_AARCH64_H +#include "acconfig.h" #include "arch/arm.h" #ifdef __cplusplus diff --git a/ceph/src/common/crc32c_intel_fast.c b/ceph/src/common/crc32c_intel_fast.c index af081a994..adaf3d777 100644 --- a/ceph/src/common/crc32c_intel_fast.c +++ b/ceph/src/common/crc32c_intel_fast.c @@ -1,5 +1,4 @@ #include "acconfig.h" -#include "include/int_types.h" #include "common/crc32c_intel_baseline.h" extern unsigned int crc32_iscsi_00(unsigned char const *buffer, int len, unsigned int crc); @@ -12,9 +11,10 @@ uint32_t ceph_crc32c_intel_fast(uint32_t crc, unsigned char const *buffer, unsig uint32_t v; unsigned left; - if (!buffer) - return crc32_iscsi_zero_00(buffer, len, crc); + { + return crc32_iscsi_zero_00(buffer, len, crc); + } /* * the crc32_iscsi_00 method reads past buffer+len (because it diff --git a/ceph/src/common/crc32c_intel_fast_asm.S b/ceph/src/common/crc32c_intel_fast_asm.s similarity index 100% rename from ceph/src/common/crc32c_intel_fast_asm.S rename to ceph/src/common/crc32c_intel_fast_asm.s diff --git a/ceph/src/common/crc32c_intel_fast_zero_asm.S b/ceph/src/common/crc32c_intel_fast_zero_asm.s similarity index 100% rename from ceph/src/common/crc32c_intel_fast_zero_asm.S rename to ceph/src/common/crc32c_intel_fast_zero_asm.s diff --git a/ceph/src/common/crc32c_ppc.c b/ceph/src/common/crc32c_ppc.c index e113ad8e1..43756e24e 100644 --- a/ceph/src/common/crc32c_ppc.c +++ b/ceph/src/common/crc32c_ppc.c @@ -7,9 +7,12 @@ * 2 of the License, or (at your option) any later version. */ #define CRC_TABLE +#define FAST_ZERO_TABLE + #include "acconfig.h" #include "include/int_types.h" #include "crc32c_ppc_constants.h" +#include "reverse.h" #include #include @@ -35,8 +38,38 @@ static unsigned int crc32_align(unsigned int crc, unsigned char const *p, } #endif - #ifdef HAVE_POWER8 +static inline unsigned long polynomial_multiply(unsigned int a, unsigned int b) { + vector unsigned int va = {a, 0, 0, 0}; + vector unsigned int vb = {b, 0, 0, 0}; + vector unsigned long vt; + + __asm__("vpmsumw %0,%1,%2" : "=v"(vt) : "v"(va), "v"(vb)); + + return vt[0]; +} + +unsigned int barrett_reduction(unsigned long val); + +static inline unsigned int gf_multiply(unsigned int a, unsigned int b) { + return barrett_reduction(polynomial_multiply(a, b)); +} + +unsigned int append_zeros(unsigned int crc, unsigned long length) { + unsigned long i = 0; + + while (length) { + if (length & 1) { + crc = gf_multiply(crc, crc_zero[i]); + } + i++; + length /= 2; + } + + return crc; +} + + unsigned int __crc32_vpmsum(unsigned int crc, unsigned char const *p, unsigned long len); @@ -79,19 +112,23 @@ out: } /* This wrapper function works around the fact that crc32_vpmsum - * does not gracefully handle the case where the data pointer is NULL. There - * may be room for performance improvement here. + * does not gracefully handle the case where the data pointer is NULL. */ uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len) { - unsigned char *buf2; - if (!data) { - buf2 = malloc(len); - bzero(buf2, len); - crc = crc32_vpmsum(crc, buf2, len); - free(buf2); + /* Handle the NULL buffer case. */ +#ifdef REFLECT + crc = reverse_bits(crc); +#endif + + crc = append_zeros(crc, len); + +#ifdef REFLECT + crc = reverse_bits(crc); +#endif } else { + /* Handle the valid buffer case. */ crc = crc32_vpmsum(crc, data, (unsigned long)len); } return crc; diff --git a/ceph/src/common/crc32c_ppc_constants.h b/ceph/src/common/crc32c_ppc_constants.h index 25864f104..12a1e1d51 100644 --- a/ceph/src/common/crc32c_ppc_constants.h +++ b/ceph/src/common/crc32c_ppc_constants.h @@ -78,6 +78,77 @@ static const unsigned int crc_table[] = { 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,}; #endif + +#ifdef FAST_ZERO_TABLE +/* fast zero table */ +unsigned int crc_zero[] = { + 0x100, + 0x10000, + 0x1edc6f41, + 0x3aab4576, + 0x18571d18, + 0x59a3508a, + 0xaa97d41d, + 0xe78dbf1d, + 0x4ef6a711, + 0x2506c32e, + 0x68d4e827, + 0x546ea6b0, + 0x465cebac, + 0x26a86214, + 0x964aa2fd, + 0x3b4c5747, + 0x6702ee7f, + 0xd086629f, + 0xf1f2043c, + 0xc761a1ca, + 0xa8964e9a, + 0x90cab2ce, + 0xc6e3583d, + 0x3344e0be, + 0x7d53914b, + 0x3d953297, + 0xfcf2eda0, + 0x42f878a5, + 0x2, + 0x4, + 0x10, + 0x100, + 0x10000, + 0x1edc6f41, + 0x3aab4576, + 0x18571d18, + 0x59a3508a, + 0xaa97d41d, + 0xe78dbf1d, + 0x4ef6a711, + 0x2506c32e, + 0x68d4e827, + 0x546ea6b0, + 0x465cebac, + 0x26a86214, + 0x964aa2fd, + 0x3b4c5747, + 0x6702ee7f, + 0xd086629f, + 0xf1f2043c, + 0xc761a1ca, + 0xa8964e9a, + 0x90cab2ce, + 0xc6e3583d, + 0x3344e0be, + 0x7d53914b, + 0x3d953297, + 0xfcf2eda0, + 0x42f878a5, + 0x2, + 0x4, + 0x10, + 0x100, + 0x10000 +}; +#endif + #else #define MAX_SIZE 32768 .constants: diff --git a/ceph/src/common/crc32c_ppc_fast_zero_asm.S b/ceph/src/common/crc32c_ppc_fast_zero_asm.S new file mode 100644 index 000000000..a53df1dee --- /dev/null +++ b/ceph/src/common/crc32c_ppc_fast_zero_asm.S @@ -0,0 +1,77 @@ +/* + * Use the fixed point version of Barrett reduction to compute a mod n + * over GF(2) for given n using POWER8 instructions. We use k = 32. + * + * http://en.wikipedia.org/wiki/Barrett_reduction + * + * Copyright (C) 2015 Anton Blanchard , IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of either: + * + * a) the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version, or + * b) the Apache License, Version 2.0 + */ +#include +#include "common/ppc-opcode.h" + +#undef toc + +#ifndef r1 +#define r1 1 +#endif + +#ifndef r2 +#define r2 2 +#endif + + .section .data +.balign 16 + +.barrett_fz_constants: + /* Barrett constant m - (4^32)/n */ + .octa 0x0000000000000000000000011f91caf6 /* x^64 div p(x) */ + /* Barrett constant n */ + .octa 0x0000000000000000000000011edc6f41 + +.text +/* unsigned int barrett_reduction(unsigned long val) */ +FUNC_START(barrett_reduction) + addis r4,r2,.barrett_fz_constants@toc@ha + addi r4,r4,.barrett_fz_constants@toc@l + + li r5,16 + vxor v1,v1,v1 /* zero v1 */ + + /* Get a into v0 */ + MTVRD(v0, r3) + vsldoi v0,v1,v0,8 /* shift into bottom 64 bits, this is a */ + + /* Load constants */ + lvx v2,0,r4 /* m */ + lvx v3,r5,r4 /* n */ + + /* + * Now for the actual algorithm. The idea is to calculate q, + * the multiple of our polynomial that we need to subtract. By + * doing the computation 2x bits higher (ie 64 bits) and shifting the + * result back down 2x bits, we round down to the nearest multiple. + */ + VPMSUMD(v4,v0,v2) /* ma */ + vsldoi v4,v1,v4,8 /* q = floor(ma/(2^64)) */ + VPMSUMD(v4,v4,v3) /* qn */ + vxor v0,v0,v4 /* a - qn, subtraction is xor in GF(2) */ + + /* + * Get the result into r3. We need to shift it left 8 bytes: + * V0 [ 0 1 2 X ] + * V0 [ 0 X 2 3 ] + */ + vsldoi v0,v0,v1,8 /* shift result into top 64 bits of v0 */ + MFVRD(r3, v0) + + blr +FUNC_END(barrett_reduction) + diff --git a/ceph/src/common/darwin_errno.cc b/ceph/src/common/darwin_errno.cc index 48372d090..4409abcd4 100644 --- a/ceph/src/common/darwin_errno.cc +++ b/ceph/src/common/darwin_errno.cc @@ -18,7 +18,7 @@ // converts from linux errno values to host values -__s32 ceph_to_host_errno(__s32 r) +__s32 ceph_to_hostos_errno(__s32 r) { if (r < -34) { switch (r) { @@ -222,3 +222,12 @@ __s32 ceph_to_host_errno(__s32 r) } return r; // otherwise return original value } + +// converts Host OS errno values to linux/Ceph values +// XXX Currently not worked out +__s32 hostos_to_ceph_errno(__s32 r) +{ + return r; +} + + diff --git a/ceph/src/common/deleter.h b/ceph/src/common/deleter.h index a13cf1f92..767ef4b1c 100644 --- a/ceph/src/common/deleter.h +++ b/ceph/src/common/deleter.h @@ -23,11 +23,6 @@ #define CEPH_COMMON_DELETER_H #include -#include -#include -#include - -#include "include/assert.h" /// \addtogroup memory-module /// @{ diff --git a/ceph/src/common/dns_resolve.cc b/ceph/src/common/dns_resolve.cc index 77f5b5294..3227c88e2 100644 --- a/ceph/src/common/dns_resolve.cc +++ b/ceph/src/common/dns_resolve.cc @@ -12,18 +12,10 @@ * */ -#include -#include -#include #include -#include #include "dns_resolve.h" - -#include "acconfig.h" #include "common/debug.h" -#include "msg/msg_types.h" - #define dout_subsys ceph_subsys_ diff --git a/ceph/src/common/dns_resolve.h b/ceph/src/common/dns_resolve.h index dbcc79a7b..3e8f7e463 100644 --- a/ceph/src/common/dns_resolve.h +++ b/ceph/src/common/dns_resolve.h @@ -14,13 +14,10 @@ #ifndef CEPH_DNS_RESOLVE_H #define CEPH_DNS_RESOLVE_H -#include -#include #include #include #include "common/Mutex.h" -#include "common/ceph_context.h" struct entity_addr_t; diff --git a/ceph/src/common/dout.h b/ceph/src/common/dout.h index d2340c936..8aa976b8c 100644 --- a/ceph/src/common/dout.h +++ b/ceph/src/common/dout.h @@ -21,12 +21,6 @@ #include "common/likely.h" #include "common/Clock.h" #include "log/Log.h" -#include "include/assert.h" - -#include -#include -#include -#include extern void dout_emergency(const char * const str); extern void dout_emergency(const std::string &str); diff --git a/ceph/src/common/entity_name.cc b/ceph/src/common/entity_name.cc index becad3a12..7c9cd7848 100644 --- a/ceph/src/common/entity_name.cc +++ b/ceph/src/common/entity_name.cc @@ -13,11 +13,8 @@ */ #include "common/entity_name.h" -#include "include/msgr.h" -#include #include -#include using std::string; @@ -76,9 +73,13 @@ set(uint32_t type_, const std::string &id_) type = type_; id = id_; - std::ostringstream oss; - oss << ceph_entity_type_name(type_) << "." << id_; - type_id = oss.str(); + if (type) { + std::ostringstream oss; + oss << ceph_entity_type_name(type_) << "." << id_; + type_id = oss.str(); + } else { + type_id.clear(); + } } int EntityName:: diff --git a/ceph/src/common/entity_name.h b/ceph/src/common/entity_name.h index d1c6cbcdd..e30b75f70 100644 --- a/ceph/src/common/entity_name.h +++ b/ceph/src/common/entity_name.h @@ -15,12 +15,8 @@ #ifndef CEPH_COMMON_ENTITY_NAME_H #define CEPH_COMMON_ENTITY_NAME_H -#include -#include -#include +#include -#include "include/encoding.h" -#include "include/buffer_fwd.h" #include "msg/msg_types.h" /* Represents a Ceph entity name. diff --git a/ceph/src/common/errno.cc b/ceph/src/common/errno.cc index da06991ba..69e54254b 100644 --- a/ceph/src/common/errno.cc +++ b/ceph/src/common/errno.cc @@ -2,8 +2,6 @@ #include "acconfig.h" #include -#include - #include std::string cpp_strerror(int err) diff --git a/ceph/src/common/event_socket.h b/ceph/src/common/event_socket.h index f38808ef5..79e8e15a7 100644 --- a/ceph/src/common/event_socket.h +++ b/ceph/src/common/event_socket.h @@ -17,9 +17,11 @@ #ifndef CEPH_COMMON_EVENT_SOCKET_H #define CEPH_COMMON_EVENT_SOCKET_H -#include "include/event_type.h" #include +#if defined(__FreeBSD__) #include +#endif +#include "include/event_type.h" class EventSocket { int socket; diff --git a/ceph/src/common/fd.cc b/ceph/src/common/fd.cc index 19f817daf..243b1ebfc 100644 --- a/ceph/src/common/fd.cc +++ b/ceph/src/common/fd.cc @@ -13,13 +13,6 @@ */ #include "include/compat.h" -#include "fd.h" - -#include -#include -#include -#include - #include "debug.h" #include "errno.h" diff --git a/ceph/src/common/freebsd_errno.cc b/ceph/src/common/freebsd_errno.cc new file mode 100644 index 000000000..77f6df91e --- /dev/null +++ b/ceph/src/common/freebsd_errno.cc @@ -0,0 +1,219 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2011 New Dream Network + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include +#include "include/types.h" +#include "include/compat.h" + +#define H2C_ERRNO(a,b) [a] = b +#define C2H_ERRNO(a,b) [a] = b + +// Build a table with the FreeBSD error as index +// and the Linux error as value +// Use the fact that the arry is initialised per default on all 0's +// And we do not translate for 0's, but return the original value. +static const __s32 ceph_to_hostos_conv[256] = { +// Linux errno FreeBSD errno + C2H_ERRNO(11, EAGAIN), + C2H_ERRNO(35, EDEADLK), + C2H_ERRNO(36, ENAMETOOLONG), + C2H_ERRNO(37, ENOLCK), + C2H_ERRNO(38, ENOSYS), + C2H_ERRNO(39, ENOTEMPTY), + C2H_ERRNO(40, ELOOP), + C2H_ERRNO(42, ENOMSG), + C2H_ERRNO(43, EIDRM), + C2H_ERRNO(44, EPERM), //TODO ECHRNG /* Channel number out of range */ + C2H_ERRNO(45, EPERM), //TODO EL2NSYNC /* Level 2 not synchronized */ + C2H_ERRNO(46, EPERM), //TODO EL3HLT /* Level 3 halted */ + C2H_ERRNO(47, EPERM), //TODO EL3RST /* Level 3 reset */ + C2H_ERRNO(48, EPERM), //TODO ELNRNG /* Link number out of range */ + C2H_ERRNO(49, EPERM), //TODO EUNATCH /* Protocol driver not attached */ + C2H_ERRNO(50, EPERM), //TODO ENOCSI /* No CSI structure available */ + C2H_ERRNO(51, EPERM), //TODO EL2HLT /* Level 2 halted */ + C2H_ERRNO(52, EPERM), //TODO EBADE /* Invalid exchange */ + C2H_ERRNO(53, EPERM), //TODO EBADR /* Invalid request descriptor */ + C2H_ERRNO(54, EPERM), //TODO EXFULL /* Exchange full */ + C2H_ERRNO(55, EPERM), //TODO ENOANO /* No anode */ + C2H_ERRNO(56, EPERM), //TODO EBADRQC /* Invalid request code */ + C2H_ERRNO(57, EPERM), //TODO EBADSLT /* Invalid slot */ + C2H_ERRNO(59, EPERM), //TODO EBFONT /* Bad font file format */ + C2H_ERRNO(60, ENOSTR), + C2H_ERRNO(61, ENODATA), + C2H_ERRNO(62, ETIME), + C2H_ERRNO(63, ENOSR), + C2H_ERRNO(64, EPERM), //TODO ENONET + C2H_ERRNO(65, EPERM), //TODO ENOPKG + C2H_ERRNO(66, EREMOTE), + C2H_ERRNO(67, ENOLINK), + C2H_ERRNO(68, EPERM), //TODO EADV + C2H_ERRNO(69, EPERM), //TODO ESRMNT + C2H_ERRNO(70, EPERM), //TODO ECOMM + C2H_ERRNO(71, EPROTO), + C2H_ERRNO(72, EMULTIHOP), + C2H_ERRNO(73, EPERM), //TODO EDOTDOT + C2H_ERRNO(74, EBADMSG), + C2H_ERRNO(75, EOVERFLOW), + C2H_ERRNO(76, EPERM), //TODO ENOTUNIQ + C2H_ERRNO(77, EPERM), //TODO EBADFD + C2H_ERRNO(78, EPERM), //TODO EREMCHG + C2H_ERRNO(79, EPERM), //TODO ELIBACC + C2H_ERRNO(80, EPERM), //TODO ELIBBAD + C2H_ERRNO(81, EPERM), //TODO ELIBSCN + C2H_ERRNO(82, EPERM), //TODO ELIBMAX + C2H_ERRNO(83, EPERM), //TODO ELIBEXEC + C2H_ERRNO(84, EILSEQ), + C2H_ERRNO(85, EINTR), /* not quite, since this is a syscll restart */ + C2H_ERRNO(86, EPERM), //ESTRPIPE; + C2H_ERRNO(87, EUSERS), + C2H_ERRNO(88, ENOTSOCK), + C2H_ERRNO(89, EDESTADDRREQ), + C2H_ERRNO(90, EMSGSIZE), + C2H_ERRNO(91, EPROTOTYPE), + C2H_ERRNO(92, ENOPROTOOPT), + C2H_ERRNO(93, EPROTONOSUPPORT), + C2H_ERRNO(94, ESOCKTNOSUPPORT), + C2H_ERRNO(95, EOPNOTSUPP), + C2H_ERRNO(96, EPFNOSUPPORT), + C2H_ERRNO(97, EAFNOSUPPORT), + C2H_ERRNO(98, EADDRINUSE), + C2H_ERRNO(99, EADDRNOTAVAIL), + C2H_ERRNO(100, ENETDOWN), + C2H_ERRNO(101, ENETUNREACH), + C2H_ERRNO(102, ENETRESET), + C2H_ERRNO(103, ECONNABORTED), + C2H_ERRNO(104, ECONNRESET), + C2H_ERRNO(105, ENOBUFS), + C2H_ERRNO(106, EISCONN), + C2H_ERRNO(107, ENOTCONN), + C2H_ERRNO(108, ESHUTDOWN), + C2H_ERRNO(109, ETOOMANYREFS), + C2H_ERRNO(110, ETIMEDOUT), + C2H_ERRNO(111, ECONNREFUSED), + C2H_ERRNO(112, EHOSTDOWN), + C2H_ERRNO(113, EHOSTUNREACH), + C2H_ERRNO(114, EALREADY), + C2H_ERRNO(115, EINPROGRESS), + C2H_ERRNO(116, ESTALE), + C2H_ERRNO(117, EPERM), //TODO EUCLEAN + C2H_ERRNO(118, EPERM), //TODO ENOTNAM + C2H_ERRNO(119, EPERM), //TODO ENAVAIL + C2H_ERRNO(120, EPERM), //TODO EISNAM + C2H_ERRNO(121, EREMOTEIO), + C2H_ERRNO(122, EDQUOT), + C2H_ERRNO(123, EPERM), //TODO ENOMEDIUM + C2H_ERRNO(124, EPERM), //TODO EMEDIUMTYPE - not used + C2H_ERRNO(125, ECANCELED), + C2H_ERRNO(126, EPERM), //TODO ENOKEY + C2H_ERRNO(127, EPERM), //TODO EKEYEXPIRED + C2H_ERRNO(128, EPERM), //TODO EKEYREVOKED + C2H_ERRNO(129, EPERM), //TODO EKEYREJECTED + C2H_ERRNO(130, EOWNERDEAD), + C2H_ERRNO(131, ENOTRECOVERABLE), + C2H_ERRNO(132, EPERM), //TODO ERFKILL + C2H_ERRNO(133, EPERM), //TODO EHWPOISON + }; + +// Build a table with the FreeBSD error as index +// and the Linux error as value +// Use the fact that the arry is initialised per default on all 0's +// And we do not translate for 0's, but return the original value. +static const __s32 hostos_to_ceph_conv[256] = { + // FreeBSD errno Linux errno + H2C_ERRNO(EDEADLK, 35), /* Resource deadlock avoided */ + H2C_ERRNO(EAGAIN, 11), /* Resource temporarily unavailable */ + H2C_ERRNO(EINPROGRESS, 115), /* Operation now in progress */ + H2C_ERRNO(EALREADY, 114), /* Operation already in progress */ + H2C_ERRNO(ENOTSOCK, 88), /* Socket operation on non-socket */ + H2C_ERRNO(EDESTADDRREQ, 89), /* Destination address required */ + H2C_ERRNO(EMSGSIZE, 90), /* Message too long */ + H2C_ERRNO(EPROTOTYPE, 91), /* Protocol wrong type for socket */ + H2C_ERRNO(ENOPROTOOPT, 92), /* Protocol not available */ + H2C_ERRNO(EPROTONOSUPPORT, 93), /* Protocol not supported */ + H2C_ERRNO(ESOCKTNOSUPPORT, 94), /* Socket type not supported */ + H2C_ERRNO(EOPNOTSUPP, 95), /* Operation not supported */ + H2C_ERRNO(EPFNOSUPPORT, 96), /* Protocol family not supported */ + H2C_ERRNO(EAFNOSUPPORT, 97), /* Address family not supported by protocol family */ + H2C_ERRNO(EADDRINUSE, 98), /* Address already in use */ + H2C_ERRNO(EADDRNOTAVAIL, 99), /* Can't assign requested address */ + H2C_ERRNO(ENETDOWN, 100), /* Network is down */ + H2C_ERRNO(ENETUNREACH, 101), /* Network is unreachable */ + H2C_ERRNO(ENETRESET, 102), /* Network dropped connection on reset */ + H2C_ERRNO(ECONNABORTED, 103), /* Software caused connection abort */ + H2C_ERRNO(ECONNRESET, 104), /* Connection reset by peer */ + H2C_ERRNO(ENOBUFS, 105), /* No buffer space available */ + H2C_ERRNO(EISCONN, 106), /* Socket is already connected */ + H2C_ERRNO(ENOTCONN, 107), /* Socket is not connected */ + H2C_ERRNO(ESHUTDOWN, 108), /* Can't send after socket shutdown */ + H2C_ERRNO(ETOOMANYREFS, 109), /* Too many references: can't splice */ + H2C_ERRNO(ETIMEDOUT, 110), /* Operation timed out */ + H2C_ERRNO(ECONNREFUSED, 111), /* Connection refused */ + H2C_ERRNO(ELOOP, 40), /* Too many levels of symbolic links */ + H2C_ERRNO(ENAMETOOLONG, 36), /* File name too long */ + H2C_ERRNO(EHOSTDOWN, 112), /* Host is down */ + H2C_ERRNO(EHOSTUNREACH, 113), /* No route to host */ + H2C_ERRNO(ENOTEMPTY, 39), /* Directory not empty */ + H2C_ERRNO(EPROCLIM, EPERM), /* Too many processes */ + H2C_ERRNO(EUSERS, 87), /* Too many users */ + H2C_ERRNO(EDQUOT, 122), /* Disc quota exceeded */ + H2C_ERRNO(ESTALE, 116), /* Stale NFS file handle */ + H2C_ERRNO(EREMOTE, 66), /* Too many levels of remote in path */ + H2C_ERRNO(EBADRPC, EPERM), /* RPC struct is bad */ + H2C_ERRNO(ERPCMISMATCH, EPERM), /* RPC version wrong */ + H2C_ERRNO(EPROGUNAVAIL, EPERM), /* RPC prog. not avail */ + H2C_ERRNO(EPROGMISMATCH, EPERM),/* Program version wrong */ + H2C_ERRNO(EPROCUNAVAIL, EPERM), /* Bad procedure for program */ + H2C_ERRNO(ENOLCK, EPERM), /* No locks available */ + H2C_ERRNO(ENOSYS, EPERM), /* Function not implemented */ + H2C_ERRNO(EFTYPE, EPERM), /* Inappropriate file type or format */ + H2C_ERRNO(EAUTH, EPERM), /* Authentication error */ + H2C_ERRNO(ENEEDAUTH, EPERM), /* Need authenticator */ + H2C_ERRNO(EIDRM, 43), /* Identifier removed */ + H2C_ERRNO(ENOMSG, 42), /* No message of desired type */ + H2C_ERRNO(EOVERFLOW, 75), /* Value too large to be stored in data type */ + H2C_ERRNO(ECANCELED, 125), /* Operation canceled */ + H2C_ERRNO(EILSEQ, 84), /* Illegal byte sequence */ + H2C_ERRNO(ENOATTR, 61), /* Attribute not found */ + H2C_ERRNO(EDOOFUS, EPERM), /* Programming error */ + H2C_ERRNO(EBADMSG, 74), /* Bad message */ + H2C_ERRNO(EMULTIHOP, 72), /* Multihop attempted */ + H2C_ERRNO(ENOLINK, 67), /* Link has been severed */ + H2C_ERRNO(EPROTO, 71), /* Protocol error */ + H2C_ERRNO(ENOTCAPABLE, EPERM), /* Capabilities insufficient */ + H2C_ERRNO(ECAPMODE, EPERM), /* Not permitted in capability mode */ + H2C_ERRNO(ENOTRECOVERABLE, 131),/* State not recoverable */ + H2C_ERRNO(EOWNERDEAD, 130), /* Previous owner died */ + }; + +// converts from linux errno values to host values +__s32 ceph_to_hostos_errno(__s32 r) +{ + int sign = (r < 0 ? -1 : 1); + int err = std::abs(r); + if (err < 256 && hostos_to_ceph_conv[err] !=0 ) { + err = ceph_to_hostos_conv[err]; + } + return err * sign; +} + +// converts Host OS errno values to linux/Ceph values +__s32 hostos_to_ceph_errno(__s32 r) +{ + int sign = (r < 0 ? -1 : 1); + int err = std::abs(r); + if (err < 256 && hostos_to_ceph_conv[err] !=0 ) { + err = hostos_to_ceph_conv[err]; + } + return err * sign; +} diff --git a/ceph/src/common/function_signature.h b/ceph/src/common/function_signature.h index 58b284ec8..6d2a34ee6 100644 --- a/ceph/src/common/function_signature.h +++ b/ceph/src/common/function_signature.h @@ -12,13 +12,10 @@ #include #include -#include #include #include #include -#include - template struct signature_of_member { diff --git a/ceph/src/common/hex.cc b/ceph/src/common/hex.cc index 24ba6724e..4fcc2158d 100644 --- a/ceph/src/common/hex.cc +++ b/ceph/src/common/hex.cc @@ -12,12 +12,8 @@ * */ -#include "common/debug.h" #include "common/hex.h" -#include -#include - void hex2str(const char *s, int len, char *buf, int dest_len) { int pos = 0; diff --git a/ceph/src/common/histogram.h b/ceph/src/common/histogram.h index 377e21262..5be696637 100644 --- a/ceph/src/common/histogram.h +++ b/ceph/src/common/histogram.h @@ -13,10 +13,8 @@ #ifndef CEPH_HISTOGRAM_H #define CEPH_HISTOGRAM_H -#include #include -#include "include/intarith.h" #include "include/encoding.h" namespace ceph { @@ -53,6 +51,9 @@ public: void clear() { h.clear(); } + bool empty() const { + return h.empty(); + } void set_bin(int bin, int32_t count) { _expand_to(bin + 1); h[bin] = count; diff --git a/ceph/src/common/hobject.cc b/ceph/src/common/hobject.cc index dffd471b7..d3f554f7a 100644 --- a/ceph/src/common/hobject.cc +++ b/ceph/src/common/hobject.cc @@ -1,7 +1,6 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "include/types.h" #include "hobject.h" #include "common/Formatter.h" diff --git a/ceph/src/common/hobject.h b/ceph/src/common/hobject.h index 66319e9ee..9b3f38f44 100644 --- a/ceph/src/common/hobject.h +++ b/ceph/src/common/hobject.h @@ -15,14 +15,14 @@ #ifndef __CEPH_OS_HOBJECT_H #define __CEPH_OS_HOBJECT_H -#include #include "include/types.h" -#include "include/object.h" #include "include/cmp.h" #include "json_spirit/json_spirit_value.h" #include "include/assert.h" // spirit clobbers it! +#include "reverse.h" + namespace ceph { class Formatter; } @@ -199,27 +199,10 @@ public: } static uint32_t _reverse_bits(uint32_t v) { - if (v == 0) - return v; - // reverse bits - // swap odd and even bits - v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); - // swap consecutive pairs - v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); - // swap nibbles ... - v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); - // swap bytes - v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); - // swap 2-byte long pairs - v = ( v >> 16 ) | ( v << 16); - return v; + return reverse_bits(v); } static uint32_t _reverse_nibbles(uint32_t retval) { - // reverse nibbles - retval = ((retval & 0x0f0f0f0f) << 4) | ((retval & 0xf0f0f0f0) >> 4); - retval = ((retval & 0x00ff00ff) << 8) | ((retval & 0xff00ff00) >> 8); - retval = ((retval & 0x0000ffff) << 16) | ((retval & 0xffff0000) >> 16); - return retval; + return reverse_nibbles(retval); } /** diff --git a/ceph/src/common/hostname.cc b/ceph/src/common/hostname.cc index d3c2f6739..32436534e 100644 --- a/ceph/src/common/hostname.cc +++ b/ceph/src/common/hostname.cc @@ -14,7 +14,6 @@ #include "common/hostname.h" -#include #include std::string ceph_get_hostname() diff --git a/ceph/src/common/inline_variant.h b/ceph/src/common/inline_variant.h index 8c4ce35cd..bd55a5911 100644 --- a/ceph/src/common/inline_variant.h +++ b/ceph/src/common/inline_variant.h @@ -8,31 +8,12 @@ #ifndef INLINE_VARIANT_H #define INLINE_VARIANT_H -#include #include -#include -#include -#include -#include -#include -#include #include -#include #include -#include -#include -#include #include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include "function_signature.h" diff --git a/ceph/src/common/interval_map.h b/ceph/src/common/interval_map.h index 408a60eb2..5357dff9f 100644 --- a/ceph/src/common/interval_map.h +++ b/ceph/src/common/interval_map.h @@ -15,11 +15,6 @@ #ifndef INTERVAL_MAP_H #define INTERVAL_MAP_H -#include -#include -#include -#include -#include #include "include/interval_set.h" template diff --git a/ceph/src/common/io_priority.cc b/ceph/src/common/io_priority.cc index 687faa3bd..c635555ad 100644 --- a/ceph/src/common/io_priority.cc +++ b/ceph/src/common/io_priority.cc @@ -13,11 +13,13 @@ */ #include +#if defined(__FreeBSD__) +#include +#endif #ifdef __linux__ #include /* For SYS_xxx definitions */ #endif #include -#include #include "io_priority.h" diff --git a/ceph/src/common/ipaddr.cc b/ceph/src/common/ipaddr.cc index a7dedf257..41add2de2 100644 --- a/ceph/src/common/ipaddr.cc +++ b/ceph/src/common/ipaddr.cc @@ -1,10 +1,15 @@ -#include "include/ipaddr.h" -#include #include +#include #include #include +#if defined(__FreeBSD__) +#include +#include +#include +#endif +#include "include/ipaddr.h" static void netmask_ipv4(const struct in_addr *addr, unsigned int prefix_len, diff --git a/ceph/src/common/iso_8601.cc b/ceph/src/common/iso_8601.cc new file mode 100644 index 000000000..39e00e0b3 --- /dev/null +++ b/ceph/src/common/iso_8601.cc @@ -0,0 +1,200 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "iso_8601.h" +#include "include/timegm.h" + +#include + +namespace ceph { +using std::chrono::duration_cast; +using std::chrono::nanoseconds; +using std::chrono::seconds; +using std::setw; +using std::size_t; +using std::stringstream; +using std::string; +using std::uint16_t; + +using boost::none; +using boost::optional; +using boost::string_ref; + +using ceph::real_clock; +using ceph::real_time; + +using sriter = string_ref::const_iterator; + +namespace { +// This assumes a contiguous block of numbers in the correct order. +uint16_t digit(char c) { + if (!(c >= '0' && c <= '9')) { + throw std::invalid_argument("Not a digit."); + } + return static_cast(c - '0'); +} + +optional calculate(const tm& t, uint32_t n = 0) { + ceph_assert(n < 1000000000); + time_t tt = internal_timegm(&t); + if (tt == static_cast(-1)) { + return none; + } + + return boost::make_optional(real_clock::from_time_t(tt) + + nanoseconds(n)); +} +} + +optional from_iso_8601(const string_ref s, + const bool ws_terminates) noexcept { + auto end = s.cend(); + auto read_digit = [end](sriter& c) mutable { + if (c == end) { + throw std::invalid_argument("End of input."); + } + auto f = digit(*c); + ++c; + return f; + }; + + auto read_digits = [end, &read_digit](sriter& c, std::size_t n) { + auto v = 0ULL; + for (auto i = 0U; i < n; ++i) { + auto d = read_digit(c); + v = (10ULL * v) + d; + } + return v; + }; + auto partial_date = [end, ws_terminates](sriter& c) { + return (c == end || (ws_terminates && std::isspace(*c))); + }; + auto time_end = [end, ws_terminates](sriter& c) { + return (c != end && *c == 'Z' && + ((c + 1) == end || + (ws_terminates && std::isspace(*(c + 1))))); + }; + auto consume_delimiter = [end](sriter& c, char q) { + if (c == end || *c != q) { + throw std::invalid_argument("Expected delimiter not found."); + } else { + ++c; + } + }; + + tm t = { 0, // tm_sec + 0, // tm_min + 0, // tm_hour + 1, // tm_mday + 0, // tm_mon + 70, // tm_year + 0, // tm_wday + 0, // tm_yday + 0, // tm_isdst + }; + try { + auto c = s.cbegin(); + { + auto y = read_digits(c, 4); + if (y < 1970) { + return none; + } + t.tm_year = y - 1900; + } + if (partial_date(c)) { + return calculate(t, 0); + } + + consume_delimiter(c, '-'); + t.tm_mon = (read_digits(c, 2) - 1); + if (partial_date(c)) { + return calculate(t); + } + consume_delimiter(c, '-'); + t.tm_mday = read_digits(c, 2); + if (partial_date(c)) { + return calculate(t); + } + consume_delimiter(c, 'T'); + t.tm_hour = read_digits(c, 2); + if (time_end(c)) { + return calculate(t); + } + consume_delimiter(c, ':'); + t.tm_min = read_digits(c, 2); + if (time_end(c)) { + return calculate(t); + } + consume_delimiter(c, ':'); + t.tm_sec = read_digits(c, 2); + if (time_end(c)) { + return calculate(t); + } + consume_delimiter(c, '.'); + + auto n = 0UL; + auto multiplier = 100000000UL; + for (auto i = 0U; i < 9U; ++i) { + auto d = read_digit(c); + n += d * multiplier; + multiplier /= 10; + if (time_end(c)) { + return calculate(t, n); + } + } + } catch (std::invalid_argument& e) { + // fallthrough + } + return none; +} + +string to_iso_8601(const real_time t, + const iso_8601_format f) noexcept { + ceph_assert(f >= iso_8601_format::Y && + f <= iso_8601_format::YMDhmsn); + stringstream out(std::ios_base::out); + + auto sec = real_clock::to_time_t(t); + auto nsec = duration_cast(t.time_since_epoch() % + seconds(1)).count(); + + struct tm bt; + gmtime_r(&sec, &bt); + out.fill('0'); + + out << 1900 + bt.tm_year; + if (f == iso_8601_format::Y) { + return out.str(); + } + + out << '-' << setw(2) << bt.tm_mon + 1; + if (f == iso_8601_format::YM) { + return out.str(); + } + + out << '-' << setw(2) << bt.tm_mday; + if (f == iso_8601_format::YMD) { + return out.str(); + } + + out << 'T' << setw(2) << bt.tm_hour; + if (f == iso_8601_format::YMDh) { + out << 'Z'; + return out.str(); + } + + out << ':' << setw(2) << bt.tm_min; + if (f == iso_8601_format::YMDhm) { + out << 'Z'; + return out.str(); + } + + out << ':' << setw(2) << bt.tm_sec; + if (f == iso_8601_format::YMDhms) { + out << 'Z'; + return out.str(); + } + out << '.' << setw(9) << nsec << 'Z'; + return out.str(); +} +} diff --git a/ceph/src/common/iso_8601.h b/ceph/src/common/iso_8601.h new file mode 100644 index 000000000..38de82848 --- /dev/null +++ b/ceph/src/common/iso_8601.h @@ -0,0 +1,43 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_COMMON_ISO_8601_H +#define CEPH_COMMON_ISO_8601_H + +#include + +#include "common/ceph_time.h" + +namespace ceph { + +// Here, we support the W3C profile of ISO 8601 with the following +// restrictions: +// - Subsecond resolution is supported to nanosecond +// granularity. Any number of digits between 1 and 9 may be +// specified after the decimal point. +// - All times must be UTC. +// - All times must be representable as a sixty-four bit count of +// nanoseconds since the epoch. +// - Partial times are handled thus: +// * If there are no subseconds, they are assumed to be zero. +// * If there are no seconds, they are assumed to be zero. +// * If there are no minutes, they are assumed to be zero. +// * If there is no time, it is assumed to midnight. +// * If there is no day, it is assumed to be the first. +// * If there is no month, it is assumed to be January. +// +// If a date is invalid, boost::none is returned. + +boost::optional from_iso_8601( + boost::string_ref s, const bool ws_terminates = true) noexcept; + +enum class iso_8601_format { + Y, YM, YMD, YMDh, YMDhm, YMDhms, YMDhmsn +}; + +std::string to_iso_8601(const ceph::real_time t, + const iso_8601_format f = iso_8601_format::YMDhmsn) + noexcept; +} + +#endif diff --git a/ceph/src/common/lockdep.cc b/ceph/src/common/lockdep.cc index 1f52e5656..5e4283e28 100644 --- a/ceph/src/common/lockdep.cc +++ b/ceph/src/common/lockdep.cc @@ -11,15 +11,9 @@ * Foundation. See file COPYING. * */ -#include "BackTrace.h" -#include "Clock.h" +#include "lockdep.h" #include "common/dout.h" -#include "common/environment.h" #include "common/valgrind.h" -#include "include/types.h" -#include "lockdep.h" - -#include "include/unordered_map.h" #if defined(__FreeBSD__) && defined(__LP64__) // On FreeBSD pthread_t is a pointer. namespace std { diff --git a/ceph/src/common/lru_map.h b/ceph/src/common/lru_map.h index 1e1acc95f..35722fcd0 100644 --- a/ceph/src/common/lru_map.h +++ b/ceph/src/common/lru_map.h @@ -1,11 +1,8 @@ #ifndef CEPH_LRU_MAP_H #define CEPH_LRU_MAP_H -#include -#include #include "common/Mutex.h" - template class lru_map { struct entry { diff --git a/ceph/src/common/map_cacher.hpp b/ceph/src/common/map_cacher.hpp index ba48c4ef9..b749460e2 100644 --- a/ceph/src/common/map_cacher.hpp +++ b/ceph/src/common/map_cacher.hpp @@ -15,16 +15,6 @@ #ifndef MAPCACHER_H #define MAPCACHER_H -#include -#include -#include "include/memory.h" -#include -#include -#include -#include -#include - -#include "include/Context.h" #include "common/sharedptr_registry.hpp" namespace MapCacher { diff --git a/ceph/src/common/mempool.cc b/ceph/src/common/mempool.cc index 15643567b..3a9cdba4f 100644 --- a/ceph/src/common/mempool.cc +++ b/ceph/src/common/mempool.cc @@ -41,12 +41,14 @@ const char *mempool::get_pool_name(mempool::pool_index_t ix) { void mempool::dump(ceph::Formatter *f) { + stats_t total; for (size_t i = 0; i < num_pools; ++i) { const pool_t &pool = mempool::get_pool((pool_index_t)i); f->open_object_section(get_pool_name((pool_index_t)i)); - pool.dump(f); + pool.dump(f, &total); f->close_section(); } + f->dump_object("total", total); } void mempool::set_debug_mode(bool d) @@ -77,6 +79,13 @@ size_t mempool::pool_t::allocated_items() const return (size_t) result; } +void mempool::pool_t::adjust_count(ssize_t items, ssize_t bytes) +{ + shard_t *shard = pick_a_shard(); + shard->items += items; + shard->bytes += bytes; +} + void mempool::pool_t::get_stats( stats_t *total, std::map *by_type) const @@ -96,17 +105,22 @@ void mempool::pool_t::get_stats( } } -void mempool::pool_t::dump(ceph::Formatter *f) const +void mempool::pool_t::dump(ceph::Formatter *f, stats_t *ptotal) const { stats_t total; std::map by_type; get_stats(&total, &by_type); - f->dump_object("total", total); + if (ptotal) { + *ptotal += total; + } + total.dump(f); if (!by_type.empty()) { + f->open_object_section("by_type"); for (auto &i : by_type) { f->open_object_section(i.first.c_str()); i.second.dump(f); f->close_section(); } + f->close_section(); } } diff --git a/ceph/src/common/module.c b/ceph/src/common/module.c index b251274a5..f19f74324 100644 --- a/ceph/src/common/module.c +++ b/ceph/src/common/module.c @@ -15,8 +15,9 @@ #include #include #include +#if defined(__FreeBSD__) #include -#include +#endif /* * TODO: Switch to libkmod when we abandon older platforms. The APIs diff --git a/ceph/src/common/mutex_debug.cc b/ceph/src/common/mutex_debug.cc index a85435861..49cc82b29 100644 --- a/ceph/src/common/mutex_debug.cc +++ b/ceph/src/common/mutex_debug.cc @@ -11,17 +11,11 @@ * Foundation. See file COPYING. * */ -#include - -#include -#include -#include #include "common/mutex_debug.h" #include "common/perf_counters.h" #include "common/ceph_context.h" #include "common/config.h" -#include "include/stringify.h" namespace ceph { namespace mutex_debug_detail { diff --git a/ceph/src/common/obj_bencher.cc b/ceph/src/common/obj_bencher.cc index 32b0abe92..4eaeba347 100644 --- a/ceph/src/common/obj_bencher.cc +++ b/ceph/src/common/obj_bencher.cc @@ -20,16 +20,6 @@ #include "common/Cond.h" #include "obj_bencher.h" -#include -#include - -#include - -#include -#include -#include -#include - const std::string BENCH_LASTRUN_METADATA = "benchmark_last_metadata"; const std::string BENCH_PREFIX = "benchmark_data"; static char cached_hostname[30] = {0}; diff --git a/ceph/src/common/obj_bencher.h b/ceph/src/common/obj_bencher.h index 11909e51d..8dad8e6dd 100644 --- a/ceph/src/common/obj_bencher.h +++ b/ceph/src/common/obj_bencher.h @@ -15,8 +15,6 @@ #ifndef CEPH_OBJ_BENCHER_H #define CEPH_OBJ_BENCHER_H -#include "common/config.h" -#include "common/Cond.h" #include "common/ceph_context.h" #include "common/Formatter.h" #include diff --git a/ceph/src/common/perf_counters.cc b/ceph/src/common/perf_counters.cc index 62d9b57a4..f3bc4e378 100644 --- a/ceph/src/common/perf_counters.cc +++ b/ceph/src/common/perf_counters.cc @@ -13,21 +13,10 @@ * */ -#include "include/int_types.h" - #include "common/perf_counters.h" #include "common/dout.h" -#include "common/errno.h" -#include "common/Formatter.h" #include "common/valgrind.h" -#include -#include -#include -#include -#include -#include - using std::ostringstream; PerfCountersCollection::PerfCountersCollection(CephContext *cct) @@ -184,11 +173,11 @@ void PerfCounters::inc(int idx, uint64_t amt) if (!(data.type & PERFCOUNTER_U64)) return; if (data.type & PERFCOUNTER_LONGRUNAVG) { - data.avgcount.inc(); - data.u64.add(amt); - data.avgcount2.inc(); + data.avgcount++; + data.u64 += amt; + data.avgcount2++; } else { - data.u64.add(amt); + data.u64 += amt; } } @@ -203,7 +192,7 @@ void PerfCounters::dec(int idx, uint64_t amt) assert(!(data.type & PERFCOUNTER_LONGRUNAVG)); if (!(data.type & PERFCOUNTER_U64)) return; - data.u64.sub(amt); + data.u64 -= amt; } void PerfCounters::set(int idx, uint64_t amt) @@ -220,11 +209,11 @@ void PerfCounters::set(int idx, uint64_t amt) ANNOTATE_BENIGN_RACE_SIZED(&data.u64, sizeof(data.u64), "perf counter atomic"); if (data.type & PERFCOUNTER_LONGRUNAVG) { - data.avgcount.inc(); - data.u64.set(amt); - data.avgcount2.inc(); + data.avgcount++; + data.u64 = amt; + data.avgcount2++; } else { - data.u64.set(amt); + data.u64 = amt; } } @@ -238,7 +227,7 @@ uint64_t PerfCounters::get(int idx) const const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_U64)) return 0; - return data.u64.read(); + return data.u64; } void PerfCounters::tinc(int idx, utime_t amt, uint32_t avgcount) @@ -252,11 +241,11 @@ void PerfCounters::tinc(int idx, utime_t amt, uint32_t avgcount) if (!(data.type & PERFCOUNTER_TIME)) return; if (data.type & PERFCOUNTER_LONGRUNAVG) { - data.avgcount.add(avgcount); - data.u64.add(amt.to_nsec()); - data.avgcount2.add(avgcount); + data.avgcount++; + data.u64 += amt.to_nsec(); + data.avgcount2++; } else { - data.u64.add(amt.to_nsec()); + data.u64 += amt.to_nsec(); } } @@ -271,11 +260,11 @@ void PerfCounters::tinc(int idx, ceph::timespan amt, uint32_t avgcount) if (!(data.type & PERFCOUNTER_TIME)) return; if (data.type & PERFCOUNTER_LONGRUNAVG) { - data.avgcount.add(avgcount); - data.u64.add(amt.count()); - data.avgcount2.add(avgcount); + data.avgcount++; + data.u64 += amt.count(); + data.avgcount2++; } else { - data.u64.add(amt.count()); + data.u64 += amt.count(); } } @@ -289,7 +278,7 @@ void PerfCounters::tset(int idx, utime_t amt) perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_TIME)) return; - data.u64.set(amt.to_nsec()); + data.u64 = amt.to_nsec(); if (data.type & PERFCOUNTER_LONGRUNAVG) ceph_abort(); } @@ -304,7 +293,7 @@ utime_t PerfCounters::tget(int idx) const const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_TIME)) return utime_t(); - uint64_t v = data.u64.read(); + uint64_t v = data.u64; return utime_t(v / 1000000000ull, v % 1000000000ull); } @@ -317,7 +306,7 @@ void PerfCounters::hinc(int idx, int64_t x, int64_t y) assert(idx < m_upper_bound); perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); - assert(data.type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_U64)); + assert(data.type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64)); assert(data.histogram); data.histogram->inc(x, y); @@ -370,14 +359,38 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema, if (schema) { f->open_object_section(d->name); + // we probably should not have exposed this raw field (with bit + // values), but existing plugins rely on it so we're stuck with + // it. f->dump_int("type", d->type); - if (d->description) { - f->dump_string("description", d->description); + if (d->type & PERFCOUNTER_COUNTER) { + f->dump_string("metric_type", "counter"); + } else { + f->dump_string("metric_type", "gauge"); + } + + if (d->type & PERFCOUNTER_LONGRUNAVG) { + if (d->type & PERFCOUNTER_TIME) { + f->dump_string("value_type", "real-integer-pair"); + } else { + f->dump_string("value_type", "integer-integer-pair"); + } + } else if (d->type & PERFCOUNTER_HISTOGRAM) { + if (d->type & PERFCOUNTER_TIME) { + f->dump_string("value_type", "real-2d-histogram"); + } else { + f->dump_string("value_type", "integer-2d-histogram"); + } } else { - f->dump_string("description", ""); + if (d->type & PERFCOUNTER_TIME) { + f->dump_string("value_type", "real"); + } else { + f->dump_string("value_type", "integer"); + } } + f->dump_string("description", d->description ? d->description : ""); if (d->nick != NULL) { f->dump_string("nick", d->nick); } else { @@ -402,18 +415,28 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema, f->dump_format_unquoted("sum", "%" PRId64 ".%09" PRId64, a.first / 1000000000ull, a.first % 1000000000ull); + uint64_t count = a.second; + uint64_t sum_ns = a.first; + if (count) { + uint64_t avg_ns = sum_ns / count; + f->dump_format_unquoted("avgtime", "%" PRId64 ".%09" PRId64, + avg_ns / 1000000000ull, + avg_ns % 1000000000ull); + } else { + f->dump_format_unquoted("avgtime", "%" PRId64 ".%09" PRId64, 0, 0); + } } else { ceph_abort(); } f->close_section(); } else if (d->type & PERFCOUNTER_HISTOGRAM) { - assert(d->type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_U64)); + assert(d->type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64)); assert(d->histogram); f->open_object_section(d->name); d->histogram->dump_formatted(f); f->close_section(); } else { - uint64_t v = d->u64.read(); + uint64_t v = d->u64; if (d->type & PERFCOUNTER_U64) { f->dump_unsigned(d->name, v); } else if (d->type & PERFCOUNTER_TIME) { @@ -497,14 +520,14 @@ void PerfCountersBuilder::add_time_avg( PERFCOUNTER_TIME | PERFCOUNTER_LONGRUNAVG); } -void PerfCountersBuilder::add_histogram( +void PerfCountersBuilder::add_u64_counter_histogram( int idx, const char *name, PerfHistogramCommon::axis_config_d x_axis_config, PerfHistogramCommon::axis_config_d y_axis_config, const char *description, const char *nick, int prio) { add_impl(idx, name, description, nick, prio, - PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM, + PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER, unique_ptr>{new PerfHistogram<>{x_axis_config, y_axis_config}}); } @@ -535,8 +558,10 @@ PerfCounters *PerfCountersBuilder::create_perf_counters() { PerfCounters::perf_counter_data_vec_t::const_iterator d = m_perf_counters->m_data.begin(); PerfCounters::perf_counter_data_vec_t::const_iterator d_end = m_perf_counters->m_data.end(); - for (; d != d_end; ++d) + for (; d != d_end; ++d) { assert(d->type != PERFCOUNTER_NONE); + assert(d->type & (PERFCOUNTER_U64 | PERFCOUNTER_TIME)); + } PerfCounters *ret = m_perf_counters; m_perf_counters = NULL; diff --git a/ceph/src/common/perf_counters.h b/ceph/src/common/perf_counters.h index 569723185..5eaa59fb6 100644 --- a/ceph/src/common/perf_counters.h +++ b/ceph/src/common/perf_counters.h @@ -17,31 +17,28 @@ #ifndef CEPH_COMMON_PERF_COUNTERS_H #define CEPH_COMMON_PERF_COUNTERS_H -#include "common/config_obs.h" +#include +#include +#include +#include +#include + #include "common/perf_histogram.h" -#include "common/Mutex.h" #include "include/utime.h" - -#include "common/config_obs.h" #include "common/Mutex.h" #include "common/ceph_time.h" -#include -#include -#include -#include - class CephContext; class PerfCountersBuilder; enum perfcounter_type_d : uint8_t { PERFCOUNTER_NONE = 0, - PERFCOUNTER_TIME = 0x1, - PERFCOUNTER_U64 = 0x2, - PERFCOUNTER_LONGRUNAVG = 0x4, - PERFCOUNTER_COUNTER = 0x8, - PERFCOUNTER_HISTOGRAM = 0x10, + PERFCOUNTER_TIME = 0x1, // float (measuring seconds) + PERFCOUNTER_U64 = 0x2, // integer (note: either TIME or U64 *must* be set) + PERFCOUNTER_LONGRUNAVG = 0x4, // paired counter + sum (time) + PERFCOUNTER_COUNTER = 0x8, // counter (vs guage) + PERFCOUNTER_HISTOGRAM = 0x10, // histogram (vector) of values }; @@ -79,21 +76,18 @@ public: : name(NULL), description(NULL), nick(NULL), - type(PERFCOUNTER_NONE), - u64(0), - avgcount(0), - avgcount2(0) + type(PERFCOUNTER_NONE) {} perf_counter_data_any_d(const perf_counter_data_any_d& other) : name(other.name), description(other.description), nick(other.nick), type(other.type), - u64(other.u64.read()) { + u64(other.u64.load()) { pair a = other.read_avg(); - u64.set(a.first); - avgcount.set(a.second); - avgcount2.set(a.second); + u64 = a.first; + avgcount = a.second; + avgcount2 = a.second; if (other.histogram) { histogram.reset(new PerfHistogram<>(*other.histogram)); } @@ -104,17 +98,17 @@ public: const char *nick; int prio = 0; enum perfcounter_type_d type; - atomic64_t u64; - atomic64_t avgcount; - atomic64_t avgcount2; + std::atomic u64 = { 0 }; + std::atomic avgcount = { 0 }; + std::atomic avgcount2 = { 0 }; std::unique_ptr> histogram; void reset() { if (type != PERFCOUNTER_U64) { - u64.set(0); - avgcount.set(0); - avgcount2.set(0); + u64 = 0; + avgcount = 0; + avgcount2 = 0; } if (histogram) { histogram->reset(); @@ -127,9 +121,9 @@ public: pair read_avg() const { uint64_t sum, count; do { - count = avgcount2.read(); - sum = u64.read(); - } while (avgcount.read() != count); + count = avgcount; + sum = u64; + } while (avgcount2 != count); return make_pair(sum, count); } }; @@ -313,12 +307,14 @@ public: const char *description=NULL, const char *nick = NULL, int prio=0); - void add_histogram(int key, const char* name, - PerfHistogramCommon::axis_config_d x_axis_config, - PerfHistogramCommon::axis_config_d y_axis_config, - const char *description=NULL, - const char* nick = NULL, - int prio=0); + void add_u64_counter_histogram( + int key, const char* name, + PerfHistogramCommon::axis_config_d x_axis_config, + PerfHistogramCommon::axis_config_d y_axis_config, + const char *description=NULL, + const char* nick = NULL, + int prio=0); + PerfCounters* create_perf_counters(); private: PerfCountersBuilder(const PerfCountersBuilder &rhs); diff --git a/ceph/src/common/perf_histogram.h b/ceph/src/common/perf_histogram.h index ee726d394..0d5d63054 100644 --- a/ceph/src/common/perf_histogram.h +++ b/ceph/src/common/perf_histogram.h @@ -15,12 +15,14 @@ #ifndef CEPH_COMMON_PERF_HISTOGRAM_H #define CEPH_COMMON_PERF_HISTOGRAM_H -#include "common/Formatter.h" -#include "include/atomic.h" - #include +#include #include +#include "common/Formatter.h" +#include "include/int_types.h" +#include "include/assert.h" + class PerfHistogramCommon { public: enum scale_type_d : uint8_t { @@ -84,16 +86,16 @@ public: m_axes_config[i++] = ac; } - m_rawData.reset(new atomic64_t[get_raw_size()]); + m_rawData.reset(new std::atomic[get_raw_size()] {}); } /// Copy from other histogram object PerfHistogram(const PerfHistogram &other) : m_axes_config(other.m_axes_config) { int64_t size = get_raw_size(); - m_rawData.reset(new atomic64_t[size]); + m_rawData.reset(new std::atomic[size] {}); for (int64_t i = 0; i < size; i++) { - m_rawData[i].set(other.m_rawData[i].read()); + m_rawData[i] = other.m_rawData[i].load(); } } @@ -101,7 +103,7 @@ public: void reset() { auto size = get_raw_size(); for (auto i = size; --i >= 0;) { - m_rawData[i].set(0); + m_rawData[i] = 0; } } @@ -109,21 +111,21 @@ public: template void inc(T... axis) { auto index = get_raw_index_for_value(axis...); - m_rawData[index].add(1); + m_rawData[index]++; } /// Increase counter for given axis buckets by one template void inc_bucket(T... bucket) { auto index = get_raw_index_for_bucket(bucket...); - m_rawData[index].add(1); + m_rawData[index]++; } /// Read value from given bucket template uint64_t read_bucket(T... bucket) const { auto index = get_raw_index_for_bucket(bucket...); - return m_rawData[index].read(); + return m_rawData[index]; } /// Dump data to a Formatter object @@ -142,7 +144,7 @@ public: protected: /// Raw data stored as linear space, internal indexes are calculated on /// demand. - std::unique_ptr m_rawData; + std::unique_ptr[]> m_rawData; /// Configuration of axes std::array m_axes_config; @@ -207,7 +209,7 @@ protected: void visit_values(FDE onDimensionEnter, FV onValue, FDL onDimensionLeave, int level = 0, int startIndex = 0) const { if (level == DIM) { - onValue(m_rawData[startIndex].read()); + onValue(m_rawData[startIndex]); return; } diff --git a/ceph/src/common/pick_address.cc b/ceph/src/common/pick_address.cc index 5f910d541..e1d3f20a2 100644 --- a/ceph/src/common/pick_address.cc +++ b/ceph/src/common/pick_address.cc @@ -13,15 +13,13 @@ */ #include "common/pick_address.h" - -#include -#include - #include "include/ipaddr.h" #include "include/str_list.h" #include "common/debug.h" #include "common/errno.h" +#include + #define dout_subsys ceph_subsys_ static const struct sockaddr *find_ip_in_subnet_list(CephContext *cct, diff --git a/ceph/src/common/pipe.c b/ceph/src/common/pipe.c index 913aa4fe8..7353cb77f 100644 --- a/ceph/src/common/pipe.c +++ b/ceph/src/common/pipe.c @@ -11,15 +11,10 @@ * Foundation. See file COPYING. * */ -#include "acconfig.h" - -#include "common/pipe.h" #include "include/compat.h" #include #include -#include -#include #include int pipe_cloexec(int pipefd[2]) diff --git a/ceph/src/common/reverse.c b/ceph/src/common/reverse.c new file mode 100644 index 000000000..f65540d54 --- /dev/null +++ b/ceph/src/common/reverse.c @@ -0,0 +1,42 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "reverse.h" + +uint32_t reverse_bits(uint32_t v) { + if (v == 0) + return v; + + /* reverse bits + * swap odd and even bits + */ + v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); + /* swap consecutive pairs */ + v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); + /* swap nibbles ... */ + v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); + /* swap bytes */ + v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); + /* swap 2-byte long pairs */ + v = ( v >> 16 ) | ( v << 16); + return v; +} + +uint32_t reverse_nibbles(uint32_t retval) { + /* reverse nibbles */ + retval = ((retval & 0x0f0f0f0f) << 4) | ((retval & 0xf0f0f0f0) >> 4); + retval = ((retval & 0x00ff00ff) << 8) | ((retval & 0xff00ff00) >> 8); + retval = ((retval & 0x0000ffff) << 16) | ((retval & 0xffff0000) >> 16); + return retval; +} diff --git a/ceph/src/common/reverse.h b/ceph/src/common/reverse.h new file mode 100644 index 000000000..9a199a847 --- /dev/null +++ b/ceph/src/common/reverse.h @@ -0,0 +1,31 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __CEPH_OS_REVERSE_H +#define __CEPH_OS_REVERSE_H + +#include "include/int_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t reverse_bits(uint32_t v); +extern uint32_t reverse_nibbles(uint32_t retval); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ceph/src/common/run_cmd.cc b/ceph/src/common/run_cmd.cc index 396676d7b..a84f68aea 100644 --- a/ceph/src/common/run_cmd.cc +++ b/ceph/src/common/run_cmd.cc @@ -14,10 +14,8 @@ #include "common/errno.h" -#include #include #include -#include #include #include #include diff --git a/ceph/src/common/safe_io.c b/ceph/src/common/safe_io.c index e727542fb..633e3b3e8 100644 --- a/ceph/src/common/safe_io.c +++ b/ceph/src/common/safe_io.c @@ -12,6 +12,9 @@ * */ +#include "common/safe_io.h" +#include "include/compat.h" + #include #include #include @@ -19,9 +22,6 @@ #include #include -#include "common/safe_io.h" -#include "include/compat.h" - ssize_t safe_read(int fd, void *buf, size_t count) { size_t cnt = 0; diff --git a/ceph/src/common/safe_io.h b/ceph/src/common/safe_io.h index 9ba34b6bc..af8ca700d 100644 --- a/ceph/src/common/safe_io.h +++ b/ceph/src/common/safe_io.h @@ -15,7 +15,6 @@ #ifndef CEPH_SAFE_IO #define CEPH_SAFE_IO -#include "acconfig.h" #include "common/compiler_extensions.h" #include diff --git a/ceph/src/common/scrub_types.h b/ceph/src/common/scrub_types.h index 6143e9e17..39a265671 100644 --- a/ceph/src/common/scrub_types.h +++ b/ceph/src/common/scrub_types.h @@ -4,11 +4,8 @@ #ifndef CEPH_SCRUB_TYPES_H #define CEPH_SCRUB_TYPES_H -#include "include/rados/rados_types.hpp" -#include "common/hobject.h" #include "osd/osd_types.h" - // wrappers around scrub types to offer the necessary bits other than // the minimal set that the lirados requires struct object_id_wrapper : public librados::object_id_t { diff --git a/ceph/src/common/secret.c b/ceph/src/common/secret.c index 82150930e..b6f26ec3e 100644 --- a/ceph/src/common/secret.c +++ b/ceph/src/common/secret.c @@ -14,12 +14,10 @@ #include #include -#include #include #include #include #include -#include #include "common/armor.h" #include "common/safe_io.h" diff --git a/ceph/src/common/shared_cache.hpp b/ceph/src/common/shared_cache.hpp index 8ff949084..3332bd4f0 100644 --- a/ceph/src/common/shared_cache.hpp +++ b/ceph/src/common/shared_cache.hpp @@ -17,12 +17,13 @@ #include #include -#include -#include #include "common/Mutex.h" #include "common/Cond.h" #include "include/unordered_map.h" +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" + template , class H = std::hash > class SharedLRU { CephContext *cct; diff --git a/ceph/src/common/simple_cache.hpp b/ceph/src/common/simple_cache.hpp index d8653ece2..1ff4ae911 100644 --- a/ceph/src/common/simple_cache.hpp +++ b/ceph/src/common/simple_cache.hpp @@ -15,11 +15,7 @@ #ifndef CEPH_SIMPLECACHE_H #define CEPH_SIMPLECACHE_H -#include -#include -#include #include "common/Mutex.h" -#include "common/Cond.h" #include "include/unordered_map.h" template , class H = std::hash > diff --git a/ceph/src/common/solaris_errno.cc b/ceph/src/common/solaris_errno.cc index 0ce23c704..bb68e68fa 100644 --- a/ceph/src/common/solaris_errno.cc +++ b/ceph/src/common/solaris_errno.cc @@ -12,12 +12,11 @@ * */ -#include #include "include/types.h" // converts from linux errno values to host values -__s32 ceph_to_host_errno(__s32 r) +__s32 ceph_to_hostos_errno(__s32 r) { if (r < -34) { switch (r) { @@ -224,4 +223,11 @@ __s32 ceph_to_host_errno(__s32 r) return r; // otherwise return original value } +// converts Host OS errno values to linux/Ceph values +// XXX Currently not worked out +__s32 hostos_to_ceph_errno(__s32 r) +{ + return r; +} + diff --git a/ceph/src/common/sstring.hh b/ceph/src/common/sstring.hh index 8d2c92cc4..3783cc1ef 100644 --- a/ceph/src/common/sstring.hh +++ b/ceph/src/common/sstring.hh @@ -26,17 +26,11 @@ #ifndef SSTRING_HH_ #define SSTRING_HH_ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include + +#include "include/buffer.h" +#include "include/denc.h" template class basic_sstring; @@ -533,8 +527,8 @@ public: const char_type& operator[](size_type pos) const { return str()[pos]; } - operator boost::basic_string_ref() const { - return boost::basic_string_ref(str(), size()); + operator boost::basic_string_view() const { + return boost::basic_string_view(str(), size()); } template friend inline string_type to_sstring(T value); @@ -617,7 +611,7 @@ template struct hash> { size_t operator()(const basic_sstring& s) const { using traits_type = std::char_traits; - return std::hash>()(s); + return std::hash>()(s); } }; @@ -647,6 +641,60 @@ inline string_type to_sstring(T value) { return sstring::to_sstring(value); } + +// encode/decode +template +struct denc_traits> { +private: + using value_type = basic_sstring; +public: + static constexpr bool supported = true; + static constexpr bool featured = false; + static constexpr bool bounded = false; + + static void bound_encode(const value_type& s, size_t& p, uint64_t f=0) { + p += sizeof(Size) + s.size(); + } + + static void encode_nohead(const value_type& s, + buffer::list::contiguous_appender& p) + { + auto len = s.size(); + if (len) { + p.append(reinterpret_cast(s.c_str()), len); + } + } + + static void decode_nohead(size_t len, value_type& s, + buffer::ptr::iterator& p) + { + s.reset(); + if (len) { + s.append(reinterpret_cast(p.get_pos_add(len)), len); + } + } + + static void encode(const value_type& s, + buffer::list::contiguous_appender& p, + uint64_t f=0) + { + Size len = (Size)(s.size()); + ::denc(len, p); + if (len) { + p.append(reinterpret_cast(s.c_str()), len); + } + } + + static void decode(value_type& s, + buffer::ptr::iterator& p, + uint64_t f=0) + { + Size len; + ::denc(len, p); + decode_nohead(len, s, p); + } +}; + #if 0 /* XXX conflicts w/Ceph types.h */ template inline diff --git a/ceph/src/common/str_map.cc b/ceph/src/common/str_map.cc index 4605302e5..c3f6a2b65 100644 --- a/ceph/src/common/str_map.cc +++ b/ceph/src/common/str_map.cc @@ -14,8 +14,6 @@ * */ -#include - #include "include/str_map.h" #include "include/str_list.h" diff --git a/ceph/src/common/strtol.cc b/ceph/src/common/strtol.cc index a8ddafe70..4997a1242 100644 --- a/ceph/src/common/strtol.cc +++ b/ceph/src/common/strtol.cc @@ -14,9 +14,7 @@ #include "strtol.h" -#include #include -#include #include #include diff --git a/ceph/src/common/tracked_int_ptr.hpp b/ceph/src/common/tracked_int_ptr.hpp index e0e423835..5752906b1 100644 --- a/ceph/src/common/tracked_int_ptr.hpp +++ b/ceph/src/common/tracked_int_ptr.hpp @@ -15,12 +15,6 @@ #ifndef CEPH_TRACKEDINTPTR_H #define CEPH_TRACKEDINTPTR_H -#include -#include -#include -#include -#include "common/Mutex.h" -#include "common/Cond.h" template class TrackedIntPtr { @@ -50,18 +44,14 @@ public: TrackedIntPtr o(rhs.ptr); swap(o); } - const T &operator*() const { + T &operator*() const { return *ptr; } - T &operator*() { - return *ptr; - } - const T *operator->() const { - return ptr; - } - T *operator->() { + T *operator->() const { return ptr; } + T *get() const { return ptr; } + operator bool() const { return ptr != NULL; } @@ -71,6 +61,13 @@ public: bool operator==(const TrackedIntPtr &lhs) const { return ptr == lhs.ptr; } + + void reset() { + if (ptr) + put_with_id(ptr, id); + ptr = nullptr; + id = 0; + } }; #endif diff --git a/ceph/src/common/util.cc b/ceph/src/common/util.cc index 3cc1c49e7..762fe374b 100644 --- a/ceph/src/common/util.cc +++ b/ceph/src/common/util.cc @@ -12,7 +12,6 @@ * */ -#include #include #include @@ -20,7 +19,6 @@ #include "include/util.h" #include "common/debug.h" #include "common/errno.h" -#include "common/strtol.h" #include "common/version.h" #ifdef HAVE_SYS_VFS_H diff --git a/ceph/src/common/version.cc b/ceph/src/common/version.cc index 99c9d58ed..3f882a2b4 100644 --- a/ceph/src/common/version.cc +++ b/ceph/src/common/version.cc @@ -12,11 +12,13 @@ * */ +#include + #include "ceph_ver.h" #include "common/version.h" +#include "include/rados.h" #include -#include #define _STR(x) #x #define STRINGIFY(x) _STR(x) @@ -34,7 +36,19 @@ const char *git_version_to_str(void) std::string const pretty_version_to_str(void) { std::ostringstream oss; - oss << "ceph version " << CEPH_GIT_NICE_VER << " (" - << STRINGIFY(CEPH_GIT_VER) << ")"; + oss << "ceph version " << CEPH_GIT_NICE_VER + << " (" << STRINGIFY(CEPH_GIT_VER) << ") " + << ceph_release_name(CEPH_RELEASE) + << " (" << CEPH_RELEASE_TYPE << ")"; return oss.str(); } + +unsigned ceph_release(void) +{ + return CEPH_RELEASE; +} + +const char *ceph_release_type(void) +{ + return CEPH_RELEASE_TYPE; +} diff --git a/ceph/src/common/version.h b/ceph/src/common/version.h index fae88f835..3d9d6622c 100644 --- a/ceph/src/common/version.h +++ b/ceph/src/common/version.h @@ -26,4 +26,11 @@ const char *git_version_to_str(void); // Return a formatted string describing the ceph and git versions std::string const pretty_version_to_str(void); +// Release number (e.g., 12 for luminous); see CEPH_RELEASE_* in include/rados.h +// and use const char *ceph_release_name(int) to translate to a string. +unsigned ceph_release(void); + +// Release type ("dev", "rc", or "stable") +const char *ceph_release_type(void); + #endif diff --git a/ceph/src/common/xattr.h b/ceph/src/common/xattr.h index 147a23c11..15b356196 100644 --- a/ceph/src/common/xattr.h +++ b/ceph/src/common/xattr.h @@ -12,8 +12,6 @@ #ifndef CEPH_EXTATTR_H #define CEPH_EXTATTR_H -#include -#include #ifdef __cplusplus extern "C" { diff --git a/ceph/src/common/zipkin_trace.h b/ceph/src/common/zipkin_trace.h index 6d3f02b43..86624715c 100644 --- a/ceph/src/common/zipkin_trace.h +++ b/ceph/src/common/zipkin_trace.h @@ -3,8 +3,8 @@ #ifndef COMMON_ZIPKIN_TRACE_H #define COMMON_ZIPKIN_TRACE_H -#include #include "acconfig.h" +#include "include/encoding.h" #ifdef WITH_BLKIN diff --git a/ceph/src/compressor/AsyncCompressor.cc b/ceph/src/compressor/AsyncCompressor.cc index 7a9071a71..d4a77686b 100644 --- a/ceph/src/compressor/AsyncCompressor.cc +++ b/ceph/src/compressor/AsyncCompressor.cc @@ -22,7 +22,6 @@ AsyncCompressor::AsyncCompressor(CephContext *c): compressor(Compressor::create(c, c->_conf->async_compressor_type)), cct(c), - job_id(0), compress_tp(cct, "AsyncCompressor::compressor_tp", "tp_async_compr", cct->_conf->async_compressor_threads, "async_compressor_threads"), job_lock("AsyncCompressor::job_lock"), compress_wq(this, c->_conf->async_compressor_thread_timeout, c->_conf->async_compressor_thread_suicide_timeout, &compress_tp) { @@ -42,7 +41,7 @@ void AsyncCompressor::terminate() uint64_t AsyncCompressor::async_compress(bufferlist &data) { - uint64_t id = job_id.inc(); + uint64_t id = ++job_id; pair::iterator, bool> it; { Mutex::Locker l(job_lock); @@ -56,7 +55,7 @@ uint64_t AsyncCompressor::async_compress(bufferlist &data) uint64_t AsyncCompressor::async_decompress(bufferlist &data) { - uint64_t id = job_id.inc(); + uint64_t id = ++job_id; pair::iterator, bool> it; { Mutex::Locker l(job_lock); @@ -77,25 +76,25 @@ int AsyncCompressor::get_compress_data(uint64_t compress_id, bufferlist &data, b ldout(cct, 10) << __func__ << " missing to get compress job id=" << compress_id << dendl; return -ENOENT; } - int status; retry: - status = it->second.status.read(); - if (status == DONE) { + auto status = it->second.status.load(); + if (status == status_t::DONE) { ldout(cct, 20) << __func__ << " successfully getting compressed data, job id=" << compress_id << dendl; *finished = true; data.swap(it->second.data); jobs.erase(it); - } else if (status == ERROR) { + } else if (status == status_t::ERROR) { ldout(cct, 20) << __func__ << " compressed data failed, job id=" << compress_id << dendl; jobs.erase(it); return -EIO; } else if (blocking) { - if (it->second.status.compare_and_swap(WAIT, DONE)) { + auto expected = status_t::WAIT; + if (it->second.status.compare_exchange_strong(expected, status_t::DONE)) { ldout(cct, 10) << __func__ << " compress job id=" << compress_id << " hasn't finished, abort!"<< dendl; if (compressor->compress(it->second.data, data)) { ldout(cct, 1) << __func__ << " compress job id=" << compress_id << " failed!"<< dendl; - it->second.status.set(ERROR); + it->second.status = status_t::ERROR; return -EIO; } *finished = true; @@ -121,25 +120,24 @@ int AsyncCompressor::get_decompress_data(uint64_t decompress_id, bufferlist &dat ldout(cct, 10) << __func__ << " missing to get decompress job id=" << decompress_id << dendl; return -ENOENT; } - int status; - retry: - status = it->second.status.read(); - if (status == DONE) { + auto status = it->second.status.load(); + if (status == status_t::DONE) { ldout(cct, 20) << __func__ << " successfully getting decompressed data, job id=" << decompress_id << dendl; *finished = true; data.swap(it->second.data); jobs.erase(it); - } else if (status == ERROR) { + } else if (status == status_t::ERROR) { ldout(cct, 20) << __func__ << " compressed data failed, job id=" << decompress_id << dendl; jobs.erase(it); return -EIO; } else if (blocking) { - if (it->second.status.compare_and_swap(WAIT, DONE)) { + auto expected = status_t::WAIT; + if (it->second.status.compare_exchange_strong(expected, status_t::DONE)) { ldout(cct, 10) << __func__ << " decompress job id=" << decompress_id << " hasn't started, abort!"<< dendl; if (compressor->decompress(it->second.data, data)) { ldout(cct, 1) << __func__ << " decompress job id=" << decompress_id << " failed!"<< dendl; - it->second.status.set(ERROR); + it->second.status = status_t::ERROR; return -EIO; } *finished = true; diff --git a/ceph/src/compressor/AsyncCompressor.h b/ceph/src/compressor/AsyncCompressor.h index 81321fdd5..7ca8fad04 100644 --- a/ceph/src/compressor/AsyncCompressor.h +++ b/ceph/src/compressor/AsyncCompressor.h @@ -16,34 +16,36 @@ #define CEPH_ASYNCCOMPRESSOR_H #include +#include +#include -#include "include/atomic.h" #include "include/str_list.h" + #include "Compressor.h" #include "common/WorkQueue.h" - class AsyncCompressor { private: CompressorRef compressor; CephContext *cct; - atomic_t job_id; + std::atomic job_id { 0 }; vector coreids; ThreadPool compress_tp; - enum { + enum class status_t { WAIT, WORKING, DONE, ERROR - } status; + }; + struct Job { uint64_t id; - atomic_t status; + std::atomic status { status_t::WAIT }; bool is_compress; bufferlist data; - Job(uint64_t i, bool compress): id(i), status(WAIT), is_compress(compress) {} - Job(const Job &j): id(j.id), status(j.status.read()), is_compress(j.is_compress), data(j.data) {} + Job(uint64_t i, bool compress): id(i), is_compress(compress) {} + Job(const Job &j): id(j.id), status(j.status.load()), is_compress(j.is_compress), data(j.data) {} }; Mutex job_lock; // only when job.status == DONE && with job_lock holding, we can insert/erase element in jobs @@ -75,7 +77,9 @@ class AsyncCompressor { while (!job_queue.empty()) { item = job_queue.front(); job_queue.pop_front(); - if (item->status.compare_and_swap(WAIT, WORKING)) { + + auto expected = status_t::WAIT; + if (item->status.compare_exchange_strong(expected, status_t::WORKING)) { break; } else { Mutex::Locker l(async_compressor->job_lock); @@ -86,7 +90,7 @@ class AsyncCompressor { return item; } void _process(Job *item, ThreadPool::TPHandle &) override { - assert(item->status.read() == WORKING); + assert(item->status == status_t::WORKING); bufferlist out; int r; if (item->is_compress) @@ -95,9 +99,10 @@ class AsyncCompressor { r = async_compressor->compressor->decompress(item->data, out); if (!r) { item->data.swap(out); - assert(item->status.compare_and_swap(WORKING, DONE)); + auto expected = status_t::WORKING; + assert(item->status.compare_exchange_strong(expected, status_t::DONE)); } else { - item->status.set(ERROR); + item->status = status_t::ERROR; } } void _process_finish(Job *item) override {} diff --git a/ceph/src/compressor/CMakeLists.txt b/ceph/src/compressor/CMakeLists.txt index c4d3b82c9..8e0e61cdb 100644 --- a/ceph/src/compressor/CMakeLists.txt +++ b/ceph/src/compressor/CMakeLists.txt @@ -12,14 +12,33 @@ add_subdirectory(snappy) add_subdirectory(zlib) add_subdirectory(zstd) -add_custom_target(compressor_plugins DEPENDS +if (HAVE_LZ4) + add_subdirectory(lz4) +endif() + +set(ceph_compressor_libs ceph_snappy ceph_zlib ceph_zstd) +if (HAVE_LZ4) + list(APPEND ceph_compressor_libs ceph_lz4) +endif() + +add_custom_target(compressor_plugins DEPENDS + ${ceph_compressor_libs}) + if(WITH_EMBEDDED) include(MergeStaticLibraries) add_library(cephd_compressor_base STATIC ${compressor_srcs}) set_target_properties(cephd_compressor_base PROPERTIES COMPILE_DEFINITIONS BUILDING_FOR_EMBEDDED) - merge_static_libraries(cephd_compressor cephd_compressor_base cephd_compressor_snappy cephd_compressor_zlib cephd_compressor_zstd) + set(cephd_compressor_libs + cephd_compressor_base + cephd_compressor_snappy + cephd_compressor_zlib + cephd_compressor_zstd) + if (HAVE_LZ4) + list(APPEND cephd_compressor_libs cephd_compressor_lz4) + endif() + merge_static_libraries(cephd_compressor ${cephd_compressor_libs}) endif() diff --git a/ceph/src/compressor/CompressionPlugin.h b/ceph/src/compressor/CompressionPlugin.h index d2e253f2d..5e0ed777b 100644 --- a/ceph/src/compressor/CompressionPlugin.h +++ b/ceph/src/compressor/CompressionPlugin.h @@ -18,8 +18,9 @@ #ifndef COMPRESSION_PLUGIN_H #define COMPRESSION_PLUGIN_H +#include #include -#include "common/Mutex.h" + #include "common/PluginRegistry.h" #include "Compressor.h" diff --git a/ceph/src/compressor/Compressor.cc b/ceph/src/compressor/Compressor.cc index 6b49b788f..a1ed5e928 100644 --- a/ceph/src/compressor/Compressor.cc +++ b/ceph/src/compressor/Compressor.cc @@ -13,8 +13,12 @@ */ #include -#include "Compressor.h" +#include + #include "CompressionPlugin.h" +#include "Compressor.h" +#include "common/ceph_context.h" +#include "common/debug.h" #include "common/dout.h" const char * Compressor::get_comp_alg_name(int a) { @@ -23,6 +27,7 @@ const char * Compressor::get_comp_alg_name(int a) { case COMP_ALG_SNAPPY: return "snappy"; case COMP_ALG_ZLIB: return "zlib"; case COMP_ALG_ZSTD: return "zstd"; + case COMP_ALG_LZ4: return "lz4"; default: return "???"; } } @@ -34,6 +39,8 @@ boost::optional Compressor::get_comp_alg_type( return COMP_ALG_ZLIB; if (s == "zstd") return COMP_ALG_ZSTD; + if (s == "lz4") + return COMP_ALG_LZ4; if (s == "") return COMP_ALG_NONE; diff --git a/ceph/src/compressor/Compressor.h b/ceph/src/compressor/Compressor.h index 8be13043d..fec82d44c 100644 --- a/ceph/src/compressor/Compressor.h +++ b/ceph/src/compressor/Compressor.h @@ -15,13 +15,17 @@ #ifndef CEPH_COMPRESSOR_H #define CEPH_COMPRESSOR_H + +#include #include #include -#include "include/memory.h" +#include "include/assert.h" // boost clobbers this #include "include/buffer.h" +#include "include/int_types.h" class Compressor; -typedef shared_ptr CompressorRef; +typedef std::shared_ptr CompressorRef; +class CephContext; class Compressor { public: @@ -30,6 +34,7 @@ public: COMP_ALG_SNAPPY = 1, COMP_ALG_ZLIB = 2, COMP_ALG_ZSTD = 3, + COMP_ALG_LZ4 = 4, COMP_ALG_LAST //the last value for range checks }; // compression options @@ -55,11 +60,11 @@ public: CompressionAlgorithm get_type() const { return alg; } - virtual int compress(const bufferlist &in, bufferlist &out) = 0; - virtual int decompress(const bufferlist &in, bufferlist &out) = 0; + virtual int compress(const ceph::bufferlist &in, ceph::bufferlist &out) = 0; + virtual int decompress(const ceph::bufferlist &in, ceph::bufferlist &out) = 0; // this is a bit weird but we need non-const iterator to be in // alignment with decode methods - virtual int decompress(bufferlist::iterator &p, size_t compressed_len, bufferlist &out) = 0; + virtual int decompress(ceph::bufferlist::iterator &p, size_t compressed_len, ceph::bufferlist &out) = 0; static CompressorRef create(CephContext *cct, const std::string &type); static CompressorRef create(CephContext *cct, int alg); diff --git a/ceph/src/compressor/lz4/CMakeLists.txt b/ceph/src/compressor/lz4/CMakeLists.txt new file mode 100644 index 000000000..7a53000e9 --- /dev/null +++ b/ceph/src/compressor/lz4/CMakeLists.txt @@ -0,0 +1,19 @@ +# lz4 + +set(lz4_sources + CompressionPluginLZ4.cc +) + +add_library(ceph_lz4 SHARED ${lz4_sources}) +add_dependencies(ceph_lz4 ${CMAKE_SOURCE_DIR}/src/ceph_ver.h) +target_link_libraries(ceph_lz4 ${LZ4_LIBRARY}) +set_target_properties(ceph_lz4 PROPERTIES + VERSION 2.0.0 + SOVERSION 2 + INSTALL_RPATH "") +install(TARGETS ceph_lz4 DESTINATION ${compressor_plugin_dir}) + +if(WITH_EMBEDDED) + add_library(cephd_compressor_lz4 STATIC ${lz4_sources}) + set_target_properties(cephd_compressor_lz4 PROPERTIES COMPILE_DEFINITIONS BUILDING_FOR_EMBEDDED) +endif() diff --git a/ceph/src/compressor/lz4/CompressionPluginLZ4.cc b/ceph/src/compressor/lz4/CompressionPluginLZ4.cc new file mode 100644 index 000000000..c99e5dcdc --- /dev/null +++ b/ceph/src/compressor/lz4/CompressionPluginLZ4.cc @@ -0,0 +1,39 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 XSKY Inc. + * + * Author: Haomai Wang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include "acconfig.h" +#include "ceph_ver.h" +#include "CompressionPluginLZ4.h" + +#ifndef BUILDING_FOR_EMBEDDED + +// ----------------------------------------------------------------------------- + +const char *__ceph_plugin_version() +{ + return CEPH_GIT_NICE_VER; +} + +// ----------------------------------------------------------------------------- + +int __ceph_plugin_init(CephContext *cct, + const std::string& type, + const std::string& name) +{ + PluginRegistry *instance = cct->get_plugin_registry(); + + return instance->add(type, name, new CompressionPluginLZ4(cct)); +} + +#endif // !BUILDING_FOR_EMBEDDED diff --git a/ceph/src/compressor/lz4/CompressionPluginLZ4.h b/ceph/src/compressor/lz4/CompressionPluginLZ4.h new file mode 100644 index 000000000..82227ae16 --- /dev/null +++ b/ceph/src/compressor/lz4/CompressionPluginLZ4.h @@ -0,0 +1,41 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 XSKY Inc. + * + * Author: Haomai Wang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#ifndef CEPH_COMPRESSION_PLUGIN_LZ4_H +#define CEPH_COMPRESSION_PLUGIN_LZ4_H + +// ----------------------------------------------------------------------------- +#include "ceph_ver.h" +#include "compressor/CompressionPlugin.h" +#include "LZ4Compressor.h" +// ----------------------------------------------------------------------------- + +class CompressionPluginLZ4 : public CompressionPlugin { + +public: + + explicit CompressionPluginLZ4(CephContext* cct) : CompressionPlugin(cct) + {} + + int factory(CompressorRef *cs, std::ostream *ss) override { + if (compressor == 0) { + LZ4Compressor *interface = new LZ4Compressor(); + compressor = CompressorRef(interface); + } + *cs = compressor; + return 0; + } +}; + +#endif diff --git a/ceph/src/compressor/lz4/LZ4Compressor.h b/ceph/src/compressor/lz4/LZ4Compressor.h new file mode 100644 index 000000000..55e816be4 --- /dev/null +++ b/ceph/src/compressor/lz4/LZ4Compressor.h @@ -0,0 +1,114 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 Haomai Wang + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_LZ4COMPRESSOR_H +#define CEPH_LZ4COMPRESSOR_H + +#include + +#include "compressor/Compressor.h" +#include "include/buffer.h" +#include "include/encoding.h" +#include "common/Tub.h" + + +class LZ4Compressor : public Compressor { + public: + LZ4Compressor() : Compressor(COMP_ALG_LZ4, "lz4") {} + + int compress(const bufferlist &src, bufferlist &dst) override { + bufferptr outptr = buffer::create_page_aligned( + LZ4_compressBound(src.length())); + LZ4_stream_t lz4_stream; + LZ4_resetStream(&lz4_stream); + + auto p = src.begin(); + size_t left = src.length(); + int pos = 0; + const char *data; + unsigned num = src.get_num_buffers(); + uint32_t origin_len; + uint32_t compressed_len; + ::encode((uint32_t)num, dst); + while (left) { + origin_len = p.get_ptr_and_advance(left, &data); + compressed_len = LZ4_compress_fast_continue( + &lz4_stream, data, outptr.c_str()+pos, origin_len, + outptr.length()-pos, 1); + if (compressed_len <= 0) + return -1; + pos += compressed_len; + left -= origin_len; + ::encode(origin_len, dst); + ::encode(compressed_len, dst); + } + assert(p.end()); + + dst.append(outptr, 0, pos); + return 0; + } + + int decompress(const bufferlist &src, bufferlist &dst) override { + bufferlist::iterator i = const_cast(src).begin(); + return decompress(i, src.length(), dst); + } + + int decompress(bufferlist::iterator &p, + size_t compressed_len, + bufferlist &dst) override { + uint32_t count; + std::vector > compressed_pairs; + ::decode(count, p); + compressed_pairs.resize(count); + uint32_t total_origin = 0; + for (unsigned i = 0; i < count; ++i) { + ::decode(compressed_pairs[i].first, p); + ::decode(compressed_pairs[i].second, p); + total_origin += compressed_pairs[i].first; + } + compressed_len -= (sizeof(uint32_t) + sizeof(uint32_t) * count * 2); + + bufferptr dstptr(total_origin); + LZ4_streamDecode_t lz4_stream_decode; + LZ4_setStreamDecode(&lz4_stream_decode, nullptr, 0); + + bufferptr cur_ptr = p.get_current_ptr(); + bufferptr *ptr = &cur_ptr; + Tub data_holder; + if (compressed_len != cur_ptr.length()) { + data_holder.construct(compressed_len); + p.copy_deep(compressed_len, *data_holder); + ptr = data_holder.get(); + } + + char *c_in = ptr->c_str(); + char *c_out = dstptr.c_str(); + for (unsigned i = 0; i < count; ++i) { + int r = LZ4_decompress_safe_continue( + &lz4_stream_decode, c_in, c_out, compressed_pairs[i].second, compressed_pairs[i].first); + if (r == (int)compressed_pairs[i].first) { + c_in += compressed_pairs[i].second; + c_out += compressed_pairs[i].first; + } else if (r < 0) { + return -1; + } else if (r != (int)compressed_pairs[i].first) { + return -2; + } + } + dst.push_back(std::move(dstptr)); + return 0; + } +}; + +#endif diff --git a/ceph/src/compressor/snappy/CompressionPluginSnappy.cc b/ceph/src/compressor/snappy/CompressionPluginSnappy.cc index f4e8c3819..6d67c41c7 100644 --- a/ceph/src/compressor/snappy/CompressionPluginSnappy.cc +++ b/ceph/src/compressor/snappy/CompressionPluginSnappy.cc @@ -38,4 +38,4 @@ int __ceph_plugin_init(CephContext *cct, return instance->add(type, name, new CompressionPluginSnappy(cct)); } -#endif // !BUILDING_FOR_EMBEDDED \ No newline at end of file +#endif // !BUILDING_FOR_EMBEDDED diff --git a/ceph/src/compressor/snappy/SnappyCompressor.h b/ceph/src/compressor/snappy/SnappyCompressor.h index aa377b510..44348f72b 100644 --- a/ceph/src/compressor/snappy/SnappyCompressor.h +++ b/ceph/src/compressor/snappy/SnappyCompressor.h @@ -17,8 +17,8 @@ #include #include -#include "include/buffer.h" #include "compressor/Compressor.h" +#include "include/buffer.h" class CEPH_BUFFER_API BufferlistSource : public snappy::Source { bufferlist::iterator pb; diff --git a/ceph/src/crush/CrushCompiler.cc b/ceph/src/crush/CrushCompiler.cc index ac5599250..a6b624566 100644 --- a/ceph/src/crush/CrushCompiler.cc +++ b/ceph/src/crush/CrushCompiler.cc @@ -8,16 +8,7 @@ #ifndef EBADE #define EBADE EFTYPE #endif - -#include -#include -#include #include -#include -#include -#include - -#include #include "common/errno.h" #include diff --git a/ceph/src/crush/CrushCompiler.h b/ceph/src/crush/CrushCompiler.h index 514648068..7bfd25995 100644 --- a/ceph/src/crush/CrushCompiler.h +++ b/ceph/src/crush/CrushCompiler.h @@ -8,8 +8,7 @@ #include "crush/grammar.h" #include -#include -#include +#include class CrushCompiler { CrushWrapper& crush; diff --git a/ceph/src/crush/CrushLocation.cc b/ceph/src/crush/CrushLocation.cc index c7e78f1ca..4831616c0 100644 --- a/ceph/src/crush/CrushLocation.cc +++ b/ceph/src/crush/CrushLocation.cc @@ -9,7 +9,7 @@ #include "common/debug.h" #include "include/compat.h" -#include +#include "common/SubProcess.h" #include diff --git a/ceph/src/crush/CrushTester.cc b/ceph/src/crush/CrushTester.cc index c6822ad1a..ef83e7311 100644 --- a/ceph/src/crush/CrushTester.cc +++ b/ceph/src/crush/CrushTester.cc @@ -18,7 +18,7 @@ #endif #include #include -#include +#include "common/SubProcess.h" void CrushTester::set_device_weight(int dev, float f) { diff --git a/ceph/src/crush/CrushTester.h b/ceph/src/crush/CrushTester.h index b05d1c3d4..b3c3b70c3 100644 --- a/ceph/src/crush/CrushTester.h +++ b/ceph/src/crush/CrushTester.h @@ -7,7 +7,6 @@ #include "crush/CrushWrapper.h" #include -#include class CrushTester { CrushWrapper& crush; diff --git a/ceph/src/crush/CrushTreeDumper.h b/ceph/src/crush/CrushTreeDumper.h index 3286fc72c..40691c697 100644 --- a/ceph/src/crush/CrushTreeDumper.h +++ b/ceph/src/crush/CrushTreeDumper.h @@ -76,8 +76,31 @@ namespace CrushTreeDumper { clear(); } + virtual bool should_dump_leaf(int i) const { + return true; + } + virtual bool should_dump_empty_bucket() const { + return true; + } + + bool should_dump(int id) { + if (id >= 0) + return should_dump_leaf(id); + if (should_dump_empty_bucket()) + return true; + int s = crush->get_bucket_size(id); + for (int k = s - 1; k >= 0; k--) { + int c = crush->get_bucket_item(id, k); + if (should_dump(c)) + return true; + } + return false; + } + bool next(Item &qi) { if (empty()) { + while (root != roots.end() && !should_dump(*root)) + ++root; if (root == roots.end()) return false; push_back(Item(*root, 0, crush->get_bucket_weightf(*root))); @@ -93,9 +116,11 @@ namespace CrushTreeDumper { int s = crush->get_bucket_size(qi.id); for (int k = s - 1; k >= 0; k--) { int id = crush->get_bucket_item(qi.id, k); - qi.children.push_back(id); - push_front(Item(id, qi.depth + 1, - crush->get_bucket_item_weightf(qi.id, k))); + if (should_dump(id)) { + qi.children.push_back(id); + push_front(Item(id, qi.depth + 1, + crush->get_bucket_item_weightf(qi.id, k))); + } } } return true; diff --git a/ceph/src/crush/CrushWrapper.cc b/ceph/src/crush/CrushWrapper.cc index ee6db9bc6..3a669e959 100644 --- a/ceph/src/crush/CrushWrapper.cc +++ b/ceph/src/crush/CrushWrapper.cc @@ -12,6 +12,65 @@ #define dout_subsys ceph_subsys_crush +bool CrushWrapper::has_legacy_rulesets() const +{ + for (unsigned i=0; imax_rules; i++) { + crush_rule *r = crush->rules[i]; + if (r && + r->mask.ruleset != i) { + return true; + } + } + return false; +} + +int CrushWrapper::renumber_rules_by_ruleset() +{ + int max_ruleset = 0; + for (unsigned i=0; imax_rules; i++) { + crush_rule *r = crush->rules[i]; + if (r && r->mask.ruleset >= max_ruleset) { + max_ruleset = r->mask.ruleset + 1; + } + } + struct crush_rule **newrules = + (crush_rule**)calloc(1, max_ruleset * sizeof(crush_rule*)); + for (unsigned i=0; imax_rules; i++) { + crush_rule *r = crush->rules[i]; + if (!r) + continue; + if (newrules[r->mask.ruleset]) { + // collision, we can't do it. + free(newrules); + return -EINVAL; + } + newrules[r->mask.ruleset] = r; + } + + // success, swap! + free(crush->rules); + crush->rules = newrules; + crush->max_rules = max_ruleset; + return 0; +} + +bool CrushWrapper::has_multirule_rulesets() const +{ + for (unsigned i=0; imax_rules; i++) { + crush_rule *r = crush->rules[i]; + if (!r) + continue; + for (unsigned j=i+1; jmax_rules; j++) { + crush_rule *s = crush->rules[j]; + if (!s) + continue; + if (r->mask.ruleset == s->mask.ruleset) + return true; + } + } + return false; +} + bool CrushWrapper::has_v2_rules() const { for (unsigned i=0; imax_rules; i++) { @@ -105,17 +164,29 @@ bool CrushWrapper::is_v5_rule(unsigned ruleid) const return false; } -bool CrushWrapper::has_chooseargs() const +bool CrushWrapper::has_choose_args() const { return !choose_args.empty(); } -bool CrushWrapper::has_incompat_chooseargs() const +bool CrushWrapper::has_incompat_choose_args() const { - // FIXME: if the chooseargs all have 1 position *and* do not remap IDs then - // we can fabricate a compatible crush map for legacy clients by swapping the - // choose_args weights in for the real weights. until then, - return has_chooseargs(); + if (choose_args.empty()) + return false; + if (choose_args.size() > 1) + return true; + crush_choose_arg_map arg_map = choose_args.begin()->second; + for (__u32 i = 0; i < arg_map.size; i++) { + crush_choose_arg *arg = &arg_map.args[i]; + if (arg->weight_set_size == 0 && + arg->ids_size == 0) + continue; + if (arg->weight_set_size != 1) + return true; + if (arg->ids_size != 0) + return true; + } + return false; } int CrushWrapper::split_id_class(int i, int *idout, int *classout) const @@ -302,11 +373,6 @@ int CrushWrapper::remove_root(int item, bool unused) int CrushWrapper::remove_item(CephContext *cct, int item, bool unlink_only) { - if (choose_args.size() > 0) { - ldout(cct, 1) << "remove_item not implemented when choose_args is not empty" << dendl; - return -EDOM; - } - ldout(cct, 5) << "remove_item " << item << (unlink_only ? " unlink_only":"") << dendl; int ret = -ENOENT; @@ -338,7 +404,7 @@ int CrushWrapper::remove_item(CephContext *cct, int item, bool unlink_only) if (id == item) { ldout(cct, 5) << "remove_item removing item " << item << " from bucket " << b->id << dendl; - crush_bucket_remove_item(crush, b, item); + bucket_remove_item(b, item); adjust_item_weight(cct, b->id, b->weight); ret = 0; } @@ -410,7 +476,7 @@ int CrushWrapper::_remove_item_under(CephContext *cct, int item, int ancestor, b int id = b->items[i]; if (id == item) { ldout(cct, 5) << "_remove_item_under removing item " << item << " from bucket " << b->id << dendl; - crush_bucket_remove_item(crush, b, item); + bucket_remove_item(b, item); adjust_item_weight(cct, b->id, b->weight); ret = 0; } else if (id < 0) { @@ -600,6 +666,20 @@ int CrushWrapper::get_full_location_ordered(int id, vector return 0; } +string CrushWrapper::get_full_location_ordered_string(int id) +{ + vector > full_location_ordered; + string full_location; + get_full_location_ordered(id, full_location_ordered); + reverse(begin(full_location_ordered), end(full_location_ordered)); + for(auto i = full_location_ordered.begin(); i != full_location_ordered.end(); i++) { + full_location = full_location + i->first + "=" + i->second; + if (i != full_location_ordered.end() - 1) { + full_location = full_location + ","; + } + } + return full_location; +} map CrushWrapper::get_parent_hierarchy(int id) { @@ -656,15 +736,68 @@ int CrushWrapper::get_children(int id, list *children) return b->size; } +int CrushWrapper::_get_leaves(int id, list *leaves) +{ + assert(leaves); -int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string name, - const map& loc) // typename -> bucketname + // Already leaf? + if (id >= 0) { + leaves->push_back(id); + return 0; + } + + crush_bucket *b = get_bucket(id); + if (IS_ERR(b)) { + return -ENOENT; + } + + for (unsigned n = 0; n < b->size; n++) { + if (b->items[n] >= 0) { + leaves->push_back(b->items[n]); + } else { + // is a bucket, do recursive call + int r = _get_leaves(b->items[n], leaves); + if (r < 0) { + return r; + } + } + } + + return 0; // all is well +} + +int CrushWrapper::get_leaves(const string &name, set *leaves) { - if (choose_args.size() > 0) { - ldout(cct, 1) << "insert_item not implemented when choose_args is not empty" << dendl; - return -EDOM; + assert(leaves); + leaves->clear(); + + if (!name_exists(name)) { + return -ENOENT; + } + + int id = get_item_id(name); + if (id >= 0) { + // already leaf + leaves->insert(id); + return 0; } + list unordered; + int r = _get_leaves(id, &unordered); + if (r < 0) { + return r; + } + + for (auto &p : unordered) { + leaves->insert(p); + } + + return 0; +} + +int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string name, + const map& loc) // typename -> bucketname +{ ldout(cct, 5) << "insert_item item " << item << " weight " << weight << " name " << name << " loc " << loc << dendl; @@ -748,7 +881,7 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n ldout(cct, 5) << "insert_item adding " << cur << " weight " << weight << " to bucket " << id << dendl; - int r = crush_bucket_add_item(crush, b, cur, 0); + int r = bucket_add_item(b, cur, 0); assert (!r); break; } @@ -768,11 +901,6 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n int CrushWrapper::move_bucket(CephContext *cct, int id, const map& loc) { - if (choose_args.size() > 0) { - ldout(cct, 1) << "move_bucket not implemented when choose_args is not empty" << dendl; - return -EDOM; - } - // sorry this only works for buckets if (id >= 0) return -EINVAL; @@ -790,13 +918,54 @@ int CrushWrapper::move_bucket(CephContext *cct, int id, const map return insert_item(cct, id, bucket_weight / (float)0x10000, id_name, loc); } -int CrushWrapper::link_bucket(CephContext *cct, int id, const map& loc) +int CrushWrapper::swap_bucket(CephContext *cct, int src, int dst) { - if (choose_args.size() > 0) { - ldout(cct, 1) << "link_bucket not implemented when choose_args is not empty" << dendl; - return -EDOM; - } + if (src >= 0 || dst >= 0) + return -EINVAL; + if (!item_exists(src) || !item_exists(dst)) + return -EINVAL; + crush_bucket *a = get_bucket(src); + crush_bucket *b = get_bucket(dst); + unsigned aw = a->weight; + unsigned bw = b->weight; + + // swap weights + adjust_item_weight(cct, a->id, bw); + adjust_item_weight(cct, b->id, aw); + + // swap items + map tmp; + unsigned as = a->size; + unsigned bs = b->size; + for (unsigned i = 0; i < as; ++i) { + int item = a->items[0]; + int itemw = crush_get_bucket_item_weight(a, 0); + tmp[item] = itemw; + bucket_remove_item(a, item); + } + assert(a->size == 0); + assert(b->size == bs); + for (unsigned i = 0; i < bs; ++i) { + int item = b->items[0]; + int itemw = crush_get_bucket_item_weight(b, 0); + bucket_remove_item(b, item); + bucket_add_item(a, item, itemw); + } + assert(a->size == bs); + assert(b->size == 0); + for (auto t : tmp) { + bucket_add_item(b, t.first, t.second); + } + assert(a->size == bs); + assert(b->size == as); + + // swap names + swap_names(src, dst); + return 0; +} +int CrushWrapper::link_bucket(CephContext *cct, int id, const map& loc) +{ // sorry this only works for buckets if (id >= 0) return -EINVAL; @@ -816,11 +985,6 @@ int CrushWrapper::link_bucket(CephContext *cct, int id, const map int CrushWrapper::create_or_move_item(CephContext *cct, int item, float weight, string name, const map& loc) // typename -> bucketname { - if (choose_args.size() > 0) { - ldout(cct, 1) << "create_or_move_item not implemented when choose_args is not empty" << dendl; - return -EDOM; - } - int ret = 0; int old_iweight; @@ -847,11 +1011,6 @@ int CrushWrapper::create_or_move_item(CephContext *cct, int item, float weight, int CrushWrapper::update_item(CephContext *cct, int item, float weight, string name, const map& loc) // typename -> bucketname { - if (choose_args.size() > 0) { - ldout(cct, 1) << "update_item not implemented when choose_args is not empty" << dendl; - return -EDOM; - } - ldout(cct, 5) << "update_item item " << item << " weight " << weight << " name " << name << " loc " << loc << dendl; int ret = 0; @@ -933,7 +1092,7 @@ int CrushWrapper::adjust_item_weight(CephContext *cct, int id, int weight) continue; for (unsigned i = 0; i < b->size; i++) { if (b->items[i] == id) { - int diff = crush_bucket_adjust_item_weight(crush, b, id, weight); + int diff = bucket_adjust_item_weight(cct, b, id, weight); ldout(cct, 5) << "adjust_item_weight " << id << " diff " << diff << " in bucket " << bidx << dendl; adjust_item_weight(cct, -1 - bidx, b->weight); changed++; @@ -957,7 +1116,7 @@ int CrushWrapper::adjust_item_weight_in_loc(CephContext *cct, int id, int weight crush_bucket *b = get_bucket(bid); for (unsigned int i = 0; i < b->size; i++) { if (b->items[i] == id) { - int diff = crush_bucket_adjust_item_weight(crush, b, id, weight); + int diff = bucket_adjust_item_weight(cct, b, id, weight); ldout(cct, 5) << "adjust_item_weight_in_loc " << id << " diff " << diff << " in bucket " << bid << dendl; adjust_item_weight(cct, bid, b->weight); changed++; @@ -985,7 +1144,7 @@ int CrushWrapper::adjust_subtree_weight(CephContext *cct, int id, int weight) for (unsigned i=0; isize; ++i) { int n = b->items[i]; if (n >= 0) { - crush_bucket_adjust_item_weight(crush, b, n, weight); + bucket_adjust_item_weight(cct, b, n, weight); ++changed; ++local_changed; } else { @@ -1057,6 +1216,17 @@ int CrushWrapper::get_immediate_parent_id(int id, int *parent) const return -ENOENT; } +int CrushWrapper::get_parent_of_type(int item, int type) const +{ + do { + int r = get_immediate_parent_id(item, &item); + if (r < 0) { + return 0; + } + } while (get_bucket_type(item) != type); + return item; +} + bool CrushWrapper::class_is_in_use(int class_id) { for (auto &i : class_bucket) @@ -1127,10 +1297,11 @@ void CrushWrapper::reweight(CephContext *cct) } } -int CrushWrapper::add_simple_ruleset_at(string name, string root_name, - string failure_domain_name, - string mode, int rule_type, - int rno, ostream *err) +int CrushWrapper::add_simple_rule_at( + string name, string root_name, + string failure_domain_name, + string mode, int rule_type, + int rno, ostream *err) { if (rule_exists(name)) { if (err) @@ -1213,13 +1384,14 @@ int CrushWrapper::add_simple_ruleset_at(string name, string root_name, return rno; } -int CrushWrapper::add_simple_ruleset(string name, string root_name, - string failure_domain_name, - string mode, int rule_type, - ostream *err) +int CrushWrapper::add_simple_rule( + string name, string root_name, + string failure_domain_name, + string mode, int rule_type, + ostream *err) { - return add_simple_ruleset_at(name, root_name, failure_domain_name, mode, - rule_type, -1, err); + return add_simple_rule_at(name, root_name, failure_domain_name, mode, + rule_type, -1, err); } int CrushWrapper::get_rule_weight_osd_map(unsigned ruleno, map *pmap) @@ -1231,6 +1403,11 @@ int CrushWrapper::get_rule_weight_osd_map(unsigned ruleno, map *pmap) crush_rule *rule = crush->rules[ruleno]; // build a weight map for each TAKE in the rule, and then merge them + + // FIXME: if there are multiple takes that place a different number of + // objects we do not take that into account. (Also, note that doing this + // right is also a function of the pool, since the crush rule + // might choose 2 + choose 2 but pool size may only be 3.) for (unsigned i=0; ilen; ++i) { map m; float sum = 0; @@ -1287,6 +1464,79 @@ int CrushWrapper::remove_rule(int ruleno) return 0; } +int CrushWrapper::bucket_adjust_item_weight(CephContext *cct, crush_bucket *bucket, int item, int weight) +{ + if (cct->_conf->osd_crush_update_weight_set) { + unsigned position; + for (position = 0; position < bucket->size; position++) + if (bucket->items[position] == item) + break; + assert(position != bucket->size); + for (auto w : choose_args) { + crush_choose_arg_map arg_map = w.second; + crush_choose_arg *arg = &arg_map.args[-1-bucket->id]; + for (__u32 j = 0; j < arg->weight_set_size; j++) { + crush_weight_set *weight_set = &arg->weight_set[j]; + weight_set->weights[position] = weight; + } + } + } + return crush_bucket_adjust_item_weight(crush, bucket, item, weight); +} + +int CrushWrapper::bucket_add_item(crush_bucket *bucket, int item, int weight) +{ + __u32 new_size = bucket->size + 1; + for (auto w : choose_args) { + crush_choose_arg_map arg_map = w.second; + crush_choose_arg *arg = &arg_map.args[-1-bucket->id]; + for (__u32 j = 0; j < arg->weight_set_size; j++) { + crush_weight_set *weight_set = &arg->weight_set[j]; + weight_set->weights = (__u32*)realloc(weight_set->weights, new_size * sizeof(__u32)); + assert(weight_set->size + 1 == new_size); + weight_set->weights[weight_set->size] = weight; + weight_set->size = new_size; + } + if (arg->ids_size) { + arg->ids = (int*)realloc(arg->ids, new_size * sizeof(int)); + assert(arg->ids_size + 1 == new_size); + arg->ids[arg->ids_size] = item; + arg->ids_size = new_size; + } + } + return crush_bucket_add_item(crush, bucket, item, weight); +} + +int CrushWrapper::bucket_remove_item(crush_bucket *bucket, int item) +{ + __u32 new_size = bucket->size - 1; + unsigned position; + for (position = 0; position < bucket->size; position++) + if (bucket->items[position] == item) + break; + assert(position != bucket->size); + for (auto w : choose_args) { + crush_choose_arg_map arg_map = w.second; + crush_choose_arg *arg = &arg_map.args[-1-bucket->id]; + for (__u32 j = 0; j < arg->weight_set_size; j++) { + crush_weight_set *weight_set = &arg->weight_set[j]; + assert(weight_set->size - 1 == new_size); + for (__u32 k = position; k < new_size; k++) + weight_set->weights[k] = weight_set->weights[k+1]; + weight_set->weights = (__u32*)realloc(weight_set->weights, new_size * sizeof(__u32)); + weight_set->size = new_size; + } + if (arg->ids_size) { + assert(arg->ids_size - 1 == new_size); + for (__u32 k = position; k < new_size; k++) + arg->ids[k] = arg->ids[k+1]; + arg->ids = (int*)realloc(arg->ids, new_size * sizeof(int)); + arg->ids_size = new_size; + } + } + return crush_bucket_remove_item(crush, bucket, item); +} + int CrushWrapper::update_device_class(CephContext *cct, int id, const string& class_name, const string& name) { int class_id = get_class_id(class_name); @@ -1341,7 +1591,7 @@ int CrushWrapper::device_class_clone(int original_id, int device_class, int *clo int weight = crush_get_bucket_item_weight(original, i); if (item >= 0) { if (class_map.count(item) != 0 && class_map[item] == device_class) { - int res = crush_bucket_add_item(crush, copy, item, weight); + int res = bucket_add_item(copy, item, weight); if (res) return res; } @@ -1353,7 +1603,7 @@ int CrushWrapper::device_class_clone(int original_id, int device_class, int *clo crush_bucket *child_copy = get_bucket(child_copy_id); if (IS_ERR(child_copy)) return -ENOENT; - res = crush_bucket_add_item(crush, copy, child_copy_id, child_copy->weight); + res = bucket_add_item(copy, child_copy_id, child_copy->weight); if (res) return res; } @@ -1394,6 +1644,16 @@ void CrushWrapper::encode(bufferlist& bl, uint64_t features) const ::encode(crush->max_rules, bl); ::encode(crush->max_devices, bl); + bool encode_compat_choose_args = false; + crush_choose_arg_map arg_map; + memset(&arg_map, '\0', sizeof(arg_map)); + if (has_choose_args() && + !HAVE_FEATURE(features, CRUSH_CHOOSE_ARGS)) { + assert(!has_incompat_choose_args()); + encode_compat_choose_args = true; + arg_map = choose_args.begin()->second; + } + // buckets for (int i=0; imax_buckets; i++) { __u32 alg = 0; @@ -1437,8 +1697,17 @@ void CrushWrapper::encode(bufferlist& bl, uint64_t features) const break; case CRUSH_BUCKET_STRAW2: - for (unsigned j=0; jbuckets[i]->size; j++) { - ::encode((reinterpret_cast(crush->buckets[i]))->item_weights[j], bl); + { + __u32 *weights; + if (encode_compat_choose_args && + arg_map.args[i].weight_set_size > 0) { + weights = arg_map.args[i].weight_set[0].weights; + } else { + weights = (reinterpret_cast(crush->buckets[i]))->item_weights; + } + for (unsigned j=0; jbuckets[i]->size; j++) { + ::encode(weights[j], bl); + } } break; @@ -2122,26 +2391,6 @@ void CrushWrapper::generate_test_instances(list& o) // fixme } -int CrushWrapper::_get_osd_pool_default_crush_replicated_ruleset(CephContext *cct, - bool quiet) -{ - int crush_ruleset = cct->_conf->osd_pool_default_crush_rule; - if (crush_ruleset == -1) { - crush_ruleset = cct->_conf->osd_pool_default_crush_replicated_ruleset; - } else if (!quiet) { - ldout(cct, 0) << "osd_pool_default_crush_rule is deprecated " - << "use osd_pool_default_crush_replicated_ruleset instead" - << dendl; - ldout(cct, 0) << "osd_pool_default_crush_rule = " - << cct->_conf-> osd_pool_default_crush_rule << " overrides " - << "osd_pool_default_crush_replicated_ruleset = " - << cct->_conf->osd_pool_default_crush_replicated_ruleset - << dendl; - } - - return crush_ruleset; -} - /** * Determine the default CRUSH ruleset ID to be used with * newly created replicated pools. @@ -2150,14 +2399,12 @@ int CrushWrapper::_get_osd_pool_default_crush_replicated_ruleset(CephContext *cc */ int CrushWrapper::get_osd_pool_default_crush_replicated_ruleset(CephContext *cct) { - int crush_ruleset = _get_osd_pool_default_crush_replicated_ruleset(cct, - false); - if (crush_ruleset == CEPH_DEFAULT_CRUSH_REPLICATED_RULESET) { + int crush_ruleset = cct->_conf->osd_pool_default_crush_rule; + if (crush_ruleset < 0) { crush_ruleset = find_first_ruleset(pg_pool_t::TYPE_REPLICATED); } else if (!ruleset_exists(crush_ruleset)) { crush_ruleset = -1; // match find_first_ruleset() retval } - return crush_ruleset; } @@ -2221,6 +2468,29 @@ int CrushWrapper::_choose_type_stack( ldout(cct, 10) << __func__ << " cumulative_fanout " << cumulative_fanout << dendl; + // identify underful targets for each intermediate level. + // this serves two purposes: + // 1. we can tell when we are selecting a bucket that does not have any underfull + // devices beneath it. that means that if the current input includes an overfull + // device, we won't be able to find an underfull device with this parent to + // swap for it. + // 2. when we decide we should reject a bucket due to the above, this list gives us + // a list of peers to consider that *do* have underfull devices available.. (we + // are careful to pick one that has the same parent.) + vector> underfull_buckets; // level -> set of buckets with >0 underfull item(s) + underfull_buckets.resize(stack.size() - 1); + for (auto osd : underfull) { + int item = osd; + for (int j = (int)stack.size() - 2; j >= 0; --j) { + int type = stack[j].first; + item = get_parent_of_type(item, type); + ldout(cct, 10) << __func__ << " underfull " << osd << " type " << type + << " is " << item << dendl; + underfull_buckets[j].insert(item); + } + } + ldout(cct, 20) << __func__ << " underfull_buckets " << underfull_buckets << dendl; + for (unsigned j = 0; j < stack.size(); ++j) { int type = stack[j].first; int fanout = stack[j].second; @@ -2232,25 +2502,22 @@ int CrushWrapper::_choose_type_stack( auto tmpi = i; for (auto from : w) { ldout(cct, 10) << " from " << from << dendl; - + // identify leaves under each choice. we use this to check whether any of these + // leaves are overfull. (if so, we need to make sure there are underfull candidates + // to swap for them.) + vector> leaves; + leaves.resize(fanout); for (int pos = 0; pos < fanout; ++pos) { if (type > 0) { // non-leaf - int item = *tmpi; - do { - int r = get_immediate_parent_id(item, &item); - if (r < 0) { - ldout(cct, 10) << __func__ << " parent of " << item << " got " - << cpp_strerror(r) << dendl; - return -EINVAL; - } - } while (get_bucket_type(item) != type); + int item = get_parent_of_type(*tmpi, type); o.push_back(item); - ldout(cct, 10) << __func__ << " from " << *tmpi << " got " << item - << " of type " << type << dendl; int n = cum_fanout; - while (n-- && tmpi != orig.end()) - ++tmpi; + while (n-- && tmpi != orig.end()) { + leaves[pos].insert(*tmpi++); + } + ldout(cct, 10) << __func__ << " from " << *tmpi << " got " << item + << " of type " << type << " over leaves " << leaves[pos] << dendl; } else { // leaf bool replaced = false; @@ -2292,6 +2559,50 @@ int CrushWrapper::_choose_type_stack( } } } + if (j + 1 < stack.size()) { + // check if any buckets have overfull leaves but no underfull candidates + for (int pos = 0; pos < fanout; ++pos) { + if (underfull_buckets[j].count(o[pos]) == 0) { + // are any leaves overfull? + bool any_overfull = false; + for (auto osd : leaves[pos]) { + if (overfull.count(osd)) { + any_overfull = true; + } + } + if (any_overfull) { + ldout(cct, 10) << " bucket " << o[pos] << " has no underfull targets and " + << ">0 leaves " << leaves[pos] << " is overfull; alts " + << underfull_buckets[j] + << dendl; + for (auto alt : underfull_buckets[j]) { + if (std::find(o.begin(), o.end(), alt) == o.end()) { + // see if alt has the same parent + if (j == 0 || + get_parent_of_type(o[pos], stack[j-1].first) == + get_parent_of_type(alt, stack[j-1].first)) { + if (j) + ldout(cct, 10) << " replacing " << o[pos] + << " (which has no underfull leaves) with " << alt + << " (same parent " + << get_parent_of_type(alt, stack[j-1].first) << " type " + << type << ")" << dendl; + else + ldout(cct, 10) << " replacing " << o[pos] + << " (which has no underfull leaves) with " << alt + << " (first level)" << dendl; + o[pos] = alt; + break; + } else { + ldout(cct, 30) << " alt " << alt << " for " << o[pos] + << " has different parent, skipping" << dendl; + } + } + } + } + } + } + } if (i == orig.end()) { ldout(cct, 10) << __func__ << " end of orig, break 2" << dendl; break; diff --git a/ceph/src/crush/CrushWrapper.h b/ceph/src/crush/CrushWrapper.h index c47a5badc..fce35ce79 100644 --- a/ceph/src/crush/CrushWrapper.h +++ b/ceph/src/crush/CrushWrapper.h @@ -20,13 +20,13 @@ extern "C" { #include "builder.h" } +#include "include/assert.h" #include "include/err.h" #include "include/encoding.h" #include "common/Mutex.h" -#include "include/assert.h" #define BUG_ON(x) assert(!(x)) namespace ceph { @@ -62,6 +62,9 @@ public: private: struct crush_map *crush; + + bool have_uniform_rules = false; + /* reverse maps */ mutable bool have_rmaps; mutable std::map type_rmap, name_rmap, rule_name_rmap; @@ -105,6 +108,15 @@ public: set_tunables_default(); } + /// true if any rule has a ruleset != the rule id + bool has_legacy_rulesets() const; + + /// fix rules whose ruleid != ruleset + int renumber_rules_by_ruleset(); + + /// true if any ruleset has more than 1 rule + bool has_multirule_rulesets() const; + // tunables void set_tunables_argonaut() { crush->choose_local_tries = 2; @@ -169,7 +181,7 @@ public: crush->straw_calc_version = 1; } void set_tunables_default() { - set_tunables_hammer(); + set_tunables_jewel(); crush->straw_calc_version = 1; } @@ -316,8 +328,8 @@ public: bool has_v3_rules() const; bool has_v4_buckets() const; bool has_v5_rules() const; - bool has_chooseargs() const; // any chooseargs - bool has_incompat_chooseargs() const; // chooseargs that can't be made compat + bool has_choose_args() const; // any choose_args + bool has_incompat_choose_args() const; // choose_args that can't be made compat bool is_v2_rule(unsigned ruleid) const; bool is_v3_rule(unsigned ruleid) const; @@ -356,6 +368,11 @@ public: int get_num_type_names() const { return type_map.size(); } + int get_max_type_id() const { + if (type_map.empty()) + return 0; + return type_map.rbegin()->first; + } int get_type_id(const string& name) const { build_rmaps(); if (type_rmap.count(name)) @@ -402,6 +419,16 @@ public: name_rmap[name] = i; return 0; } + void swap_names(int a, int b) { + string an = name_map[a]; + string bn = name_map[b]; + name_map[a] = bn; + name_map[b] = an; + if (have_rmaps) { + name_rmap[an] = b; + name_rmap[bn] = a; + } + } bool id_has_class(int i) { int idout; int classout; @@ -573,6 +600,12 @@ public: pair get_immediate_parent(int id, int *ret = NULL); int get_immediate_parent_id(int id, int *parent) const; + /** + * return ancestor of the given type, or 0 if none + * (parent is always a bucket and thus <0) + */ + int get_parent_of_type(int id, int type) const; + /** * get the fully qualified location of a device by successively finding * parents beginning at ID and ending at highest type number specified in @@ -592,6 +625,15 @@ public: */ int get_full_location_ordered(int id, vector >& path); + /* + * identical to get_full_location_ordered(int id, vector >& path), + * although it returns a concatenated string with the type/name pairs in descending + * hierarchical order with format key1=val1,key2=val2. + * + * returns the location in descending hierarchy as a string. + */ + string get_full_location_ordered_string(int id); + /** * returns (type_id, type) of all parent buckets between id and * default, can be used to check for anomolous CRUSH maps @@ -606,6 +648,15 @@ public: */ int get_children(int id, list *children); + /** + * enumerate leaves(devices) of given node + * + * @param name parent bucket name + * @return 0 on success or a negative errno on error. + */ + int get_leaves(const string &name, set *leaves); + int _get_leaves(int id, list *leaves); // worker + /** * insert an item into the map at a specific position * @@ -651,6 +702,16 @@ public: */ int move_bucket(CephContext *cct, int id, const map& loc); + /** + * swap bucket contents of two buckets without touching bucket ids + * + * @param cct cct + * @param src bucket a + * @param dst bucket b + * @return 0 for success, negative on error + */ + int swap_bucket(CephContext *cct, int src, int dst); + /** * add a link to an existing bucket in the hierarchy to the new location * @@ -936,14 +997,17 @@ public: return set_rule_step(ruleno, step, CRUSH_RULE_EMIT, 0, 0); } - int add_simple_ruleset(string name, string root_name, string failure_domain_type, - string mode, int rule_type, ostream *err = 0); + int add_simple_rule( + string name, string root_name, string failure_domain_type, + string mode, int rule_type, ostream *err = 0); + /** - * @param rno ruleset id to use, -1 to pick the lowest available + * @param rno rule[set] id to use, -1 to pick the lowest available */ - int add_simple_ruleset_at(string name, string root_name, - string failure_domain_type, string mode, - int rule_type, int rno, ostream *err = 0); + int add_simple_rule_at( + string name, string root_name, + string failure_domain_type, string mode, + int rule_type, int rno, ostream *err = 0); int remove_rule(int ruleno); @@ -1004,11 +1068,11 @@ private: if (!IS_ERR(parent_bucket)) { // zero out the bucket weight - crush_bucket_adjust_item_weight(crush, parent_bucket, item, 0); + bucket_adjust_item_weight(cct, parent_bucket, item, 0); adjust_item_weight(cct, parent_bucket->id, parent_bucket->weight); // remove the bucket from the parent - crush_bucket_remove_item(crush, parent_bucket, item); + bucket_remove_item(parent_bucket, item); } else if (PTR_ERR(parent_bucket) != -ENOENT) { return PTR_ERR(parent_bucket); } @@ -1100,10 +1164,15 @@ public: assert(b); return crush_add_bucket(crush, bucketno, b, idout); } - + + int bucket_add_item(crush_bucket *bucket, int item, int weight); + int bucket_remove_item(struct crush_bucket *bucket, int item); + int bucket_adjust_item_weight(CephContext *cct, struct crush_bucket *bucket, int item, int weight); + void finalize() { assert(crush); crush_finalize(crush); + have_uniform_rules = !has_legacy_rulesets(); } int update_device_class(CephContext *cct, int id, const string& class_name, const string& name); @@ -1145,7 +1214,14 @@ public: int find_rule(int ruleset, int type, int size) const { if (!crush) return -1; - return crush_find_rule(crush, ruleset, type, size); + if (!have_uniform_rules) { + return crush_find_rule(crush, ruleset, type, size); + } else { + if (ruleset < (int)crush->max_rules && + crush->rules[ruleset]) + return ruleset; + return -1; + } } bool ruleset_exists(int const ruleset) const { @@ -1284,8 +1360,6 @@ public: void dump_tree(Formatter *f) const; static void generate_test_instances(list& o); - int _get_osd_pool_default_crush_replicated_ruleset(CephContext *cct, - bool quiet); int get_osd_pool_default_crush_replicated_ruleset(CephContext *cct); static bool is_valid_crush_name(const string& s); diff --git a/ceph/src/crush/builder.c b/ceph/src/crush/builder.c index ec11d6c1f..dc342d28a 100644 --- a/ceph/src/crush/builder.c +++ b/ceph/src/crush/builder.c @@ -1,15 +1,12 @@ #include -#include #include #include #include #include #include -#include "include/int_types.h" - +#include "crush/crush.h" #include "builder.h" -#include "hash.h" #define dprintk(args...) /* printf(args) */ diff --git a/ceph/src/crush/builder.h b/ceph/src/crush/builder.h index e1db9a5a0..ffb5eaf22 100644 --- a/ceph/src/crush/builder.h +++ b/ceph/src/crush/builder.h @@ -1,7 +1,12 @@ #ifndef CEPH_CRUSH_BUILDER_H #define CEPH_CRUSH_BUILDER_H -#include "crush.h" +#include "include/int_types.h" + +struct crush_bucket; +struct crush_choose_arg; +struct crush_map; +struct crush_rule; /** @ingroup API * diff --git a/ceph/src/crush/crush.h b/ceph/src/crush/crush.h index 83963ef9c..31fb94def 100644 --- a/ceph/src/crush/crush.h +++ b/ceph/src/crush/crush.h @@ -506,6 +506,24 @@ static inline int crush_calc_tree_node(int i) return ((i+1) << 1)-1; } +static inline const char *crush_alg_name(int alg) +{ + switch (alg) { + case CRUSH_BUCKET_UNIFORM: + return "uniform"; + case CRUSH_BUCKET_LIST: + return "list"; + case CRUSH_BUCKET_TREE: + return "tree"; + case CRUSH_BUCKET_STRAW: + return "straw"; + case CRUSH_BUCKET_STRAW2: + return "straw2"; + default: + return "unknown"; + } +} + /* --------------------------------------------------------------------- Private --------------------------------------------------------------------- */ diff --git a/ceph/src/dmclock/CMakeLists.txt b/ceph/src/dmclock/CMakeLists.txt index 428863dc4..9444ea1e9 100644 --- a/ceph/src/dmclock/CMakeLists.txt +++ b/ceph/src/dmclock/CMakeLists.txt @@ -1,32 +1,25 @@ cmake_minimum_required(VERSION 2.8.11) -set(CMAKE_CXX_FLAGS "-std=c++11 -Wno-write-strings ${CMAKE_CXX_FLAGS}") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules") -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") - -if(DO_NOT_DELAY_TAG_CALC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDO_NOT_DELAY_TAG_CALC") -endif() - -if(K_WAY_HEAP) - if(K_WAY_HEAP LESS 2) - message(FATAL_ERROR "K_WAY_HEAP value should be at least 2") - else() - set(CMAKE_CXX_SIM_FLAGS "-DK_WAY_HEAP=${K_WAY_HEAP}") +if (NOT(TARGET gtest AND TARGET gtest_main)) + if(NOT(GTEST_FOUND)) + find_package(GTest REQUIRED) endif() endif() -if (NOT(TARGET gtest AND TARGET gtest_main)) - find_package(gtest REQUIRED) - include_directories(${GTEST_INCLUDE_DIRS}) +if (NOT(BOOST_FOUND)) + find_package(Boost REQUIRED) endif() -find_package(Boost REQUIRED) -include_directories(${Boost_INCLUDE_DIRS}) - +# add_subdirectory(support/src) add_subdirectory(src) add_subdirectory(sim) -add_subdirectory(support) enable_testing() add_subdirectory(test) +add_subdirectory(support/test) +add_test(NAME dmclock-tests + COMMAND $) +add_test(NAME dmclock-data-struct-tests + COMMAND $) diff --git a/ceph/src/dmclock/README.before-modifying-files-here-or-below b/ceph/src/dmclock/README.before-modifying-files-here-or-below new file mode 100644 index 000000000..2226512d7 --- /dev/null +++ b/ceph/src/dmclock/README.before-modifying-files-here-or-below @@ -0,0 +1,29 @@ +The dmclock is an EXTERNAL library is not wholly owned by the ceph +repo. Instead, it is brought into ceph repo via a "git subtree". + +If you are unfamiliar with this technique, PLEASE READ +../../README.git-subtree. + +IT'S VERY LIKELY YOU DO *NOT* WANT TO DIRECTLY MODIFY FILES IN OR +BELOW src/dmclock, AND THAT IF YOU DO MODIFY SUCH FILES YOUR +MODIFICATIONS WILL LIKELY BE REJECTED. + +You should only modify files below src/dmclock if: + + 1) you intend to diverge the ceph version of the dmclock library + from the external library, and + + 2) you intend for ceph developers to maintain those divergences + for the foreseeable future, even as the dmclock library evolves + and those changes are pulled into ceph. + +[Note: this file is an example of such a modification; this file is +such a divergence.] + +If you would like to submit a PR to the dmclock library itself, then +you'll want to submit a PR to: + + https://github.com/ceph/dmclock + +After that PR is merged, you would then submit a PR to ceph that does +a "git subtree pull" (see ../../README.git-subtree for details). diff --git a/ceph/src/dmclock/cmake/modules/Findboost.cmake b/ceph/src/dmclock/cmake/modules/Findboost.cmake deleted file mode 100644 index 4f0dfd052..000000000 --- a/ceph/src/dmclock/cmake/modules/Findboost.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# - Find boost - -find_path(BOOST_INCLUDE_DIR NAMES boost/variant.hpp - PATHS /usr/include /usr/local/include ${BOOST_DIR}/include) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(boost - REQUIRED_VARS BOOST_INCLUDE_DIR) - -if(boost_FOUND) - set(BOOST_FOUND 1) -endif() -if(BOOST_FOUND) - set(BOOST_INCLUDES ${BOOST_INCLUDE_DIR}) -endif() diff --git a/ceph/src/dmclock/cmake/modules/Findgtest.cmake b/ceph/src/dmclock/cmake/modules/Findgtest.cmake deleted file mode 100644 index bfe0980e4..000000000 --- a/ceph/src/dmclock/cmake/modules/Findgtest.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# - Find gtest -# -# GTEST_INCLUDE_DIRS - where to find mcas/mcas.h, etc. -# GTEST_LIBRARIES - List of libraries when using mcas. -# GTEST_FOUND - True if mcas found. -# -# GMOCK_INCLUDE_DIRS - where to find mcas/mcas.h, etc. -# GMOCK_LIBRARIES - List of libraries when using mcas. -# GMOCK_FOUND - True if mcas found. - - -## GTEST - -find_path(GTEST_INCLUDE_DIRS NAMES gtest/gtest.h - PATHS /usr/include /usr/local/include) - -find_library(GTEST_LIBRARY gtest - PATHS /usr/local/lib /usr/lib64) - -find_library(GTEST_MAIN_LIBRARY gtest_main - PATHS /usr/local/lib /usr/lib64) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(gtest - REQUIRED_VARS GTEST_LIBRARY GTEST_MAIN_LIBRARY GTEST_INCLUDE_DIRS) - -if(gtest_FOUND) - set(GTEST_FOUND 1) -endif() - -## GMOCK - -find_path(GMOCK_INCLUDE_DIRS NAMES gmock/gmock.h - PATHS /usr/include /usr/local/include) - -find_library(GMOCK_LIBRARY gmock - PATHS /usr/local/lib /usr/lib64) - -find_library(GMOCK_MAIN_LIBRARY gmock_main - PATHS /usr/local/lib /usr/lib64) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(gmock - REQUIRED_VARS GMOCK_LIBRARY GMOCK_MAIN_LIBRARY GMOCK_INCLUDE_DIRS) - -if(gmock_FOUND) - set(GMOCK_FOUND 1) -endif() diff --git a/ceph/src/dmclock/sim/CMakeLists.txt b/ceph/src/dmclock/sim/CMakeLists.txt index febd4f0ab..c088d2f1c 100644 --- a/ceph/src/dmclock/sim/CMakeLists.txt +++ b/ceph/src/dmclock/sim/CMakeLists.txt @@ -1 +1,9 @@ +if(K_WAY_HEAP) + if(K_WAY_HEAP LESS 2) + message(FATAL_ERROR "K_WAY_HEAP value should be at least 2") + else() + set(CMAKE_CXX_SIM_FLAGS "-DK_WAY_HEAP=${K_WAY_HEAP}") + endif() +endif() + add_subdirectory(src) diff --git a/ceph/src/dmclock/sim/src/sim_server.h b/ceph/src/dmclock/sim/src/sim_server.h index a61cc3204..e318d6e90 100644 --- a/ceph/src/dmclock/sim/src/sim_server.h +++ b/ceph/src/dmclock/sim/src/sim_server.h @@ -143,6 +143,8 @@ namespace crimson { } delete[] threads; + + delete priority_queue; } void post(const TestRequest& request, diff --git a/ceph/src/dmclock/sim/src/simulate.h b/ceph/src/dmclock/sim/src/simulate.h index 18e752d8a..a967d004b 100644 --- a/ceph/src/dmclock/sim/src/simulate.h +++ b/ceph/src/dmclock/sim/src/simulate.h @@ -88,6 +88,17 @@ namespace crimson { // empty } + ~Simulation() { + for (auto c : clients) { + TC* cp = c.second; + delete cp; + } + + for (auto s : servers) { + delete s.second; + } + } + uint get_client_count() const { return client_count; } uint get_server_count() const { return server_count; } TC& get_client(ClientId id) { return *clients[id]; } diff --git a/ceph/src/dmclock/sim/src/test_dmclock_main.cc b/ceph/src/dmclock/sim/src/test_dmclock_main.cc index c3ba1e18f..668869b8d 100644 --- a/ceph/src/dmclock/sim/src/test_dmclock_main.cc +++ b/ceph/src/dmclock/sim/src/test_dmclock_main.cc @@ -226,6 +226,8 @@ int main(int argc, char* argv[]) { simulation->display_stats(std::cout, &test::server_data, &test::client_data, server_disp_filter, client_disp_filter); + + delete simulation; } // main diff --git a/ceph/src/dmclock/src/CMakeLists.txt b/ceph/src/dmclock/src/CMakeLists.txt index 691e64cce..7178f266e 100644 --- a/ceph/src/dmclock/src/CMakeLists.txt +++ b/ceph/src/dmclock/src/CMakeLists.txt @@ -1,7 +1,12 @@ +include_directories(${GTEST_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(../support/src) -include_directories(${BOOST_INCLUDE_DIR}) -set(local_flags "-Wall -pthread") +set(local_flags "-std=c++11 -Wno-write-strings -Wall -pthread") + +if(DO_NOT_DELAY_TAG_CALC) + set(local_flags "${local_flags} -DDO_NOT_DELAY_TAG_CALC") +endif() set(dmc_srcs dmclock_util.cc ../support/src/run_every.cc) diff --git a/ceph/src/dmclock/src/dmclock_server.h b/ceph/src/dmclock/src/dmclock_server.h index 65013063f..8aaad3977 100644 --- a/ceph/src/dmclock/src/dmclock_server.h +++ b/ceph/src/dmclock/src/dmclock_server.h @@ -117,23 +117,24 @@ namespace crimson { RequestTag(const RequestTag& prev_tag, const ClientInfo& client, - const ReqParams& req_params, - const Time& time, + const uint32_t delta, + const uint32_t rho, + const Time time, const double cost = 0.0) : reservation(cost + tag_calc(time, prev_tag.reservation, client.reservation_inv, - req_params.rho, + rho, true)), proportion(tag_calc(time, prev_tag.proportion, client.weight_inv, - req_params.delta, + delta, true)), limit(tag_calc(time, prev_tag.limit, client.limit_inv, - req_params.delta, + delta, false)), ready(false) #ifndef DO_NOT_DELAY_TAG_CALC @@ -143,7 +144,15 @@ namespace crimson { assert(reservation < max_tag || proportion < max_tag); } - RequestTag(double _res, double _prop, double _lim, const Time& _arrival) : + RequestTag(const RequestTag& prev_tag, + const ClientInfo& client, + const ReqParams req_params, + const Time time, + const double cost = 0.0) : + RequestTag(prev_tag, client, req_params.delta, req_params.rho, time, cost) + { /* empty */ } + + RequestTag(double _res, double _prop, double _lim, const Time _arrival) : reservation(_res), proportion(_prop), limit(_lim), @@ -189,7 +198,7 @@ namespace crimson { private: - static double tag_calc(const Time& time, + static double tag_calc(const Time time, double prev, double increment, uint32_t dist_req_val, @@ -737,11 +746,11 @@ namespace crimson { // data_mtx must be held by caller - void do_add_request(RequestRef&& request, - const C& client_id, + void do_add_request(RequestRef&& request, + const C& client_id, const ReqParams& req_params, - const Time time, - const double cost = 0.0) { + const Time time, + const double cost = 0.0) { ++tick; // this pointer will help us create a reference to a shared @@ -822,8 +831,11 @@ namespace crimson { RequestTag tag(0, 0, 0, time); if (!client.has_request()) { - tag = RequestTag(client.get_req_tag(), client.info, - req_params, time, cost); + tag = RequestTag(client.get_req_tag(), + client.info, + req_params, + time, + cost); // copy tag to previous tag for client client.update_req_tag(tag, tick); @@ -867,8 +879,9 @@ namespace crimson { RequestRef& request)> process) { // gain access to data ClientRec& top = heap.top(); - ClientReq& first = top.next_request(); - RequestRef request = std::move(first.request); + + RequestRef request = std::move(top.next_request().request); + RequestTag tag = top.next_request().tag; // pop request and adjust heaps top.pop_request(); @@ -876,8 +889,8 @@ namespace crimson { #ifndef DO_NOT_DELAY_TAG_CALC if (top.has_request()) { ClientReq& next_first = top.next_request(); - next_first.tag = RequestTag(first.tag, top.info, - ReqParams(top.cur_delta, top.cur_rho), + next_first.tag = RequestTag(tag, top.info, + top.cur_delta, top.cur_rho, next_first.tag.arrival); // copy tag to previous tag for client @@ -1423,10 +1436,10 @@ namespace crimson { void add_request(typename super::RequestRef&& request, - const C& client_id, + const C& client_id, const ReqParams& req_params, - const Time time, - double addl_cost = 0.0) { + const Time time, + double addl_cost = 0.0) { typename super::DataGuard g(this->data_mtx); #ifdef PROFILE add_request_timer.start(); @@ -1577,6 +1590,7 @@ namespace crimson { void sched_at(Time when) { std::lock_guard l(sched_ahead_mtx); + if (this->finishing) return; if (TimeZero == sched_ahead_when || when < sched_ahead_when) { sched_ahead_when = when; sched_ahead_cv.notify_one(); diff --git a/ceph/src/dmclock/support/CMakeLists.txt b/ceph/src/dmclock/support/CMakeLists.txt deleted file mode 100644 index 552439ebc..000000000 --- a/ceph/src/dmclock/support/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(test) diff --git a/ceph/src/dmclock/support/src/indirect_intrusive_heap.h b/ceph/src/dmclock/support/src/indirect_intrusive_heap.h index b6075bda2..6342e29b1 100644 --- a/ceph/src/dmclock/support/src/indirect_intrusive_heap.h +++ b/ceph/src/dmclock/support/src/indirect_intrusive_heap.h @@ -243,7 +243,7 @@ namespace crimson { } void pop() { - remove(0); + remove(HeapIndex(0)); } void remove(Iterator& i) { diff --git a/ceph/src/dmclock/support/src/run_every.cc b/ceph/src/dmclock/support/src/run_every.cc index 258baaa74..cab414109 100644 --- a/ceph/src/dmclock/support/src/run_every.cc +++ b/ceph/src/dmclock/support/src/run_every.cc @@ -1,12 +1,10 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* - * Copyright (C) 2016 Red Hat Inc. + * Copyright (C) 2017 Red Hat Inc. */ -#include - #include "run_every.h" @@ -53,8 +51,17 @@ crimson::RunEvery& crimson::RunEvery::operator=(crimson::RunEvery&& other) crimson::RunEvery::~RunEvery() { - finishing = true; - cv.notify_all(); + join(); +} + + +void crimson::RunEvery::join() { + { + Guard l(mtx); + if (finishing) return; + finishing = true; + cv.notify_all(); + } thd.join(); } diff --git a/ceph/src/dmclock/support/src/run_every.h b/ceph/src/dmclock/support/src/run_every.h index 58b85563e..0d4c53857 100644 --- a/ceph/src/dmclock/support/src/run_every.h +++ b/ceph/src/dmclock/support/src/run_every.h @@ -1,7 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* - * Copyright (C) 2016 Red Hat Inc. + * Copyright (C) 2017 Red Hat Inc. */ @@ -61,6 +61,8 @@ namespace crimson { ~RunEvery(); + void join(); + protected: void run(); diff --git a/ceph/src/dmclock/support/test/CMakeLists.txt b/ceph/src/dmclock/support/test/CMakeLists.txt index addea6c96..1e1ea25cc 100644 --- a/ceph/src/dmclock/support/test/CMakeLists.txt +++ b/ceph/src/dmclock/support/test/CMakeLists.txt @@ -24,6 +24,3 @@ add_executable(dmclock-data-struct-tests ${test_srcs}) target_link_libraries(dmclock-data-struct-tests LINK_PRIVATE gtest gtest_main pthread) - -add_test(NAME dmclock-data-struct-tests - COMMAND $) diff --git a/ceph/src/dmclock/test/CMakeLists.txt b/ceph/src/dmclock/test/CMakeLists.txt index e72810b56..24da2e732 100644 --- a/ceph/src/dmclock/test/CMakeLists.txt +++ b/ceph/src/dmclock/test/CMakeLists.txt @@ -1,7 +1,6 @@ include_directories(../src) include_directories(../support/src) include_directories(../sim/src) -include_directories(${BOOST_INCLUDE_DIR}) set(support_srcs ../sim/src/test_dmclock.cc) set(test_srcs @@ -26,10 +25,7 @@ if (TARGET gtest AND TARGET gtest_main) $) else() target_link_libraries(dmclock-tests - LINK_PRIVATE $ pthread ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY}) + LINK_PRIVATE $ pthread ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) endif() add_dependencies(dmclock-tests dmclock) - -add_test(NAME dmclock-tests - COMMAND $) diff --git a/ceph/src/dmclock/test/test_test_client.cc b/ceph/src/dmclock/test/test_test_client.cc index 6015cb9bf..dd04fd179 100644 --- a/ceph/src/dmclock/test/test_test_client.cc +++ b/ceph/src/dmclock/test/test_test_client.cc @@ -61,6 +61,8 @@ TEST(test_client, full_bore_timing) { int milliseconds = (end - start) / std::chrono::milliseconds(1); EXPECT_LT(10000, milliseconds) << "timing too fast to be correct"; EXPECT_GT(12000, milliseconds) << "timing suspiciously slow"; + + delete client; } @@ -120,4 +122,6 @@ TEST(test_client, paused_timing) { EXPECT_LT(15000 - 500, milliseconds) << "timing too fast to be correct"; EXPECT_GT(17000 - 500, milliseconds) << "timing suspiciously slow"; t.join(); + + delete client; } diff --git a/ceph/src/erasure-code/ErasureCode.cc b/ceph/src/erasure-code/ErasureCode.cc index eaacb2469..353ab4f0d 100644 --- a/ceph/src/erasure-code/ErasureCode.cc +++ b/ceph/src/erasure-code/ErasureCode.cc @@ -16,14 +16,15 @@ */ #include -#include #include -#include -#include "common/strtol.h" #include "ErasureCode.h" + +#include "common/strtol.h" #include "include/buffer.h" +using namespace std; + const unsigned ErasureCode::SIMD_ALIGN = 32; int ErasureCode::sanity_check_k(int k, ostream *ss) diff --git a/ceph/src/erasure-code/ErasureCode.h b/ceph/src/erasure-code/ErasureCode.h index 6ca39d6f9..e544b022a 100644 --- a/ceph/src/erasure-code/ErasureCode.h +++ b/ceph/src/erasure-code/ErasureCode.h @@ -22,8 +22,6 @@ */ -#include - #include "ErasureCodeInterface.h" namespace ceph { @@ -32,12 +30,12 @@ namespace ceph { public: static const unsigned SIMD_ALIGN; - vector chunk_mapping; + std::vector chunk_mapping; ErasureCodeProfile _profile; ~ErasureCode() override {} - int init(ErasureCodeProfile &profile, ostream *ss) override { + int init(ErasureCodeProfile &profile, std::ostream *ss) override { _profile = profile; return 0; } @@ -46,67 +44,67 @@ namespace ceph { return _profile; } - int sanity_check_k(int k, ostream *ss); + int sanity_check_k(int k, std::ostream *ss); unsigned int get_coding_chunk_count() const override { return get_chunk_count() - get_data_chunk_count(); } - int minimum_to_decode(const set &want_to_read, - const set &available_chunks, - set *minimum) override; + int minimum_to_decode(const std::set &want_to_read, + const std::set &available_chunks, + std::set *minimum) override; - int minimum_to_decode_with_cost(const set &want_to_read, - const map &available, - set *minimum) override; + int minimum_to_decode_with_cost(const std::set &want_to_read, + const std::map &available, + std::set *minimum) override; int encode_prepare(const bufferlist &raw, - map &encoded) const; + std::map &encoded) const; - int encode(const set &want_to_encode, + int encode(const std::set &want_to_encode, const bufferlist &in, - map *encoded) override; + std::map *encoded) override; - int encode_chunks(const set &want_to_encode, - map *encoded) override; + int encode_chunks(const std::set &want_to_encode, + std::map *encoded) override; - int decode(const set &want_to_read, - const map &chunks, - map *decoded) override; + int decode(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) override; - int decode_chunks(const set &want_to_read, - const map &chunks, - map *decoded) override; + int decode_chunks(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) override; - const vector &get_chunk_mapping() const override; + const std::vector &get_chunk_mapping() const override; int to_mapping(const ErasureCodeProfile &profile, - ostream *ss); + std::ostream *ss); static int to_int(const std::string &name, ErasureCodeProfile &profile, int *value, const std::string &default_value, - ostream *ss); + std::ostream *ss); static int to_bool(const std::string &name, ErasureCodeProfile &profile, bool *value, const std::string &default_value, - ostream *ss); + std::ostream *ss); static int to_string(const std::string &name, ErasureCodeProfile &profile, std::string *value, const std::string &default_value, - ostream *ss); + std::ostream *ss); - int decode_concat(const map &chunks, + int decode_concat(const std::map &chunks, bufferlist *decoded) override; protected: int parse(const ErasureCodeProfile &profile, - ostream *ss); + std::ostream *ss); private: int chunk_index(unsigned int i) const; diff --git a/ceph/src/erasure-code/ErasureCodeInterface.h b/ceph/src/erasure-code/ErasureCodeInterface.h index 32c3b1ac2..fbe9eea27 100644 --- a/ceph/src/erasure-code/ErasureCodeInterface.h +++ b/ceph/src/erasure-code/ErasureCodeInterface.h @@ -143,19 +143,18 @@ #include #include #include -#include -#include "include/memory.h" +#include +#include +#include #include "include/buffer_fwd.h" class CrushWrapper; -using namespace std; - namespace ceph { - typedef map ErasureCodeProfile; + typedef std::map ErasureCodeProfile; - inline ostream& operator<<(ostream& out, const ErasureCodeProfile& profile) { + inline std::ostream& operator<<(std::ostream& out, const ErasureCodeProfile& profile) { out << "{"; for (ErasureCodeProfile::const_iterator it = profile.begin(); it != profile.end(); @@ -186,7 +185,7 @@ namespace ceph { * @param [out] ss contains informative messages when an error occurs * @return 0 on success or a negative errno on error. */ - virtual int init(ErasureCodeProfile &profile, ostream *ss) = 0; + virtual int init(ErasureCodeProfile &profile, std::ostream *ss) = 0; /** * Return the profile that was used to initialize the instance @@ -210,9 +209,9 @@ namespace ceph { * @param [out] ss contains informative messages when an error occurs * @return a ruleset on success or a negative errno on error. */ - virtual int create_ruleset(const string &name, + virtual int create_ruleset(const std::string &name, CrushWrapper &crush, - ostream *ss) const = 0; + std::ostream *ss) const = 0; /** * Return the number of chunks created by a call to the **encode** @@ -284,9 +283,9 @@ namespace ceph { * @param [out] minimum chunk indexes to retrieve * @return **0** on success or a negative errno on error. */ - virtual int minimum_to_decode(const set &want_to_read, - const set &available, - set *minimum) = 0; + virtual int minimum_to_decode(const std::set &want_to_read, + const std::set &available, + std::set *minimum) = 0; /** * Compute the smallest subset of **available** chunks that needs @@ -312,9 +311,9 @@ namespace ceph { * @param [out] minimum chunk indexes to retrieve * @return **0** on success or a negative errno on error. */ - virtual int minimum_to_decode_with_cost(const set &want_to_read, - const map &available, - set *minimum) = 0; + virtual int minimum_to_decode_with_cost(const std::set &want_to_read, + const std::map &available, + std::set *minimum) = 0; /** * Encode the content of **in** and store the result in @@ -351,13 +350,13 @@ namespace ceph { * @param [out] encoded map chunk indexes to chunk data * @return **0** on success or a negative errno on error. */ - virtual int encode(const set &want_to_encode, + virtual int encode(const std::set &want_to_encode, const bufferlist &in, - map *encoded) = 0; + std::map *encoded) = 0; - virtual int encode_chunks(const set &want_to_encode, - map *encoded) = 0; + virtual int encode_chunks(const std::set &want_to_encode, + std::map *encoded) = 0; /** * Decode the **chunks** and store at least **want_to_read** @@ -392,13 +391,13 @@ namespace ceph { * @param [out] decoded map chunk indexes to chunk data * @return **0** on success or a negative errno on error. */ - virtual int decode(const set &want_to_read, - const map &chunks, - map *decoded) = 0; + virtual int decode(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) = 0; - virtual int decode_chunks(const set &want_to_read, - const map &chunks, - map *decoded) = 0; + virtual int decode_chunks(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) = 0; /** * Return the ordered list of chunks or an empty vector @@ -433,7 +432,7 @@ namespace ceph { * * @return vector list of indices of chunks to be remapped */ - virtual const vector &get_chunk_mapping() const = 0; + virtual const std::vector &get_chunk_mapping() const = 0; /** * Decode the first **get_data_chunk_count()** **chunks** and @@ -445,11 +444,11 @@ namespace ceph { * @param [out] decoded concatenante of the data chunks * @return **0** on success or a negative errno on error. */ - virtual int decode_concat(const map &chunks, + virtual int decode_concat(const std::map &chunks, bufferlist *decoded) = 0; }; - typedef ceph::shared_ptr ErasureCodeInterfaceRef; + typedef std::shared_ptr ErasureCodeInterfaceRef; } diff --git a/ceph/src/erasure-code/ErasureCodePlugin.cc b/ceph/src/erasure-code/ErasureCodePlugin.cc index b120eda3a..026cd3cf6 100644 --- a/ceph/src/erasure-code/ErasureCodePlugin.cc +++ b/ceph/src/erasure-code/ErasureCodePlugin.cc @@ -23,6 +23,8 @@ #include "common/errno.h" #include "include/str_list.h" +using namespace std; + #define PLUGIN_PREFIX "libec_" #if defined(DARWIN) #define PLUGIN_SUFFIX ".dylib" diff --git a/ceph/src/erasure-code/ErasureCodePlugin.h b/ceph/src/erasure-code/ErasureCodePlugin.h index 72c187bd0..a92d0e2cc 100644 --- a/ceph/src/erasure-code/ErasureCodePlugin.h +++ b/ceph/src/erasure-code/ErasureCodePlugin.h @@ -39,7 +39,7 @@ namespace ceph { virtual int factory(const std::string &directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss) = 0; + std::ostream *ss) = 0; }; class ErasureCodePluginRegistry { @@ -62,7 +62,7 @@ namespace ceph { const std::string &directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss); + std::ostream *ss); int add(const std::string &name, ErasureCodePlugin *plugin); int remove(const std::string &name); @@ -71,11 +71,11 @@ namespace ceph { int load(const std::string &plugin_name, const std::string &directory, ErasureCodePlugin **plugin, - ostream *ss); + std::ostream *ss); int preload(const std::string &plugins, const std::string &directory, - ostream *ss); + std::ostream *ss); }; } diff --git a/ceph/src/erasure-code/isa/CMakeLists.txt b/ceph/src/erasure-code/isa/CMakeLists.txt index bdb1c4ef5..c205e367c 100644 --- a/ceph/src/erasure-code/isa/CMakeLists.txt +++ b/ceph/src/erasure-code/isa/CMakeLists.txt @@ -1,49 +1,57 @@ # ISA - -include_directories(isa-l/include) +set(isal_src_dir ${CMAKE_SOURCE_DIR}/src/isa-l) +include_directories(${isal_src_dir}/include) set(isa_srcs - isa-l/erasure_code/ec_base.c - isa-l/erasure_code/gf_2vect_dot_prod_sse.asm.s - isa-l/erasure_code/gf_3vect_dot_prod_sse.asm.s - isa-l/erasure_code/gf_4vect_dot_prod_sse.asm.s - isa-l/erasure_code/gf_5vect_dot_prod_sse.asm.s - isa-l/erasure_code/gf_6vect_dot_prod_sse.asm.s - isa-l/erasure_code/gf_vect_dot_prod_sse.asm.s - isa-l/erasure_code/gf_2vect_mad_avx2.asm.s - isa-l/erasure_code/gf_3vect_mad_avx2.asm.s - isa-l/erasure_code/gf_4vect_mad_avx2.asm.s - isa-l/erasure_code/gf_5vect_mad_avx2.asm.s - isa-l/erasure_code/gf_6vect_mad_avx2.asm.s - isa-l/erasure_code/gf_vect_mad_avx2.asm.s - isa-l/erasure_code/ec_highlevel_func.c - isa-l/erasure_code/gf_2vect_mad_avx.asm.s - isa-l/erasure_code/gf_3vect_mad_avx.asm.s - isa-l/erasure_code/gf_4vect_mad_avx.asm.s - isa-l/erasure_code/gf_5vect_mad_avx.asm.s - isa-l/erasure_code/gf_6vect_mad_avx.asm.s - isa-l/erasure_code/gf_vect_mad_avx.asm.s - isa-l/erasure_code/ec_multibinary.asm.s - isa-l/erasure_code/gf_2vect_mad_sse.asm.s - isa-l/erasure_code/gf_3vect_mad_sse.asm.s - isa-l/erasure_code/gf_4vect_mad_sse.asm.s - isa-l/erasure_code/gf_5vect_mad_sse.asm.s - isa-l/erasure_code/gf_6vect_mad_sse.asm.s - isa-l/erasure_code/gf_vect_mad_sse.asm.s - isa-l/erasure_code/gf_2vect_dot_prod_avx2.asm.s - isa-l/erasure_code/gf_3vect_dot_prod_avx2.asm.s - isa-l/erasure_code/gf_4vect_dot_prod_avx2.asm.s - isa-l/erasure_code/gf_5vect_dot_prod_avx2.asm.s - isa-l/erasure_code/gf_6vect_dot_prod_avx2.asm.s - isa-l/erasure_code/gf_vect_dot_prod_avx2.asm.s - isa-l/erasure_code/gf_vect_mul_avx.asm.s - isa-l/erasure_code/gf_2vect_dot_prod_avx.asm.s - isa-l/erasure_code/gf_3vect_dot_prod_avx.asm.s - isa-l/erasure_code/gf_4vect_dot_prod_avx.asm.s - isa-l/erasure_code/gf_5vect_dot_prod_avx.asm.s - isa-l/erasure_code/gf_6vect_dot_prod_avx.asm.s - isa-l/erasure_code/gf_vect_dot_prod_avx.asm.s - isa-l/erasure_code/gf_vect_mul_sse.asm.s + ${isal_src_dir}/erasure_code/ec_base.c + ${isal_src_dir}/erasure_code/gf_2vect_dot_prod_sse.asm + ${isal_src_dir}/erasure_code/gf_3vect_dot_prod_sse.asm + ${isal_src_dir}/erasure_code/gf_4vect_dot_prod_sse.asm + ${isal_src_dir}/erasure_code/gf_5vect_dot_prod_sse.asm + ${isal_src_dir}/erasure_code/gf_6vect_dot_prod_sse.asm + ${isal_src_dir}/erasure_code/gf_vect_dot_prod_sse.asm + ${isal_src_dir}/erasure_code/gf_2vect_mad_avx2.asm + ${isal_src_dir}/erasure_code/gf_3vect_mad_avx2.asm + ${isal_src_dir}/erasure_code/gf_4vect_mad_avx2.asm + ${isal_src_dir}/erasure_code/gf_5vect_mad_avx2.asm + ${isal_src_dir}/erasure_code/gf_6vect_mad_avx2.asm + ${isal_src_dir}/erasure_code/gf_vect_mad_avx2.asm + ${isal_src_dir}/erasure_code/ec_highlevel_func.c + ${isal_src_dir}/erasure_code/gf_2vect_mad_avx.asm + ${isal_src_dir}/erasure_code/gf_3vect_mad_avx.asm + ${isal_src_dir}/erasure_code/gf_4vect_mad_avx.asm + ${isal_src_dir}/erasure_code/gf_5vect_mad_avx.asm + ${isal_src_dir}/erasure_code/gf_6vect_mad_avx.asm + ${isal_src_dir}/erasure_code/gf_vect_mad_avx.asm + ${isal_src_dir}/erasure_code/ec_multibinary.asm + ${isal_src_dir}/erasure_code/gf_2vect_mad_sse.asm + ${isal_src_dir}/erasure_code/gf_3vect_mad_sse.asm + ${isal_src_dir}/erasure_code/gf_4vect_mad_sse.asm + ${isal_src_dir}/erasure_code/gf_5vect_mad_sse.asm + ${isal_src_dir}/erasure_code/gf_6vect_mad_sse.asm + ${isal_src_dir}/erasure_code/gf_vect_mad_sse.asm + ${isal_src_dir}/erasure_code/gf_2vect_dot_prod_avx2.asm + ${isal_src_dir}/erasure_code/gf_3vect_dot_prod_avx2.asm + ${isal_src_dir}/erasure_code/gf_4vect_dot_prod_avx2.asm + ${isal_src_dir}/erasure_code/gf_5vect_dot_prod_avx2.asm + ${isal_src_dir}/erasure_code/gf_6vect_dot_prod_avx2.asm + ${isal_src_dir}/erasure_code/gf_vect_dot_prod_avx2.asm + ${isal_src_dir}/erasure_code/gf_vect_mul_avx.asm + ${isal_src_dir}/erasure_code/gf_2vect_dot_prod_avx.asm + ${isal_src_dir}/erasure_code/gf_3vect_dot_prod_avx.asm + ${isal_src_dir}/erasure_code/gf_4vect_dot_prod_avx.asm + ${isal_src_dir}/erasure_code/gf_5vect_dot_prod_avx.asm + ${isal_src_dir}/erasure_code/gf_6vect_dot_prod_avx.asm + ${isal_src_dir}/erasure_code/gf_vect_dot_prod_avx.asm + ${isal_src_dir}/erasure_code/gf_vect_mul_sse.asm + ${isal_src_dir}/erasure_code/gf_2vect_dot_prod_avx512.asm + ${isal_src_dir}/erasure_code/gf_2vect_mad_avx512.asm + ${isal_src_dir}/erasure_code/gf_3vect_dot_prod_avx512.asm + ${isal_src_dir}/erasure_code/gf_3vect_mad_avx512.asm + ${isal_src_dir}/erasure_code/gf_4vect_dot_prod_avx512.asm + ${isal_src_dir}/erasure_code/gf_4vect_mad_avx512.asm + ${isal_src_dir}/erasure_code/gf_vect_dot_prod_avx512.asm + ${isal_src_dir}/erasure_code/gf_vect_mad_avx512.asm ErasureCodeIsa.cc ErasureCodeIsaTableCache.cc ErasureCodePluginIsa.cc @@ -56,7 +64,7 @@ add_library(ec_isa SHARED add_dependencies(ec_isa ${CMAKE_SOURCE_DIR}/src/ceph_ver.h) target_link_libraries(ec_isa ${EXTRALIBS}) set_target_properties(ec_isa PROPERTIES - VERSION 2.14.0 + VERSION 2.16.0 SOVERSION 2 INSTALL_RPATH "") install(TARGETS ec_isa DESTINATION ${erasure_plugin_dir}) diff --git a/ceph/src/erasure-code/isa/ErasureCodeIsa.cc b/ceph/src/erasure-code/isa/ErasureCodeIsa.cc index 0d69e8cb7..4a6841abd 100644 --- a/ceph/src/erasure-code/isa/ErasureCodeIsa.cc +++ b/ceph/src/erasure-code/isa/ErasureCodeIsa.cc @@ -14,7 +14,6 @@ // ----------------------------------------------------------------------------- #include -#include #include // ----------------------------------------------------------------------------- #include "common/debug.h" @@ -22,6 +21,8 @@ #include "xor_op.h" #include "crush/CrushWrapper.h" #include "osd/osd_types.h" +using namespace std; + // ----------------------------------------------------------------------------- extern "C" { #include "isa-l/include/erasure_code.h" @@ -50,12 +51,13 @@ ErasureCodeIsa::create_ruleset(const string &name, CrushWrapper &crush, ostream *ss) const { - int ruleid = crush.add_simple_ruleset(name, - ruleset_root, - ruleset_failure_domain, - "indep", - pg_pool_t::TYPE_ERASURE, - ss); + int ruleid = crush.add_simple_rule( + name, + ruleset_root, + ruleset_failure_domain, + "indep", + pg_pool_t::TYPE_ERASURE, + ss); if (ruleid < 0) return ruleid; diff --git a/ceph/src/erasure-code/isa/ErasureCodeIsa.h b/ceph/src/erasure-code/isa/ErasureCodeIsa.h index 17ba4ff30..ccf8d8437 100644 --- a/ceph/src/erasure-code/isa/ErasureCodeIsa.h +++ b/ceph/src/erasure-code/isa/ErasureCodeIsa.h @@ -26,12 +26,9 @@ #define CEPH_ERASURE_CODE_ISA_L_H // ----------------------------------------------------------------------------- -#include "common/Mutex.h" #include "erasure-code/ErasureCode.h" #include "ErasureCodeIsaTableCache.h" // ----------------------------------------------------------------------------- -#include -// ----------------------------------------------------------------------------- #define DEFAULT_RULESET_ROOT "default" #define DEFAULT_RULESET_FAILURE_DOMAIN "host" @@ -49,8 +46,8 @@ public: ErasureCodeIsaTableCache &tcache; const char *technique; - string ruleset_root; - string ruleset_failure_domain; + std::string ruleset_root; + std::string ruleset_failure_domain; ErasureCodeIsa(const char *_technique, ErasureCodeIsaTableCache &_tcache) : @@ -69,9 +66,9 @@ public: { } - int create_ruleset(const string &name, + int create_ruleset(const std::string &name, CrushWrapper &crush, - ostream *ss) const override; + std::ostream *ss) const override; unsigned int get_chunk_count() const override @@ -87,14 +84,14 @@ public: unsigned int get_chunk_size(unsigned int object_size) const override; - int encode_chunks(const set &want_to_encode, - map *encoded) override; + int encode_chunks(const std::set &want_to_encode, + std::map *encoded) override; - int decode_chunks(const set &want_to_read, - const map &chunks, - map *decoded) override; + int decode_chunks(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) override; - int init(ErasureCodeProfile &profile, ostream *ss) override; + int init(ErasureCodeProfile &profile, std::ostream *ss) override; virtual void isa_encode(char **data, char **coding, @@ -112,7 +109,7 @@ public: private: virtual int parse(ErasureCodeProfile &profile, - ostream *ss) = 0; + std::ostream *ss) = 0; }; // ----------------------------------------------------------------------------- @@ -161,7 +158,7 @@ public: private: int parse(ErasureCodeProfile &profile, - ostream *ss) override; + std::ostream *ss) override; }; #endif diff --git a/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc b/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc index 951f7d083..a4d20a6fb 100644 --- a/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc +++ b/ceph/src/erasure-code/isa/ErasureCodeIsaTableCache.cc @@ -25,7 +25,6 @@ // ----------------------------------------------------------------------------- #include "ErasureCodeIsaTableCache.h" -#include "ErasureCodeIsa.h" #include "common/debug.h" // ----------------------------------------------------------------------------- diff --git a/ceph/src/erasure-code/isa/ErasureCodePluginIsa.cc b/ceph/src/erasure-code/isa/ErasureCodePluginIsa.cc index 1e95b0bc6..0641f457d 100644 --- a/ceph/src/erasure-code/isa/ErasureCodePluginIsa.cc +++ b/ceph/src/erasure-code/isa/ErasureCodePluginIsa.cc @@ -25,7 +25,7 @@ // ----------------------------------------------------------------------------- #include "ceph_ver.h" -#include "common/debug.h" +#include "include/buffer.h" #include "ErasureCodePluginIsa.h" #include "ErasureCodeIsa.h" // ----------------------------------------------------------------------------- @@ -33,7 +33,7 @@ int ErasureCodePluginIsa::factory(const std::string &directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss) + std::ostream *ss) { ErasureCodeIsa *interface; std::string t; @@ -83,4 +83,4 @@ int __erasure_code_init(char *plugin_name, char *directory) return instance.add(plugin_name, new ErasureCodePluginIsa()); } -#endif \ No newline at end of file +#endif diff --git a/ceph/src/erasure-code/isa/ErasureCodePluginIsa.h b/ceph/src/erasure-code/isa/ErasureCodePluginIsa.h index cbe841a6d..fc52e10bf 100644 --- a/ceph/src/erasure-code/isa/ErasureCodePluginIsa.h +++ b/ceph/src/erasure-code/isa/ErasureCodePluginIsa.h @@ -28,7 +28,7 @@ public: int factory(const std::string &directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss) override; + std::ostream *ss) override; }; #endif diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.c b/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.c deleted file mode 100644 index 3c7e8382c..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.c +++ /dev/null @@ -1,348 +0,0 @@ -/********************************************************************** - Copyright(c) 2011-2015 Intel Corporation All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************/ - -#include -#include // for memset -#include "erasure_code.h" -#include "ec_base.h" // for GF tables -#include "types.h" - -unsigned char gf_mul(unsigned char a, unsigned char b) -{ -#ifndef GF_LARGE_TABLES - int i; - - if ((a == 0) || (b == 0)) - return 0; - - return gff_base[(i = gflog_base[a] + gflog_base[b]) > 254 ? i - 255 : i]; -#else - return gf_mul_table_base[b * 256 + a]; -#endif -} - -unsigned char gf_inv(unsigned char a) -{ -#ifndef GF_LARGE_TABLES - if (a == 0) - return 0; - - return gff_base[255 - gflog_base[a]]; -#else - return gf_inv_table_base[a]; -#endif -} - -void gf_gen_rs_matrix(unsigned char *a, int m, int k) -{ - int i, j; - unsigned char p, gen = 1; - - memset(a, 0, k * m); - for (i = 0; i < k; i++) - a[k * i + i] = 1; - - for (i = k; i < m; i++) { - p = 1; - for (j = 0; j < k; j++) { - a[k * i + j] = p; - p = gf_mul(p, gen); - } - gen = gf_mul(gen, 2); - } -} - -void gf_gen_cauchy1_matrix(unsigned char *a, int m, int k) -{ - int i, j; - unsigned char *p; - - // Identity matrix in high position - memset(a, 0, k * m); - for (i = 0; i < k; i++) - a[k * i + i] = 1; - - // For the rest choose 1/(i + j) | i != j - p = &a[k * k]; - for (i = k; i < m; i++) - for (j = 0; j < k; j++) - *p++ = gf_inv(i ^ j); - -} - -int gf_invert_matrix(unsigned char *in_mat, unsigned char *out_mat, const int n) -{ - int i, j, k; - unsigned char temp; - - // Set out_mat[] to the identity matrix - for (i = 0; i < n * n; i++) // memset(out_mat, 0, n*n) - out_mat[i] = 0; - - for (i = 0; i < n; i++) - out_mat[i * n + i] = 1; - - // Inverse - for (i = 0; i < n; i++) { - // Check for 0 in pivot element - if (in_mat[i * n + i] == 0) { - // Find a row with non-zero in current column and swap - for (j = i + 1; j < n; j++) - if (in_mat[j * n + i]) - break; - - if (j == n) // Couldn't find means it's singular - return -1; - - for (k = 0; k < n; k++) { // Swap rows i,j - temp = in_mat[i * n + k]; - in_mat[i * n + k] = in_mat[j * n + k]; - in_mat[j * n + k] = temp; - - temp = out_mat[i * n + k]; - out_mat[i * n + k] = out_mat[j * n + k]; - out_mat[j * n + k] = temp; - } - } - - temp = gf_inv(in_mat[i * n + i]); // 1/pivot - for (j = 0; j < n; j++) { // Scale row i by 1/pivot - in_mat[i * n + j] = gf_mul(in_mat[i * n + j], temp); - out_mat[i * n + j] = gf_mul(out_mat[i * n + j], temp); - } - - for (j = 0; j < n; j++) { - if (j == i) - continue; - - temp = in_mat[j * n + i]; - for (k = 0; k < n; k++) { - out_mat[j * n + k] ^= gf_mul(temp, out_mat[i * n + k]); - in_mat[j * n + k] ^= gf_mul(temp, in_mat[i * n + k]); - } - } - } - return 0; -} - -// Calculates const table gftbl in GF(2^8) from single input A -// gftbl(A) = {A{00}, A{01}, A{02}, ... , A{0f} }, {A{00}, A{10}, A{20}, ... , A{f0} } - -void gf_vect_mul_init(unsigned char c, unsigned char *tbl) -{ - unsigned char c2 = (c << 1) ^ ((c & 0x80) ? 0x1d : 0); //Mult by GF{2} - unsigned char c4 = (c2 << 1) ^ ((c2 & 0x80) ? 0x1d : 0); //Mult by GF{2} - unsigned char c8 = (c4 << 1) ^ ((c4 & 0x80) ? 0x1d : 0); //Mult by GF{2} - -#if __WORDSIZE == 64 || _WIN64 || __x86_64__ - unsigned long long v1, v2, v4, v8, *t; - unsigned long long v10, v20, v40, v80; - unsigned char c17, c18, c20, c24; - - t = (unsigned long long *)tbl; - - v1 = c * 0x0100010001000100ull; - v2 = c2 * 0x0101000001010000ull; - v4 = c4 * 0x0101010100000000ull; - v8 = c8 * 0x0101010101010101ull; - - v4 = v1 ^ v2 ^ v4; - t[0] = v4; - t[1] = v8 ^ v4; - - c17 = (c8 << 1) ^ ((c8 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c18 = (c17 << 1) ^ ((c17 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c20 = (c18 << 1) ^ ((c18 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c24 = (c20 << 1) ^ ((c20 & 0x80) ? 0x1d : 0); //Mult by GF{2} - - v10 = c17 * 0x0100010001000100ull; - v20 = c18 * 0x0101000001010000ull; - v40 = c20 * 0x0101010100000000ull; - v80 = c24 * 0x0101010101010101ull; - - v40 = v10 ^ v20 ^ v40; - t[2] = v40; - t[3] = v80 ^ v40; - -#else // 32-bit or other - unsigned char c3, c5, c6, c7, c9, c10, c11, c12, c13, c14, c15; - unsigned char c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, - c31; - - c3 = c2 ^ c; - c5 = c4 ^ c; - c6 = c4 ^ c2; - c7 = c4 ^ c3; - - c9 = c8 ^ c; - c10 = c8 ^ c2; - c11 = c8 ^ c3; - c12 = c8 ^ c4; - c13 = c8 ^ c5; - c14 = c8 ^ c6; - c15 = c8 ^ c7; - - tbl[0] = 0; - tbl[1] = c; - tbl[2] = c2; - tbl[3] = c3; - tbl[4] = c4; - tbl[5] = c5; - tbl[6] = c6; - tbl[7] = c7; - tbl[8] = c8; - tbl[9] = c9; - tbl[10] = c10; - tbl[11] = c11; - tbl[12] = c12; - tbl[13] = c13; - tbl[14] = c14; - tbl[15] = c15; - - c17 = (c8 << 1) ^ ((c8 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c18 = (c17 << 1) ^ ((c17 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c19 = c18 ^ c17; - c20 = (c18 << 1) ^ ((c18 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c21 = c20 ^ c17; - c22 = c20 ^ c18; - c23 = c20 ^ c19; - c24 = (c20 << 1) ^ ((c20 & 0x80) ? 0x1d : 0); //Mult by GF{2} - c25 = c24 ^ c17; - c26 = c24 ^ c18; - c27 = c24 ^ c19; - c28 = c24 ^ c20; - c29 = c24 ^ c21; - c30 = c24 ^ c22; - c31 = c24 ^ c23; - - tbl[16] = 0; - tbl[17] = c17; - tbl[18] = c18; - tbl[19] = c19; - tbl[20] = c20; - tbl[21] = c21; - tbl[22] = c22; - tbl[23] = c23; - tbl[24] = c24; - tbl[25] = c25; - tbl[26] = c26; - tbl[27] = c27; - tbl[28] = c28; - tbl[29] = c29; - tbl[30] = c30; - tbl[31] = c31; - -#endif //__WORDSIZE == 64 || _WIN64 || __x86_64__ -} - -void gf_vect_dot_prod_base(int len, int vlen, unsigned char *v, - unsigned char **src, unsigned char *dest) -{ - int i, j; - unsigned char s; - for (i = 0; i < len; i++) { - s = 0; - for (j = 0; j < vlen; j++) - s ^= gf_mul(src[j][i], v[j * 32 + 1]); - - dest[i] = s; - } -} - -void gf_vect_mad_base(int len, int vec, int vec_i, - unsigned char *v, unsigned char *src, unsigned char *dest) -{ - int i; - unsigned char s; - for (i = 0; i < len; i++) { - s = dest[i]; - s ^= gf_mul(src[i], v[vec_i * 32 + 1]); - dest[i] = s; - } -} - -void ec_encode_data_base(int len, int srcs, int dests, unsigned char *v, - unsigned char **src, unsigned char **dest) -{ - int i, j, l; - unsigned char s; - - for (l = 0; l < dests; l++) { - for (i = 0; i < len; i++) { - s = 0; - for (j = 0; j < srcs; j++) - s ^= gf_mul(src[j][i], v[j * 32 + l * srcs * 32 + 1]); - - dest[l][i] = s; - } - } -} - -void ec_encode_data_update_base(int len, int k, int rows, int vec_i, unsigned char *v, - unsigned char *data, unsigned char **dest) -{ - int i, l; - unsigned char s; - - for (l = 0; l < rows; l++) { - for (i = 0; i < len; i++) { - s = dest[l][i]; - s ^= gf_mul(data[i], v[vec_i * 32 + l * k * 32 + 1]); - - dest[l][i] = s; - } - } -} - -void gf_vect_mul_base(int len, unsigned char *a, unsigned char *src, unsigned char *dest) -{ - //2nd element of table array is ref value used to fill it in - unsigned char c = a[1]; - while (len-- > 0) - *dest++ = gf_mul(c, *src++); -} - -struct slver { - UINT16 snum; - UINT8 ver; - UINT8 core; -}; - -// Version info -struct slver gf_vect_mul_init_slver_00020035; -struct slver gf_vect_mul_init_slver = { 0x0035, 0x02, 0x00 }; - -struct slver ec_encode_data_base_slver_00010135; -struct slver ec_encode_data_base_slver = { 0x0135, 0x01, 0x00 }; - -struct slver gf_vect_mul_base_slver_00010136; -struct slver gf_vect_mul_base_slver = { 0x0136, 0x01, 0x00 }; - -struct slver gf_vect_dot_prod_base_slver_00010137; -struct slver gf_vect_dot_prod_base_slver = { 0x0137, 0x01, 0x00 }; diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.h b/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.h deleted file mode 100644 index d69a92d67..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_base.h +++ /dev/null @@ -1,6680 +0,0 @@ -/********************************************************************** - Copyright(c) 2011-2015 Intel Corporation All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************/ - -#ifndef _EC_BASE_H_ -#define _EC_BASE_H_ - -// Global GF(256) tables -#ifndef GF_LARGE_TABLES -unsigned char gff_base[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, - 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c, 0x98, 0x2d, 0x5a, - 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, - 0x60, 0xc0, 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, - 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46, 0x8c, - 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, - 0xb9, 0x6f, 0xde, 0xa1, 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, - 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, - 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, - 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9, 0xaf, 0x43, 0x86, - 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, - 0x67, 0xce, 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, - 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85, 0x17, - 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, - 0x84, 0x15, 0x2a, 0x54, 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, - 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, - 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, - 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3, 0xdb, 0xab, 0x4b, - 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, - 0xae, 0x41, 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, - 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51, 0xa2, - 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, - 0xac, 0x45, 0x8a, 0x09, 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, - 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, - 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, - 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01 -}; - -unsigned char gflog_base[] = { - 0x00, 0xff, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, - 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x04, 0x64, 0xe0, 0x0e, - 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, - 0x4c, 0x71, 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, - 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d, 0xb5, - 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, - 0x4d, 0xe4, 0x72, 0xa6, 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, - 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, - 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, - 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 0x1e, 0x42, 0xb6, 0xa3, - 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, - 0xba, 0x3d, 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, - 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 0x07, 0x70, - 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, - 0x31, 0xc5, 0xfe, 0x18, 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, - 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, - 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, - 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 0xf2, 0x56, 0xd3, 0xab, - 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, - 0x41, 0xa2, 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, - 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 0x6c, 0xa1, - 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, - 0xbb, 0xcc, 0x3e, 0x5a, 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, - 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, - 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, - 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf -}; -#else -unsigned char gf_mul_table_base[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, - 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, - 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, - 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, - 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, - 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, - 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, - 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, - 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, - 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, - 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, - 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, - 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, - 0xfe, 0xff, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, - 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, - 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, - 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, - 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, - 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, - 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, - 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, - 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, - 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc2, - 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, - 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, - 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, - 0x1d, 0x1f, 0x19, 0x1b, 0x15, 0x17, 0x11, 0x13, 0x0d, 0x0f, - 0x09, 0x0b, 0x05, 0x07, 0x01, 0x03, 0x3d, 0x3f, 0x39, 0x3b, - 0x35, 0x37, 0x31, 0x33, 0x2d, 0x2f, 0x29, 0x2b, 0x25, 0x27, - 0x21, 0x23, 0x5d, 0x5f, 0x59, 0x5b, 0x55, 0x57, 0x51, 0x53, - 0x4d, 0x4f, 0x49, 0x4b, 0x45, 0x47, 0x41, 0x43, 0x7d, 0x7f, - 0x79, 0x7b, 0x75, 0x77, 0x71, 0x73, 0x6d, 0x6f, 0x69, 0x6b, - 0x65, 0x67, 0x61, 0x63, 0x9d, 0x9f, 0x99, 0x9b, 0x95, 0x97, - 0x91, 0x93, 0x8d, 0x8f, 0x89, 0x8b, 0x85, 0x87, 0x81, 0x83, - 0xbd, 0xbf, 0xb9, 0xbb, 0xb5, 0xb7, 0xb1, 0xb3, 0xad, 0xaf, - 0xa9, 0xab, 0xa5, 0xa7, 0xa1, 0xa3, 0xdd, 0xdf, 0xd9, 0xdb, - 0xd5, 0xd7, 0xd1, 0xd3, 0xcd, 0xcf, 0xc9, 0xcb, 0xc5, 0xc7, - 0xc1, 0xc3, 0xfd, 0xff, 0xf9, 0xfb, 0xf5, 0xf7, 0xf1, 0xf3, - 0xed, 0xef, 0xe9, 0xeb, 0xe5, 0xe7, 0xe1, 0xe3, 0x00, 0x03, - 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, - 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, - 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, - 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, - 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, 0x50, 0x53, 0x56, 0x55, - 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, - 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, - 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, - 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, - 0xe4, 0xe7, 0xe2, 0xe1, 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, - 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, - 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, - 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9d, 0x9e, 0x9b, 0x98, - 0x91, 0x92, 0x97, 0x94, 0x85, 0x86, 0x83, 0x80, 0x89, 0x8a, - 0x8f, 0x8c, 0xad, 0xae, 0xab, 0xa8, 0xa1, 0xa2, 0xa7, 0xa4, - 0xb5, 0xb6, 0xb3, 0xb0, 0xb9, 0xba, 0xbf, 0xbc, 0xfd, 0xfe, - 0xfb, 0xf8, 0xf1, 0xf2, 0xf7, 0xf4, 0xe5, 0xe6, 0xe3, 0xe0, - 0xe9, 0xea, 0xef, 0xec, 0xcd, 0xce, 0xcb, 0xc8, 0xc1, 0xc2, - 0xc7, 0xc4, 0xd5, 0xd6, 0xd3, 0xd0, 0xd9, 0xda, 0xdf, 0xdc, - 0x5d, 0x5e, 0x5b, 0x58, 0x51, 0x52, 0x57, 0x54, 0x45, 0x46, - 0x43, 0x40, 0x49, 0x4a, 0x4f, 0x4c, 0x6d, 0x6e, 0x6b, 0x68, - 0x61, 0x62, 0x67, 0x64, 0x75, 0x76, 0x73, 0x70, 0x79, 0x7a, - 0x7f, 0x7c, 0x3d, 0x3e, 0x3b, 0x38, 0x31, 0x32, 0x37, 0x34, - 0x25, 0x26, 0x23, 0x20, 0x29, 0x2a, 0x2f, 0x2c, 0x0d, 0x0e, - 0x0b, 0x08, 0x01, 0x02, 0x07, 0x04, 0x15, 0x16, 0x13, 0x10, - 0x19, 0x1a, 0x1f, 0x1c, 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, - 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, - 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c, 0x60, 0x64, - 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, 0x80, 0x84, 0x88, 0x8c, - 0x90, 0x94, 0x98, 0x9c, 0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, - 0xb8, 0xbc, 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc, - 0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc, 0x1d, 0x19, - 0x15, 0x11, 0x0d, 0x09, 0x05, 0x01, 0x3d, 0x39, 0x35, 0x31, - 0x2d, 0x29, 0x25, 0x21, 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, - 0x45, 0x41, 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61, - 0x9d, 0x99, 0x95, 0x91, 0x8d, 0x89, 0x85, 0x81, 0xbd, 0xb9, - 0xb5, 0xb1, 0xad, 0xa9, 0xa5, 0xa1, 0xdd, 0xd9, 0xd5, 0xd1, - 0xcd, 0xc9, 0xc5, 0xc1, 0xfd, 0xf9, 0xf5, 0xf1, 0xed, 0xe9, - 0xe5, 0xe1, 0x3a, 0x3e, 0x32, 0x36, 0x2a, 0x2e, 0x22, 0x26, - 0x1a, 0x1e, 0x12, 0x16, 0x0a, 0x0e, 0x02, 0x06, 0x7a, 0x7e, - 0x72, 0x76, 0x6a, 0x6e, 0x62, 0x66, 0x5a, 0x5e, 0x52, 0x56, - 0x4a, 0x4e, 0x42, 0x46, 0xba, 0xbe, 0xb2, 0xb6, 0xaa, 0xae, - 0xa2, 0xa6, 0x9a, 0x9e, 0x92, 0x96, 0x8a, 0x8e, 0x82, 0x86, - 0xfa, 0xfe, 0xf2, 0xf6, 0xea, 0xee, 0xe2, 0xe6, 0xda, 0xde, - 0xd2, 0xd6, 0xca, 0xce, 0xc2, 0xc6, 0x27, 0x23, 0x2f, 0x2b, - 0x37, 0x33, 0x3f, 0x3b, 0x07, 0x03, 0x0f, 0x0b, 0x17, 0x13, - 0x1f, 0x1b, 0x67, 0x63, 0x6f, 0x6b, 0x77, 0x73, 0x7f, 0x7b, - 0x47, 0x43, 0x4f, 0x4b, 0x57, 0x53, 0x5f, 0x5b, 0xa7, 0xa3, - 0xaf, 0xab, 0xb7, 0xb3, 0xbf, 0xbb, 0x87, 0x83, 0x8f, 0x8b, - 0x97, 0x93, 0x9f, 0x9b, 0xe7, 0xe3, 0xef, 0xeb, 0xf7, 0xf3, - 0xff, 0xfb, 0xc7, 0xc3, 0xcf, 0xcb, 0xd7, 0xd3, 0xdf, 0xdb, - 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, - 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33, 0x50, 0x55, 0x5a, 0x5f, - 0x44, 0x41, 0x4e, 0x4b, 0x78, 0x7d, 0x72, 0x77, 0x6c, 0x69, - 0x66, 0x63, 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb1, 0xbe, 0xbb, - 0x88, 0x8d, 0x82, 0x87, 0x9c, 0x99, 0x96, 0x93, 0xf0, 0xf5, - 0xfa, 0xff, 0xe4, 0xe1, 0xee, 0xeb, 0xd8, 0xdd, 0xd2, 0xd7, - 0xcc, 0xc9, 0xc6, 0xc3, 0x5d, 0x58, 0x57, 0x52, 0x49, 0x4c, - 0x43, 0x46, 0x75, 0x70, 0x7f, 0x7a, 0x61, 0x64, 0x6b, 0x6e, - 0x0d, 0x08, 0x07, 0x02, 0x19, 0x1c, 0x13, 0x16, 0x25, 0x20, - 0x2f, 0x2a, 0x31, 0x34, 0x3b, 0x3e, 0xfd, 0xf8, 0xf7, 0xf2, - 0xe9, 0xec, 0xe3, 0xe6, 0xd5, 0xd0, 0xdf, 0xda, 0xc1, 0xc4, - 0xcb, 0xce, 0xad, 0xa8, 0xa7, 0xa2, 0xb9, 0xbc, 0xb3, 0xb6, - 0x85, 0x80, 0x8f, 0x8a, 0x91, 0x94, 0x9b, 0x9e, 0xba, 0xbf, - 0xb0, 0xb5, 0xae, 0xab, 0xa4, 0xa1, 0x92, 0x97, 0x98, 0x9d, - 0x86, 0x83, 0x8c, 0x89, 0xea, 0xef, 0xe0, 0xe5, 0xfe, 0xfb, - 0xf4, 0xf1, 0xc2, 0xc7, 0xc8, 0xcd, 0xd6, 0xd3, 0xdc, 0xd9, - 0x1a, 0x1f, 0x10, 0x15, 0x0e, 0x0b, 0x04, 0x01, 0x32, 0x37, - 0x38, 0x3d, 0x26, 0x23, 0x2c, 0x29, 0x4a, 0x4f, 0x40, 0x45, - 0x5e, 0x5b, 0x54, 0x51, 0x62, 0x67, 0x68, 0x6d, 0x76, 0x73, - 0x7c, 0x79, 0xe7, 0xe2, 0xed, 0xe8, 0xf3, 0xf6, 0xf9, 0xfc, - 0xcf, 0xca, 0xc5, 0xc0, 0xdb, 0xde, 0xd1, 0xd4, 0xb7, 0xb2, - 0xbd, 0xb8, 0xa3, 0xa6, 0xa9, 0xac, 0x9f, 0x9a, 0x95, 0x90, - 0x8b, 0x8e, 0x81, 0x84, 0x47, 0x42, 0x4d, 0x48, 0x53, 0x56, - 0x59, 0x5c, 0x6f, 0x6a, 0x65, 0x60, 0x7b, 0x7e, 0x71, 0x74, - 0x17, 0x12, 0x1d, 0x18, 0x03, 0x06, 0x09, 0x0c, 0x3f, 0x3a, - 0x35, 0x30, 0x2b, 0x2e, 0x21, 0x24, 0x00, 0x06, 0x0c, 0x0a, - 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, - 0x24, 0x22, 0x60, 0x66, 0x6c, 0x6a, 0x78, 0x7e, 0x74, 0x72, - 0x50, 0x56, 0x5c, 0x5a, 0x48, 0x4e, 0x44, 0x42, 0xc0, 0xc6, - 0xcc, 0xca, 0xd8, 0xde, 0xd4, 0xd2, 0xf0, 0xf6, 0xfc, 0xfa, - 0xe8, 0xee, 0xe4, 0xe2, 0xa0, 0xa6, 0xac, 0xaa, 0xb8, 0xbe, - 0xb4, 0xb2, 0x90, 0x96, 0x9c, 0x9a, 0x88, 0x8e, 0x84, 0x82, - 0x9d, 0x9b, 0x91, 0x97, 0x85, 0x83, 0x89, 0x8f, 0xad, 0xab, - 0xa1, 0xa7, 0xb5, 0xb3, 0xb9, 0xbf, 0xfd, 0xfb, 0xf1, 0xf7, - 0xe5, 0xe3, 0xe9, 0xef, 0xcd, 0xcb, 0xc1, 0xc7, 0xd5, 0xd3, - 0xd9, 0xdf, 0x5d, 0x5b, 0x51, 0x57, 0x45, 0x43, 0x49, 0x4f, - 0x6d, 0x6b, 0x61, 0x67, 0x75, 0x73, 0x79, 0x7f, 0x3d, 0x3b, - 0x31, 0x37, 0x25, 0x23, 0x29, 0x2f, 0x0d, 0x0b, 0x01, 0x07, - 0x15, 0x13, 0x19, 0x1f, 0x27, 0x21, 0x2b, 0x2d, 0x3f, 0x39, - 0x33, 0x35, 0x17, 0x11, 0x1b, 0x1d, 0x0f, 0x09, 0x03, 0x05, - 0x47, 0x41, 0x4b, 0x4d, 0x5f, 0x59, 0x53, 0x55, 0x77, 0x71, - 0x7b, 0x7d, 0x6f, 0x69, 0x63, 0x65, 0xe7, 0xe1, 0xeb, 0xed, - 0xff, 0xf9, 0xf3, 0xf5, 0xd7, 0xd1, 0xdb, 0xdd, 0xcf, 0xc9, - 0xc3, 0xc5, 0x87, 0x81, 0x8b, 0x8d, 0x9f, 0x99, 0x93, 0x95, - 0xb7, 0xb1, 0xbb, 0xbd, 0xaf, 0xa9, 0xa3, 0xa5, 0xba, 0xbc, - 0xb6, 0xb0, 0xa2, 0xa4, 0xae, 0xa8, 0x8a, 0x8c, 0x86, 0x80, - 0x92, 0x94, 0x9e, 0x98, 0xda, 0xdc, 0xd6, 0xd0, 0xc2, 0xc4, - 0xce, 0xc8, 0xea, 0xec, 0xe6, 0xe0, 0xf2, 0xf4, 0xfe, 0xf8, - 0x7a, 0x7c, 0x76, 0x70, 0x62, 0x64, 0x6e, 0x68, 0x4a, 0x4c, - 0x46, 0x40, 0x52, 0x54, 0x5e, 0x58, 0x1a, 0x1c, 0x16, 0x10, - 0x02, 0x04, 0x0e, 0x08, 0x2a, 0x2c, 0x26, 0x20, 0x32, 0x34, - 0x3e, 0x38, 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, - 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, - 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, - 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, - 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, - 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, - 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xdd, 0xda, 0xd3, 0xd4, - 0xc1, 0xc6, 0xcf, 0xc8, 0xe5, 0xe2, 0xeb, 0xec, 0xf9, 0xfe, - 0xf7, 0xf0, 0xad, 0xaa, 0xa3, 0xa4, 0xb1, 0xb6, 0xbf, 0xb8, - 0x95, 0x92, 0x9b, 0x9c, 0x89, 0x8e, 0x87, 0x80, 0x3d, 0x3a, - 0x33, 0x34, 0x21, 0x26, 0x2f, 0x28, 0x05, 0x02, 0x0b, 0x0c, - 0x19, 0x1e, 0x17, 0x10, 0x4d, 0x4a, 0x43, 0x44, 0x51, 0x56, - 0x5f, 0x58, 0x75, 0x72, 0x7b, 0x7c, 0x69, 0x6e, 0x67, 0x60, - 0xa7, 0xa0, 0xa9, 0xae, 0xbb, 0xbc, 0xb5, 0xb2, 0x9f, 0x98, - 0x91, 0x96, 0x83, 0x84, 0x8d, 0x8a, 0xd7, 0xd0, 0xd9, 0xde, - 0xcb, 0xcc, 0xc5, 0xc2, 0xef, 0xe8, 0xe1, 0xe6, 0xf3, 0xf4, - 0xfd, 0xfa, 0x47, 0x40, 0x49, 0x4e, 0x5b, 0x5c, 0x55, 0x52, - 0x7f, 0x78, 0x71, 0x76, 0x63, 0x64, 0x6d, 0x6a, 0x37, 0x30, - 0x39, 0x3e, 0x2b, 0x2c, 0x25, 0x22, 0x0f, 0x08, 0x01, 0x06, - 0x13, 0x14, 0x1d, 0x1a, 0x7a, 0x7d, 0x74, 0x73, 0x66, 0x61, - 0x68, 0x6f, 0x42, 0x45, 0x4c, 0x4b, 0x5e, 0x59, 0x50, 0x57, - 0x0a, 0x0d, 0x04, 0x03, 0x16, 0x11, 0x18, 0x1f, 0x32, 0x35, - 0x3c, 0x3b, 0x2e, 0x29, 0x20, 0x27, 0x9a, 0x9d, 0x94, 0x93, - 0x86, 0x81, 0x88, 0x8f, 0xa2, 0xa5, 0xac, 0xab, 0xbe, 0xb9, - 0xb0, 0xb7, 0xea, 0xed, 0xe4, 0xe3, 0xf6, 0xf1, 0xf8, 0xff, - 0xd2, 0xd5, 0xdc, 0xdb, 0xce, 0xc9, 0xc0, 0xc7, 0x00, 0x08, - 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, - 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, - 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, - 0x1d, 0x15, 0x0d, 0x05, 0x3d, 0x35, 0x2d, 0x25, 0x5d, 0x55, - 0x4d, 0x45, 0x7d, 0x75, 0x6d, 0x65, 0x9d, 0x95, 0x8d, 0x85, - 0xbd, 0xb5, 0xad, 0xa5, 0xdd, 0xd5, 0xcd, 0xc5, 0xfd, 0xf5, - 0xed, 0xe5, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, - 0x7a, 0x72, 0x6a, 0x62, 0x5a, 0x52, 0x4a, 0x42, 0xba, 0xb2, - 0xaa, 0xa2, 0x9a, 0x92, 0x8a, 0x82, 0xfa, 0xf2, 0xea, 0xe2, - 0xda, 0xd2, 0xca, 0xc2, 0x27, 0x2f, 0x37, 0x3f, 0x07, 0x0f, - 0x17, 0x1f, 0x67, 0x6f, 0x77, 0x7f, 0x47, 0x4f, 0x57, 0x5f, - 0xa7, 0xaf, 0xb7, 0xbf, 0x87, 0x8f, 0x97, 0x9f, 0xe7, 0xef, - 0xf7, 0xff, 0xc7, 0xcf, 0xd7, 0xdf, 0x74, 0x7c, 0x64, 0x6c, - 0x54, 0x5c, 0x44, 0x4c, 0x34, 0x3c, 0x24, 0x2c, 0x14, 0x1c, - 0x04, 0x0c, 0xf4, 0xfc, 0xe4, 0xec, 0xd4, 0xdc, 0xc4, 0xcc, - 0xb4, 0xbc, 0xa4, 0xac, 0x94, 0x9c, 0x84, 0x8c, 0x69, 0x61, - 0x79, 0x71, 0x49, 0x41, 0x59, 0x51, 0x29, 0x21, 0x39, 0x31, - 0x09, 0x01, 0x19, 0x11, 0xe9, 0xe1, 0xf9, 0xf1, 0xc9, 0xc1, - 0xd9, 0xd1, 0xa9, 0xa1, 0xb9, 0xb1, 0x89, 0x81, 0x99, 0x91, - 0x4e, 0x46, 0x5e, 0x56, 0x6e, 0x66, 0x7e, 0x76, 0x0e, 0x06, - 0x1e, 0x16, 0x2e, 0x26, 0x3e, 0x36, 0xce, 0xc6, 0xde, 0xd6, - 0xee, 0xe6, 0xfe, 0xf6, 0x8e, 0x86, 0x9e, 0x96, 0xae, 0xa6, - 0xbe, 0xb6, 0x53, 0x5b, 0x43, 0x4b, 0x73, 0x7b, 0x63, 0x6b, - 0x13, 0x1b, 0x03, 0x0b, 0x33, 0x3b, 0x23, 0x2b, 0xd3, 0xdb, - 0xc3, 0xcb, 0xf3, 0xfb, 0xe3, 0xeb, 0x93, 0x9b, 0x83, 0x8b, - 0xb3, 0xbb, 0xa3, 0xab, 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, - 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, - 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, - 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3d, 0x34, 0x2f, 0x26, - 0x19, 0x10, 0x0b, 0x02, 0x75, 0x7c, 0x67, 0x6e, 0x51, 0x58, - 0x43, 0x4a, 0xad, 0xa4, 0xbf, 0xb6, 0x89, 0x80, 0x9b, 0x92, - 0xe5, 0xec, 0xf7, 0xfe, 0xc1, 0xc8, 0xd3, 0xda, 0x7a, 0x73, - 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, 0x32, 0x3b, 0x20, 0x29, - 0x16, 0x1f, 0x04, 0x0d, 0xea, 0xe3, 0xf8, 0xf1, 0xce, 0xc7, - 0xdc, 0xd5, 0xa2, 0xab, 0xb0, 0xb9, 0x86, 0x8f, 0x94, 0x9d, - 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, - 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0xd7, 0xde, 0xc5, 0xcc, - 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, - 0xa9, 0xa0, 0xf4, 0xfd, 0xe6, 0xef, 0xd0, 0xd9, 0xc2, 0xcb, - 0xbc, 0xb5, 0xae, 0xa7, 0x98, 0x91, 0x8a, 0x83, 0x64, 0x6d, - 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, 0x2c, 0x25, 0x3e, 0x37, - 0x08, 0x01, 0x1a, 0x13, 0xc9, 0xc0, 0xdb, 0xd2, 0xed, 0xe4, - 0xff, 0xf6, 0x81, 0x88, 0x93, 0x9a, 0xa5, 0xac, 0xb7, 0xbe, - 0x59, 0x50, 0x4b, 0x42, 0x7d, 0x74, 0x6f, 0x66, 0x11, 0x18, - 0x03, 0x0a, 0x35, 0x3c, 0x27, 0x2e, 0x8e, 0x87, 0x9c, 0x95, - 0xaa, 0xa3, 0xb8, 0xb1, 0xc6, 0xcf, 0xd4, 0xdd, 0xe2, 0xeb, - 0xf0, 0xf9, 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, - 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0xb3, 0xba, - 0xa1, 0xa8, 0x97, 0x9e, 0x85, 0x8c, 0xfb, 0xf2, 0xe9, 0xe0, - 0xdf, 0xd6, 0xcd, 0xc4, 0x23, 0x2a, 0x31, 0x38, 0x07, 0x0e, - 0x15, 0x1c, 0x6b, 0x62, 0x79, 0x70, 0x4f, 0x46, 0x5d, 0x54, - 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, - 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66, 0xa0, 0xaa, 0xb4, 0xbe, - 0x88, 0x82, 0x9c, 0x96, 0xf0, 0xfa, 0xe4, 0xee, 0xd8, 0xd2, - 0xcc, 0xc6, 0x5d, 0x57, 0x49, 0x43, 0x75, 0x7f, 0x61, 0x6b, - 0x0d, 0x07, 0x19, 0x13, 0x25, 0x2f, 0x31, 0x3b, 0xfd, 0xf7, - 0xe9, 0xe3, 0xd5, 0xdf, 0xc1, 0xcb, 0xad, 0xa7, 0xb9, 0xb3, - 0x85, 0x8f, 0x91, 0x9b, 0xba, 0xb0, 0xae, 0xa4, 0x92, 0x98, - 0x86, 0x8c, 0xea, 0xe0, 0xfe, 0xf4, 0xc2, 0xc8, 0xd6, 0xdc, - 0x1a, 0x10, 0x0e, 0x04, 0x32, 0x38, 0x26, 0x2c, 0x4a, 0x40, - 0x5e, 0x54, 0x62, 0x68, 0x76, 0x7c, 0xe7, 0xed, 0xf3, 0xf9, - 0xcf, 0xc5, 0xdb, 0xd1, 0xb7, 0xbd, 0xa3, 0xa9, 0x9f, 0x95, - 0x8b, 0x81, 0x47, 0x4d, 0x53, 0x59, 0x6f, 0x65, 0x7b, 0x71, - 0x17, 0x1d, 0x03, 0x09, 0x3f, 0x35, 0x2b, 0x21, 0x69, 0x63, - 0x7d, 0x77, 0x41, 0x4b, 0x55, 0x5f, 0x39, 0x33, 0x2d, 0x27, - 0x11, 0x1b, 0x05, 0x0f, 0xc9, 0xc3, 0xdd, 0xd7, 0xe1, 0xeb, - 0xf5, 0xff, 0x99, 0x93, 0x8d, 0x87, 0xb1, 0xbb, 0xa5, 0xaf, - 0x34, 0x3e, 0x20, 0x2a, 0x1c, 0x16, 0x08, 0x02, 0x64, 0x6e, - 0x70, 0x7a, 0x4c, 0x46, 0x58, 0x52, 0x94, 0x9e, 0x80, 0x8a, - 0xbc, 0xb6, 0xa8, 0xa2, 0xc4, 0xce, 0xd0, 0xda, 0xec, 0xe6, - 0xf8, 0xf2, 0xd3, 0xd9, 0xc7, 0xcd, 0xfb, 0xf1, 0xef, 0xe5, - 0x83, 0x89, 0x97, 0x9d, 0xab, 0xa1, 0xbf, 0xb5, 0x73, 0x79, - 0x67, 0x6d, 0x5b, 0x51, 0x4f, 0x45, 0x23, 0x29, 0x37, 0x3d, - 0x0b, 0x01, 0x1f, 0x15, 0x8e, 0x84, 0x9a, 0x90, 0xa6, 0xac, - 0xb2, 0xb8, 0xde, 0xd4, 0xca, 0xc0, 0xf6, 0xfc, 0xe2, 0xe8, - 0x2e, 0x24, 0x3a, 0x30, 0x06, 0x0c, 0x12, 0x18, 0x7e, 0x74, - 0x6a, 0x60, 0x56, 0x5c, 0x42, 0x48, 0x00, 0x0b, 0x16, 0x1d, - 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, - 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, - 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7d, 0x76, - 0x6b, 0x60, 0x51, 0x5a, 0x47, 0x4c, 0x25, 0x2e, 0x33, 0x38, - 0x09, 0x02, 0x1f, 0x14, 0xcd, 0xc6, 0xdb, 0xd0, 0xe1, 0xea, - 0xf7, 0xfc, 0x95, 0x9e, 0x83, 0x88, 0xb9, 0xb2, 0xaf, 0xa4, - 0xfa, 0xf1, 0xec, 0xe7, 0xd6, 0xdd, 0xc0, 0xcb, 0xa2, 0xa9, - 0xb4, 0xbf, 0x8e, 0x85, 0x98, 0x93, 0x4a, 0x41, 0x5c, 0x57, - 0x66, 0x6d, 0x70, 0x7b, 0x12, 0x19, 0x04, 0x0f, 0x3e, 0x35, - 0x28, 0x23, 0x87, 0x8c, 0x91, 0x9a, 0xab, 0xa0, 0xbd, 0xb6, - 0xdf, 0xd4, 0xc9, 0xc2, 0xf3, 0xf8, 0xe5, 0xee, 0x37, 0x3c, - 0x21, 0x2a, 0x1b, 0x10, 0x0d, 0x06, 0x6f, 0x64, 0x79, 0x72, - 0x43, 0x48, 0x55, 0x5e, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, - 0xd3, 0xd8, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, - 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0x01, 0x0a, - 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x94, 0x9f, 0x82, 0x89, - 0xb8, 0xb3, 0xae, 0xa5, 0xcc, 0xc7, 0xda, 0xd1, 0xe0, 0xeb, - 0xf6, 0xfd, 0x24, 0x2f, 0x32, 0x39, 0x08, 0x03, 0x1e, 0x15, - 0x7c, 0x77, 0x6a, 0x61, 0x50, 0x5b, 0x46, 0x4d, 0x13, 0x18, - 0x05, 0x0e, 0x3f, 0x34, 0x29, 0x22, 0x4b, 0x40, 0x5d, 0x56, - 0x67, 0x6c, 0x71, 0x7a, 0xa3, 0xa8, 0xb5, 0xbe, 0x8f, 0x84, - 0x99, 0x92, 0xfb, 0xf0, 0xed, 0xe6, 0xd7, 0xdc, 0xc1, 0xca, - 0x6e, 0x65, 0x78, 0x73, 0x42, 0x49, 0x54, 0x5f, 0x36, 0x3d, - 0x20, 0x2b, 0x1a, 0x11, 0x0c, 0x07, 0xde, 0xd5, 0xc8, 0xc3, - 0xf2, 0xf9, 0xe4, 0xef, 0x86, 0x8d, 0x90, 0x9b, 0xaa, 0xa1, - 0xbc, 0xb7, 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, - 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44, 0xc0, 0xcc, - 0xd8, 0xd4, 0xf0, 0xfc, 0xe8, 0xe4, 0xa0, 0xac, 0xb8, 0xb4, - 0x90, 0x9c, 0x88, 0x84, 0x9d, 0x91, 0x85, 0x89, 0xad, 0xa1, - 0xb5, 0xb9, 0xfd, 0xf1, 0xe5, 0xe9, 0xcd, 0xc1, 0xd5, 0xd9, - 0x5d, 0x51, 0x45, 0x49, 0x6d, 0x61, 0x75, 0x79, 0x3d, 0x31, - 0x25, 0x29, 0x0d, 0x01, 0x15, 0x19, 0x27, 0x2b, 0x3f, 0x33, - 0x17, 0x1b, 0x0f, 0x03, 0x47, 0x4b, 0x5f, 0x53, 0x77, 0x7b, - 0x6f, 0x63, 0xe7, 0xeb, 0xff, 0xf3, 0xd7, 0xdb, 0xcf, 0xc3, - 0x87, 0x8b, 0x9f, 0x93, 0xb7, 0xbb, 0xaf, 0xa3, 0xba, 0xb6, - 0xa2, 0xae, 0x8a, 0x86, 0x92, 0x9e, 0xda, 0xd6, 0xc2, 0xce, - 0xea, 0xe6, 0xf2, 0xfe, 0x7a, 0x76, 0x62, 0x6e, 0x4a, 0x46, - 0x52, 0x5e, 0x1a, 0x16, 0x02, 0x0e, 0x2a, 0x26, 0x32, 0x3e, - 0x4e, 0x42, 0x56, 0x5a, 0x7e, 0x72, 0x66, 0x6a, 0x2e, 0x22, - 0x36, 0x3a, 0x1e, 0x12, 0x06, 0x0a, 0x8e, 0x82, 0x96, 0x9a, - 0xbe, 0xb2, 0xa6, 0xaa, 0xee, 0xe2, 0xf6, 0xfa, 0xde, 0xd2, - 0xc6, 0xca, 0xd3, 0xdf, 0xcb, 0xc7, 0xe3, 0xef, 0xfb, 0xf7, - 0xb3, 0xbf, 0xab, 0xa7, 0x83, 0x8f, 0x9b, 0x97, 0x13, 0x1f, - 0x0b, 0x07, 0x23, 0x2f, 0x3b, 0x37, 0x73, 0x7f, 0x6b, 0x67, - 0x43, 0x4f, 0x5b, 0x57, 0x69, 0x65, 0x71, 0x7d, 0x59, 0x55, - 0x41, 0x4d, 0x09, 0x05, 0x11, 0x1d, 0x39, 0x35, 0x21, 0x2d, - 0xa9, 0xa5, 0xb1, 0xbd, 0x99, 0x95, 0x81, 0x8d, 0xc9, 0xc5, - 0xd1, 0xdd, 0xf9, 0xf5, 0xe1, 0xed, 0xf4, 0xf8, 0xec, 0xe0, - 0xc4, 0xc8, 0xdc, 0xd0, 0x94, 0x98, 0x8c, 0x80, 0xa4, 0xa8, - 0xbc, 0xb0, 0x34, 0x38, 0x2c, 0x20, 0x04, 0x08, 0x1c, 0x10, - 0x54, 0x58, 0x4c, 0x40, 0x64, 0x68, 0x7c, 0x70, 0x00, 0x0d, - 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, - 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, - 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, - 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, - 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0x6d, 0x60, 0x77, 0x7a, - 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, - 0x2b, 0x26, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, - 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0xb7, 0xba, - 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, - 0xeb, 0xe6, 0xf1, 0xfc, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, - 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, - 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, - 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0xce, 0xc3, 0xd4, 0xd9, - 0xfa, 0xf7, 0xe0, 0xed, 0xa6, 0xab, 0xbc, 0xb1, 0x92, 0x9f, - 0x88, 0x85, 0x1e, 0x13, 0x04, 0x09, 0x2a, 0x27, 0x30, 0x3d, - 0x76, 0x7b, 0x6c, 0x61, 0x42, 0x4f, 0x58, 0x55, 0x73, 0x7e, - 0x69, 0x64, 0x47, 0x4a, 0x5d, 0x50, 0x1b, 0x16, 0x01, 0x0c, - 0x2f, 0x22, 0x35, 0x38, 0xa3, 0xae, 0xb9, 0xb4, 0x97, 0x9a, - 0x8d, 0x80, 0xcb, 0xc6, 0xd1, 0xdc, 0xff, 0xf2, 0xe5, 0xe8, - 0xa9, 0xa4, 0xb3, 0xbe, 0x9d, 0x90, 0x87, 0x8a, 0xc1, 0xcc, - 0xdb, 0xd6, 0xf5, 0xf8, 0xef, 0xe2, 0x79, 0x74, 0x63, 0x6e, - 0x4d, 0x40, 0x57, 0x5a, 0x11, 0x1c, 0x0b, 0x06, 0x25, 0x28, - 0x3f, 0x32, 0x14, 0x19, 0x0e, 0x03, 0x20, 0x2d, 0x3a, 0x37, - 0x7c, 0x71, 0x66, 0x6b, 0x48, 0x45, 0x52, 0x5f, 0xc4, 0xc9, - 0xde, 0xd3, 0xf0, 0xfd, 0xea, 0xe7, 0xac, 0xa1, 0xb6, 0xbb, - 0x98, 0x95, 0x82, 0x8f, 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, - 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, - 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, - 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdd, 0xd3, 0xc1, 0xcf, - 0xe5, 0xeb, 0xf9, 0xf7, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, - 0x89, 0x87, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, - 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0xa7, 0xa9, - 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, 0xd7, 0xd9, 0xcb, 0xc5, - 0xef, 0xe1, 0xf3, 0xfd, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, - 0x63, 0x6d, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, - 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, - 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0x9a, 0x94, 0x86, 0x88, - 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, - 0xce, 0xc0, 0x53, 0x5d, 0x4f, 0x41, 0x6b, 0x65, 0x77, 0x79, - 0x23, 0x2d, 0x3f, 0x31, 0x1b, 0x15, 0x07, 0x09, 0xb3, 0xbd, - 0xaf, 0xa1, 0x8b, 0x85, 0x97, 0x99, 0xc3, 0xcd, 0xdf, 0xd1, - 0xfb, 0xf5, 0xe7, 0xe9, 0x8e, 0x80, 0x92, 0x9c, 0xb6, 0xb8, - 0xaa, 0xa4, 0xfe, 0xf0, 0xe2, 0xec, 0xc6, 0xc8, 0xda, 0xd4, - 0x6e, 0x60, 0x72, 0x7c, 0x56, 0x58, 0x4a, 0x44, 0x1e, 0x10, - 0x02, 0x0c, 0x26, 0x28, 0x3a, 0x34, 0xf4, 0xfa, 0xe8, 0xe6, - 0xcc, 0xc2, 0xd0, 0xde, 0x84, 0x8a, 0x98, 0x96, 0xbc, 0xb2, - 0xa0, 0xae, 0x14, 0x1a, 0x08, 0x06, 0x2c, 0x22, 0x30, 0x3e, - 0x64, 0x6a, 0x78, 0x76, 0x5c, 0x52, 0x40, 0x4e, 0x29, 0x27, - 0x35, 0x3b, 0x11, 0x1f, 0x0d, 0x03, 0x59, 0x57, 0x45, 0x4b, - 0x61, 0x6f, 0x7d, 0x73, 0xc9, 0xc7, 0xd5, 0xdb, 0xf1, 0xff, - 0xed, 0xe3, 0xb9, 0xb7, 0xa5, 0xab, 0x81, 0x8f, 0x9d, 0x93, - 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, - 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55, 0xf0, 0xff, 0xee, 0xe1, - 0xcc, 0xc3, 0xd2, 0xdd, 0x88, 0x87, 0x96, 0x99, 0xb4, 0xbb, - 0xaa, 0xa5, 0xfd, 0xf2, 0xe3, 0xec, 0xc1, 0xce, 0xdf, 0xd0, - 0x85, 0x8a, 0x9b, 0x94, 0xb9, 0xb6, 0xa7, 0xa8, 0x0d, 0x02, - 0x13, 0x1c, 0x31, 0x3e, 0x2f, 0x20, 0x75, 0x7a, 0x6b, 0x64, - 0x49, 0x46, 0x57, 0x58, 0xe7, 0xe8, 0xf9, 0xf6, 0xdb, 0xd4, - 0xc5, 0xca, 0x9f, 0x90, 0x81, 0x8e, 0xa3, 0xac, 0xbd, 0xb2, - 0x17, 0x18, 0x09, 0x06, 0x2b, 0x24, 0x35, 0x3a, 0x6f, 0x60, - 0x71, 0x7e, 0x53, 0x5c, 0x4d, 0x42, 0x1a, 0x15, 0x04, 0x0b, - 0x26, 0x29, 0x38, 0x37, 0x62, 0x6d, 0x7c, 0x73, 0x5e, 0x51, - 0x40, 0x4f, 0xea, 0xe5, 0xf4, 0xfb, 0xd6, 0xd9, 0xc8, 0xc7, - 0x92, 0x9d, 0x8c, 0x83, 0xae, 0xa1, 0xb0, 0xbf, 0xd3, 0xdc, - 0xcd, 0xc2, 0xef, 0xe0, 0xf1, 0xfe, 0xab, 0xa4, 0xb5, 0xba, - 0x97, 0x98, 0x89, 0x86, 0x23, 0x2c, 0x3d, 0x32, 0x1f, 0x10, - 0x01, 0x0e, 0x5b, 0x54, 0x45, 0x4a, 0x67, 0x68, 0x79, 0x76, - 0x2e, 0x21, 0x30, 0x3f, 0x12, 0x1d, 0x0c, 0x03, 0x56, 0x59, - 0x48, 0x47, 0x6a, 0x65, 0x74, 0x7b, 0xde, 0xd1, 0xc0, 0xcf, - 0xe2, 0xed, 0xfc, 0xf3, 0xa6, 0xa9, 0xb8, 0xb7, 0x9a, 0x95, - 0x84, 0x8b, 0x34, 0x3b, 0x2a, 0x25, 0x08, 0x07, 0x16, 0x19, - 0x4c, 0x43, 0x52, 0x5d, 0x70, 0x7f, 0x6e, 0x61, 0xc4, 0xcb, - 0xda, 0xd5, 0xf8, 0xf7, 0xe6, 0xe9, 0xbc, 0xb3, 0xa2, 0xad, - 0x80, 0x8f, 0x9e, 0x91, 0xc9, 0xc6, 0xd7, 0xd8, 0xf5, 0xfa, - 0xeb, 0xe4, 0xb1, 0xbe, 0xaf, 0xa0, 0x8d, 0x82, 0x93, 0x9c, - 0x39, 0x36, 0x27, 0x28, 0x05, 0x0a, 0x1b, 0x14, 0x41, 0x4e, - 0x5f, 0x50, 0x7d, 0x72, 0x63, 0x6c, 0x00, 0x10, 0x20, 0x30, - 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, - 0xe0, 0xf0, 0x1d, 0x0d, 0x3d, 0x2d, 0x5d, 0x4d, 0x7d, 0x6d, - 0x9d, 0x8d, 0xbd, 0xad, 0xdd, 0xcd, 0xfd, 0xed, 0x3a, 0x2a, - 0x1a, 0x0a, 0x7a, 0x6a, 0x5a, 0x4a, 0xba, 0xaa, 0x9a, 0x8a, - 0xfa, 0xea, 0xda, 0xca, 0x27, 0x37, 0x07, 0x17, 0x67, 0x77, - 0x47, 0x57, 0xa7, 0xb7, 0x87, 0x97, 0xe7, 0xf7, 0xc7, 0xd7, - 0x74, 0x64, 0x54, 0x44, 0x34, 0x24, 0x14, 0x04, 0xf4, 0xe4, - 0xd4, 0xc4, 0xb4, 0xa4, 0x94, 0x84, 0x69, 0x79, 0x49, 0x59, - 0x29, 0x39, 0x09, 0x19, 0xe9, 0xf9, 0xc9, 0xd9, 0xa9, 0xb9, - 0x89, 0x99, 0x4e, 0x5e, 0x6e, 0x7e, 0x0e, 0x1e, 0x2e, 0x3e, - 0xce, 0xde, 0xee, 0xfe, 0x8e, 0x9e, 0xae, 0xbe, 0x53, 0x43, - 0x73, 0x63, 0x13, 0x03, 0x33, 0x23, 0xd3, 0xc3, 0xf3, 0xe3, - 0x93, 0x83, 0xb3, 0xa3, 0xe8, 0xf8, 0xc8, 0xd8, 0xa8, 0xb8, - 0x88, 0x98, 0x68, 0x78, 0x48, 0x58, 0x28, 0x38, 0x08, 0x18, - 0xf5, 0xe5, 0xd5, 0xc5, 0xb5, 0xa5, 0x95, 0x85, 0x75, 0x65, - 0x55, 0x45, 0x35, 0x25, 0x15, 0x05, 0xd2, 0xc2, 0xf2, 0xe2, - 0x92, 0x82, 0xb2, 0xa2, 0x52, 0x42, 0x72, 0x62, 0x12, 0x02, - 0x32, 0x22, 0xcf, 0xdf, 0xef, 0xff, 0x8f, 0x9f, 0xaf, 0xbf, - 0x4f, 0x5f, 0x6f, 0x7f, 0x0f, 0x1f, 0x2f, 0x3f, 0x9c, 0x8c, - 0xbc, 0xac, 0xdc, 0xcc, 0xfc, 0xec, 0x1c, 0x0c, 0x3c, 0x2c, - 0x5c, 0x4c, 0x7c, 0x6c, 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, - 0xe1, 0xf1, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, - 0xa6, 0xb6, 0x86, 0x96, 0xe6, 0xf6, 0xc6, 0xd6, 0x26, 0x36, - 0x06, 0x16, 0x66, 0x76, 0x46, 0x56, 0xbb, 0xab, 0x9b, 0x8b, - 0xfb, 0xeb, 0xdb, 0xcb, 0x3b, 0x2b, 0x1b, 0x0b, 0x7b, 0x6b, - 0x5b, 0x4b, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0d, 0x1c, - 0x2f, 0x3e, 0x49, 0x58, 0x6b, 0x7a, 0x85, 0x94, 0xa7, 0xb6, - 0xc1, 0xd0, 0xe3, 0xf2, 0x1a, 0x0b, 0x38, 0x29, 0x5e, 0x4f, - 0x7c, 0x6d, 0x92, 0x83, 0xb0, 0xa1, 0xd6, 0xc7, 0xf4, 0xe5, - 0x17, 0x06, 0x35, 0x24, 0x53, 0x42, 0x71, 0x60, 0x9f, 0x8e, - 0xbd, 0xac, 0xdb, 0xca, 0xf9, 0xe8, 0x34, 0x25, 0x16, 0x07, - 0x70, 0x61, 0x52, 0x43, 0xbc, 0xad, 0x9e, 0x8f, 0xf8, 0xe9, - 0xda, 0xcb, 0x39, 0x28, 0x1b, 0x0a, 0x7d, 0x6c, 0x5f, 0x4e, - 0xb1, 0xa0, 0x93, 0x82, 0xf5, 0xe4, 0xd7, 0xc6, 0x2e, 0x3f, - 0x0c, 0x1d, 0x6a, 0x7b, 0x48, 0x59, 0xa6, 0xb7, 0x84, 0x95, - 0xe2, 0xf3, 0xc0, 0xd1, 0x23, 0x32, 0x01, 0x10, 0x67, 0x76, - 0x45, 0x54, 0xab, 0xba, 0x89, 0x98, 0xef, 0xfe, 0xcd, 0xdc, - 0x68, 0x79, 0x4a, 0x5b, 0x2c, 0x3d, 0x0e, 0x1f, 0xe0, 0xf1, - 0xc2, 0xd3, 0xa4, 0xb5, 0x86, 0x97, 0x65, 0x74, 0x47, 0x56, - 0x21, 0x30, 0x03, 0x12, 0xed, 0xfc, 0xcf, 0xde, 0xa9, 0xb8, - 0x8b, 0x9a, 0x72, 0x63, 0x50, 0x41, 0x36, 0x27, 0x14, 0x05, - 0xfa, 0xeb, 0xd8, 0xc9, 0xbe, 0xaf, 0x9c, 0x8d, 0x7f, 0x6e, - 0x5d, 0x4c, 0x3b, 0x2a, 0x19, 0x08, 0xf7, 0xe6, 0xd5, 0xc4, - 0xb3, 0xa2, 0x91, 0x80, 0x5c, 0x4d, 0x7e, 0x6f, 0x18, 0x09, - 0x3a, 0x2b, 0xd4, 0xc5, 0xf6, 0xe7, 0x90, 0x81, 0xb2, 0xa3, - 0x51, 0x40, 0x73, 0x62, 0x15, 0x04, 0x37, 0x26, 0xd9, 0xc8, - 0xfb, 0xea, 0x9d, 0x8c, 0xbf, 0xae, 0x46, 0x57, 0x64, 0x75, - 0x02, 0x13, 0x20, 0x31, 0xce, 0xdf, 0xec, 0xfd, 0x8a, 0x9b, - 0xa8, 0xb9, 0x4b, 0x5a, 0x69, 0x78, 0x0f, 0x1e, 0x2d, 0x3c, - 0xc3, 0xd2, 0xe1, 0xf0, 0x87, 0x96, 0xa5, 0xb4, 0x00, 0x12, - 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, - 0xd8, 0xca, 0xfc, 0xee, 0x3d, 0x2f, 0x19, 0x0b, 0x75, 0x67, - 0x51, 0x43, 0xad, 0xbf, 0x89, 0x9b, 0xe5, 0xf7, 0xc1, 0xd3, - 0x7a, 0x68, 0x5e, 0x4c, 0x32, 0x20, 0x16, 0x04, 0xea, 0xf8, - 0xce, 0xdc, 0xa2, 0xb0, 0x86, 0x94, 0x47, 0x55, 0x63, 0x71, - 0x0f, 0x1d, 0x2b, 0x39, 0xd7, 0xc5, 0xf3, 0xe1, 0x9f, 0x8d, - 0xbb, 0xa9, 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a, - 0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, 0xc9, 0xdb, - 0xed, 0xff, 0x81, 0x93, 0xa5, 0xb7, 0x59, 0x4b, 0x7d, 0x6f, - 0x11, 0x03, 0x35, 0x27, 0x8e, 0x9c, 0xaa, 0xb8, 0xc6, 0xd4, - 0xe2, 0xf0, 0x1e, 0x0c, 0x3a, 0x28, 0x56, 0x44, 0x72, 0x60, - 0xb3, 0xa1, 0x97, 0x85, 0xfb, 0xe9, 0xdf, 0xcd, 0x23, 0x31, - 0x07, 0x15, 0x6b, 0x79, 0x4f, 0x5d, 0xf5, 0xe7, 0xd1, 0xc3, - 0xbd, 0xaf, 0x99, 0x8b, 0x65, 0x77, 0x41, 0x53, 0x2d, 0x3f, - 0x09, 0x1b, 0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, - 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26, 0x8f, 0x9d, - 0xab, 0xb9, 0xc7, 0xd5, 0xe3, 0xf1, 0x1f, 0x0d, 0x3b, 0x29, - 0x57, 0x45, 0x73, 0x61, 0xb2, 0xa0, 0x96, 0x84, 0xfa, 0xe8, - 0xde, 0xcc, 0x22, 0x30, 0x06, 0x14, 0x6a, 0x78, 0x4e, 0x5c, - 0x01, 0x13, 0x25, 0x37, 0x49, 0x5b, 0x6d, 0x7f, 0x91, 0x83, - 0xb5, 0xa7, 0xd9, 0xcb, 0xfd, 0xef, 0x3c, 0x2e, 0x18, 0x0a, - 0x74, 0x66, 0x50, 0x42, 0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, - 0xc0, 0xd2, 0x7b, 0x69, 0x5f, 0x4d, 0x33, 0x21, 0x17, 0x05, - 0xeb, 0xf9, 0xcf, 0xdd, 0xa3, 0xb1, 0x87, 0x95, 0x46, 0x54, - 0x62, 0x70, 0x0e, 0x1c, 0x2a, 0x38, 0xd6, 0xc4, 0xf2, 0xe0, - 0x9e, 0x8c, 0xba, 0xa8, 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, - 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1, - 0x2d, 0x3e, 0x0b, 0x18, 0x61, 0x72, 0x47, 0x54, 0xb5, 0xa6, - 0x93, 0x80, 0xf9, 0xea, 0xdf, 0xcc, 0x5a, 0x49, 0x7c, 0x6f, - 0x16, 0x05, 0x30, 0x23, 0xc2, 0xd1, 0xe4, 0xf7, 0x8e, 0x9d, - 0xa8, 0xbb, 0x77, 0x64, 0x51, 0x42, 0x3b, 0x28, 0x1d, 0x0e, - 0xef, 0xfc, 0xc9, 0xda, 0xa3, 0xb0, 0x85, 0x96, 0xb4, 0xa7, - 0x92, 0x81, 0xf8, 0xeb, 0xde, 0xcd, 0x2c, 0x3f, 0x0a, 0x19, - 0x60, 0x73, 0x46, 0x55, 0x99, 0x8a, 0xbf, 0xac, 0xd5, 0xc6, - 0xf3, 0xe0, 0x01, 0x12, 0x27, 0x34, 0x4d, 0x5e, 0x6b, 0x78, - 0xee, 0xfd, 0xc8, 0xdb, 0xa2, 0xb1, 0x84, 0x97, 0x76, 0x65, - 0x50, 0x43, 0x3a, 0x29, 0x1c, 0x0f, 0xc3, 0xd0, 0xe5, 0xf6, - 0x8f, 0x9c, 0xa9, 0xba, 0x5b, 0x48, 0x7d, 0x6e, 0x17, 0x04, - 0x31, 0x22, 0x75, 0x66, 0x53, 0x40, 0x39, 0x2a, 0x1f, 0x0c, - 0xed, 0xfe, 0xcb, 0xd8, 0xa1, 0xb2, 0x87, 0x94, 0x58, 0x4b, - 0x7e, 0x6d, 0x14, 0x07, 0x32, 0x21, 0xc0, 0xd3, 0xe6, 0xf5, - 0x8c, 0x9f, 0xaa, 0xb9, 0x2f, 0x3c, 0x09, 0x1a, 0x63, 0x70, - 0x45, 0x56, 0xb7, 0xa4, 0x91, 0x82, 0xfb, 0xe8, 0xdd, 0xce, - 0x02, 0x11, 0x24, 0x37, 0x4e, 0x5d, 0x68, 0x7b, 0x9a, 0x89, - 0xbc, 0xaf, 0xd6, 0xc5, 0xf0, 0xe3, 0xc1, 0xd2, 0xe7, 0xf4, - 0x8d, 0x9e, 0xab, 0xb8, 0x59, 0x4a, 0x7f, 0x6c, 0x15, 0x06, - 0x33, 0x20, 0xec, 0xff, 0xca, 0xd9, 0xa0, 0xb3, 0x86, 0x95, - 0x74, 0x67, 0x52, 0x41, 0x38, 0x2b, 0x1e, 0x0d, 0x9b, 0x88, - 0xbd, 0xae, 0xd7, 0xc4, 0xf1, 0xe2, 0x03, 0x10, 0x25, 0x36, - 0x4f, 0x5c, 0x69, 0x7a, 0xb6, 0xa5, 0x90, 0x83, 0xfa, 0xe9, - 0xdc, 0xcf, 0x2e, 0x3d, 0x08, 0x1b, 0x62, 0x71, 0x44, 0x57, - 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, - 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc, 0x5d, 0x49, 0x75, 0x61, - 0x0d, 0x19, 0x25, 0x31, 0xfd, 0xe9, 0xd5, 0xc1, 0xad, 0xb9, - 0x85, 0x91, 0xba, 0xae, 0x92, 0x86, 0xea, 0xfe, 0xc2, 0xd6, - 0x1a, 0x0e, 0x32, 0x26, 0x4a, 0x5e, 0x62, 0x76, 0xe7, 0xf3, - 0xcf, 0xdb, 0xb7, 0xa3, 0x9f, 0x8b, 0x47, 0x53, 0x6f, 0x7b, - 0x17, 0x03, 0x3f, 0x2b, 0x69, 0x7d, 0x41, 0x55, 0x39, 0x2d, - 0x11, 0x05, 0xc9, 0xdd, 0xe1, 0xf5, 0x99, 0x8d, 0xb1, 0xa5, - 0x34, 0x20, 0x1c, 0x08, 0x64, 0x70, 0x4c, 0x58, 0x94, 0x80, - 0xbc, 0xa8, 0xc4, 0xd0, 0xec, 0xf8, 0xd3, 0xc7, 0xfb, 0xef, - 0x83, 0x97, 0xab, 0xbf, 0x73, 0x67, 0x5b, 0x4f, 0x23, 0x37, - 0x0b, 0x1f, 0x8e, 0x9a, 0xa6, 0xb2, 0xde, 0xca, 0xf6, 0xe2, - 0x2e, 0x3a, 0x06, 0x12, 0x7e, 0x6a, 0x56, 0x42, 0xd2, 0xc6, - 0xfa, 0xee, 0x82, 0x96, 0xaa, 0xbe, 0x72, 0x66, 0x5a, 0x4e, - 0x22, 0x36, 0x0a, 0x1e, 0x8f, 0x9b, 0xa7, 0xb3, 0xdf, 0xcb, - 0xf7, 0xe3, 0x2f, 0x3b, 0x07, 0x13, 0x7f, 0x6b, 0x57, 0x43, - 0x68, 0x7c, 0x40, 0x54, 0x38, 0x2c, 0x10, 0x04, 0xc8, 0xdc, - 0xe0, 0xf4, 0x98, 0x8c, 0xb0, 0xa4, 0x35, 0x21, 0x1d, 0x09, - 0x65, 0x71, 0x4d, 0x59, 0x95, 0x81, 0xbd, 0xa9, 0xc5, 0xd1, - 0xed, 0xf9, 0xbb, 0xaf, 0x93, 0x87, 0xeb, 0xff, 0xc3, 0xd7, - 0x1b, 0x0f, 0x33, 0x27, 0x4b, 0x5f, 0x63, 0x77, 0xe6, 0xf2, - 0xce, 0xda, 0xb6, 0xa2, 0x9e, 0x8a, 0x46, 0x52, 0x6e, 0x7a, - 0x16, 0x02, 0x3e, 0x2a, 0x01, 0x15, 0x29, 0x3d, 0x51, 0x45, - 0x79, 0x6d, 0xa1, 0xb5, 0x89, 0x9d, 0xf1, 0xe5, 0xd9, 0xcd, - 0x5c, 0x48, 0x74, 0x60, 0x0c, 0x18, 0x24, 0x30, 0xfc, 0xe8, - 0xd4, 0xc0, 0xac, 0xb8, 0x84, 0x90, 0x00, 0x15, 0x2a, 0x3f, - 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, - 0xd6, 0xc3, 0x4d, 0x58, 0x67, 0x72, 0x19, 0x0c, 0x33, 0x26, - 0xe5, 0xf0, 0xcf, 0xda, 0xb1, 0xa4, 0x9b, 0x8e, 0x9a, 0x8f, - 0xb0, 0xa5, 0xce, 0xdb, 0xe4, 0xf1, 0x32, 0x27, 0x18, 0x0d, - 0x66, 0x73, 0x4c, 0x59, 0xd7, 0xc2, 0xfd, 0xe8, 0x83, 0x96, - 0xa9, 0xbc, 0x7f, 0x6a, 0x55, 0x40, 0x2b, 0x3e, 0x01, 0x14, - 0x29, 0x3c, 0x03, 0x16, 0x7d, 0x68, 0x57, 0x42, 0x81, 0x94, - 0xab, 0xbe, 0xd5, 0xc0, 0xff, 0xea, 0x64, 0x71, 0x4e, 0x5b, - 0x30, 0x25, 0x1a, 0x0f, 0xcc, 0xd9, 0xe6, 0xf3, 0x98, 0x8d, - 0xb2, 0xa7, 0xb3, 0xa6, 0x99, 0x8c, 0xe7, 0xf2, 0xcd, 0xd8, - 0x1b, 0x0e, 0x31, 0x24, 0x4f, 0x5a, 0x65, 0x70, 0xfe, 0xeb, - 0xd4, 0xc1, 0xaa, 0xbf, 0x80, 0x95, 0x56, 0x43, 0x7c, 0x69, - 0x02, 0x17, 0x28, 0x3d, 0x52, 0x47, 0x78, 0x6d, 0x06, 0x13, - 0x2c, 0x39, 0xfa, 0xef, 0xd0, 0xc5, 0xae, 0xbb, 0x84, 0x91, - 0x1f, 0x0a, 0x35, 0x20, 0x4b, 0x5e, 0x61, 0x74, 0xb7, 0xa2, - 0x9d, 0x88, 0xe3, 0xf6, 0xc9, 0xdc, 0xc8, 0xdd, 0xe2, 0xf7, - 0x9c, 0x89, 0xb6, 0xa3, 0x60, 0x75, 0x4a, 0x5f, 0x34, 0x21, - 0x1e, 0x0b, 0x85, 0x90, 0xaf, 0xba, 0xd1, 0xc4, 0xfb, 0xee, - 0x2d, 0x38, 0x07, 0x12, 0x79, 0x6c, 0x53, 0x46, 0x7b, 0x6e, - 0x51, 0x44, 0x2f, 0x3a, 0x05, 0x10, 0xd3, 0xc6, 0xf9, 0xec, - 0x87, 0x92, 0xad, 0xb8, 0x36, 0x23, 0x1c, 0x09, 0x62, 0x77, - 0x48, 0x5d, 0x9e, 0x8b, 0xb4, 0xa1, 0xca, 0xdf, 0xe0, 0xf5, - 0xe1, 0xf4, 0xcb, 0xde, 0xb5, 0xa0, 0x9f, 0x8a, 0x49, 0x5c, - 0x63, 0x76, 0x1d, 0x08, 0x37, 0x22, 0xac, 0xb9, 0x86, 0x93, - 0xf8, 0xed, 0xd2, 0xc7, 0x04, 0x11, 0x2e, 0x3b, 0x50, 0x45, - 0x7a, 0x6f, 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, - 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2, 0x7d, 0x6b, - 0x51, 0x47, 0x25, 0x33, 0x09, 0x1f, 0xcd, 0xdb, 0xe1, 0xf7, - 0x95, 0x83, 0xb9, 0xaf, 0xfa, 0xec, 0xd6, 0xc0, 0xa2, 0xb4, - 0x8e, 0x98, 0x4a, 0x5c, 0x66, 0x70, 0x12, 0x04, 0x3e, 0x28, - 0x87, 0x91, 0xab, 0xbd, 0xdf, 0xc9, 0xf3, 0xe5, 0x37, 0x21, - 0x1b, 0x0d, 0x6f, 0x79, 0x43, 0x55, 0xe9, 0xff, 0xc5, 0xd3, - 0xb1, 0xa7, 0x9d, 0x8b, 0x59, 0x4f, 0x75, 0x63, 0x01, 0x17, - 0x2d, 0x3b, 0x94, 0x82, 0xb8, 0xae, 0xcc, 0xda, 0xe0, 0xf6, - 0x24, 0x32, 0x08, 0x1e, 0x7c, 0x6a, 0x50, 0x46, 0x13, 0x05, - 0x3f, 0x29, 0x4b, 0x5d, 0x67, 0x71, 0xa3, 0xb5, 0x8f, 0x99, - 0xfb, 0xed, 0xd7, 0xc1, 0x6e, 0x78, 0x42, 0x54, 0x36, 0x20, - 0x1a, 0x0c, 0xde, 0xc8, 0xf2, 0xe4, 0x86, 0x90, 0xaa, 0xbc, - 0xcf, 0xd9, 0xe3, 0xf5, 0x97, 0x81, 0xbb, 0xad, 0x7f, 0x69, - 0x53, 0x45, 0x27, 0x31, 0x0b, 0x1d, 0xb2, 0xa4, 0x9e, 0x88, - 0xea, 0xfc, 0xc6, 0xd0, 0x02, 0x14, 0x2e, 0x38, 0x5a, 0x4c, - 0x76, 0x60, 0x35, 0x23, 0x19, 0x0f, 0x6d, 0x7b, 0x41, 0x57, - 0x85, 0x93, 0xa9, 0xbf, 0xdd, 0xcb, 0xf1, 0xe7, 0x48, 0x5e, - 0x64, 0x72, 0x10, 0x06, 0x3c, 0x2a, 0xf8, 0xee, 0xd4, 0xc2, - 0xa0, 0xb6, 0x8c, 0x9a, 0x26, 0x30, 0x0a, 0x1c, 0x7e, 0x68, - 0x52, 0x44, 0x96, 0x80, 0xba, 0xac, 0xce, 0xd8, 0xe2, 0xf4, - 0x5b, 0x4d, 0x77, 0x61, 0x03, 0x15, 0x2f, 0x39, 0xeb, 0xfd, - 0xc7, 0xd1, 0xb3, 0xa5, 0x9f, 0x89, 0xdc, 0xca, 0xf0, 0xe6, - 0x84, 0x92, 0xa8, 0xbe, 0x6c, 0x7a, 0x40, 0x56, 0x34, 0x22, - 0x18, 0x0e, 0xa1, 0xb7, 0x8d, 0x9b, 0xf9, 0xef, 0xd5, 0xc3, - 0x11, 0x07, 0x3d, 0x2b, 0x49, 0x5f, 0x65, 0x73, 0x00, 0x17, - 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, - 0xe4, 0xf3, 0xca, 0xdd, 0x6d, 0x7a, 0x43, 0x54, 0x31, 0x26, - 0x1f, 0x08, 0xd5, 0xc2, 0xfb, 0xec, 0x89, 0x9e, 0xa7, 0xb0, - 0xda, 0xcd, 0xf4, 0xe3, 0x86, 0x91, 0xa8, 0xbf, 0x62, 0x75, - 0x4c, 0x5b, 0x3e, 0x29, 0x10, 0x07, 0xb7, 0xa0, 0x99, 0x8e, - 0xeb, 0xfc, 0xc5, 0xd2, 0x0f, 0x18, 0x21, 0x36, 0x53, 0x44, - 0x7d, 0x6a, 0xa9, 0xbe, 0x87, 0x90, 0xf5, 0xe2, 0xdb, 0xcc, - 0x11, 0x06, 0x3f, 0x28, 0x4d, 0x5a, 0x63, 0x74, 0xc4, 0xd3, - 0xea, 0xfd, 0x98, 0x8f, 0xb6, 0xa1, 0x7c, 0x6b, 0x52, 0x45, - 0x20, 0x37, 0x0e, 0x19, 0x73, 0x64, 0x5d, 0x4a, 0x2f, 0x38, - 0x01, 0x16, 0xcb, 0xdc, 0xe5, 0xf2, 0x97, 0x80, 0xb9, 0xae, - 0x1e, 0x09, 0x30, 0x27, 0x42, 0x55, 0x6c, 0x7b, 0xa6, 0xb1, - 0x88, 0x9f, 0xfa, 0xed, 0xd4, 0xc3, 0x4f, 0x58, 0x61, 0x76, - 0x13, 0x04, 0x3d, 0x2a, 0xf7, 0xe0, 0xd9, 0xce, 0xab, 0xbc, - 0x85, 0x92, 0x22, 0x35, 0x0c, 0x1b, 0x7e, 0x69, 0x50, 0x47, - 0x9a, 0x8d, 0xb4, 0xa3, 0xc6, 0xd1, 0xe8, 0xff, 0x95, 0x82, - 0xbb, 0xac, 0xc9, 0xde, 0xe7, 0xf0, 0x2d, 0x3a, 0x03, 0x14, - 0x71, 0x66, 0x5f, 0x48, 0xf8, 0xef, 0xd6, 0xc1, 0xa4, 0xb3, - 0x8a, 0x9d, 0x40, 0x57, 0x6e, 0x79, 0x1c, 0x0b, 0x32, 0x25, - 0xe6, 0xf1, 0xc8, 0xdf, 0xba, 0xad, 0x94, 0x83, 0x5e, 0x49, - 0x70, 0x67, 0x02, 0x15, 0x2c, 0x3b, 0x8b, 0x9c, 0xa5, 0xb2, - 0xd7, 0xc0, 0xf9, 0xee, 0x33, 0x24, 0x1d, 0x0a, 0x6f, 0x78, - 0x41, 0x56, 0x3c, 0x2b, 0x12, 0x05, 0x60, 0x77, 0x4e, 0x59, - 0x84, 0x93, 0xaa, 0xbd, 0xd8, 0xcf, 0xf6, 0xe1, 0x51, 0x46, - 0x7f, 0x68, 0x0d, 0x1a, 0x23, 0x34, 0xe9, 0xfe, 0xc7, 0xd0, - 0xb5, 0xa2, 0x9b, 0x8c, 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, - 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88, - 0x9d, 0x85, 0xad, 0xb5, 0xfd, 0xe5, 0xcd, 0xd5, 0x5d, 0x45, - 0x6d, 0x75, 0x3d, 0x25, 0x0d, 0x15, 0x27, 0x3f, 0x17, 0x0f, - 0x47, 0x5f, 0x77, 0x6f, 0xe7, 0xff, 0xd7, 0xcf, 0x87, 0x9f, - 0xb7, 0xaf, 0xba, 0xa2, 0x8a, 0x92, 0xda, 0xc2, 0xea, 0xf2, - 0x7a, 0x62, 0x4a, 0x52, 0x1a, 0x02, 0x2a, 0x32, 0x4e, 0x56, - 0x7e, 0x66, 0x2e, 0x36, 0x1e, 0x06, 0x8e, 0x96, 0xbe, 0xa6, - 0xee, 0xf6, 0xde, 0xc6, 0xd3, 0xcb, 0xe3, 0xfb, 0xb3, 0xab, - 0x83, 0x9b, 0x13, 0x0b, 0x23, 0x3b, 0x73, 0x6b, 0x43, 0x5b, - 0x69, 0x71, 0x59, 0x41, 0x09, 0x11, 0x39, 0x21, 0xa9, 0xb1, - 0x99, 0x81, 0xc9, 0xd1, 0xf9, 0xe1, 0xf4, 0xec, 0xc4, 0xdc, - 0x94, 0x8c, 0xa4, 0xbc, 0x34, 0x2c, 0x04, 0x1c, 0x54, 0x4c, - 0x64, 0x7c, 0x9c, 0x84, 0xac, 0xb4, 0xfc, 0xe4, 0xcc, 0xd4, - 0x5c, 0x44, 0x6c, 0x74, 0x3c, 0x24, 0x0c, 0x14, 0x01, 0x19, - 0x31, 0x29, 0x61, 0x79, 0x51, 0x49, 0xc1, 0xd9, 0xf1, 0xe9, - 0xa1, 0xb9, 0x91, 0x89, 0xbb, 0xa3, 0x8b, 0x93, 0xdb, 0xc3, - 0xeb, 0xf3, 0x7b, 0x63, 0x4b, 0x53, 0x1b, 0x03, 0x2b, 0x33, - 0x26, 0x3e, 0x16, 0x0e, 0x46, 0x5e, 0x76, 0x6e, 0xe6, 0xfe, - 0xd6, 0xce, 0x86, 0x9e, 0xb6, 0xae, 0xd2, 0xca, 0xe2, 0xfa, - 0xb2, 0xaa, 0x82, 0x9a, 0x12, 0x0a, 0x22, 0x3a, 0x72, 0x6a, - 0x42, 0x5a, 0x4f, 0x57, 0x7f, 0x67, 0x2f, 0x37, 0x1f, 0x07, - 0x8f, 0x97, 0xbf, 0xa7, 0xef, 0xf7, 0xdf, 0xc7, 0xf5, 0xed, - 0xc5, 0xdd, 0x95, 0x8d, 0xa5, 0xbd, 0x35, 0x2d, 0x05, 0x1d, - 0x55, 0x4d, 0x65, 0x7d, 0x68, 0x70, 0x58, 0x40, 0x08, 0x10, - 0x38, 0x20, 0xa8, 0xb0, 0x98, 0x80, 0xc8, 0xd0, 0xf8, 0xe0, - 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, - 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87, 0x8d, 0x94, 0xbf, 0xa6, - 0xe9, 0xf0, 0xdb, 0xc2, 0x45, 0x5c, 0x77, 0x6e, 0x21, 0x38, - 0x13, 0x0a, 0x07, 0x1e, 0x35, 0x2c, 0x63, 0x7a, 0x51, 0x48, - 0xcf, 0xd6, 0xfd, 0xe4, 0xab, 0xb2, 0x99, 0x80, 0x8a, 0x93, - 0xb8, 0xa1, 0xee, 0xf7, 0xdc, 0xc5, 0x42, 0x5b, 0x70, 0x69, - 0x26, 0x3f, 0x14, 0x0d, 0x0e, 0x17, 0x3c, 0x25, 0x6a, 0x73, - 0x58, 0x41, 0xc6, 0xdf, 0xf4, 0xed, 0xa2, 0xbb, 0x90, 0x89, - 0x83, 0x9a, 0xb1, 0xa8, 0xe7, 0xfe, 0xd5, 0xcc, 0x4b, 0x52, - 0x79, 0x60, 0x2f, 0x36, 0x1d, 0x04, 0x09, 0x10, 0x3b, 0x22, - 0x6d, 0x74, 0x5f, 0x46, 0xc1, 0xd8, 0xf3, 0xea, 0xa5, 0xbc, - 0x97, 0x8e, 0x84, 0x9d, 0xb6, 0xaf, 0xe0, 0xf9, 0xd2, 0xcb, - 0x4c, 0x55, 0x7e, 0x67, 0x28, 0x31, 0x1a, 0x03, 0x1c, 0x05, - 0x2e, 0x37, 0x78, 0x61, 0x4a, 0x53, 0xd4, 0xcd, 0xe6, 0xff, - 0xb0, 0xa9, 0x82, 0x9b, 0x91, 0x88, 0xa3, 0xba, 0xf5, 0xec, - 0xc7, 0xde, 0x59, 0x40, 0x6b, 0x72, 0x3d, 0x24, 0x0f, 0x16, - 0x1b, 0x02, 0x29, 0x30, 0x7f, 0x66, 0x4d, 0x54, 0xd3, 0xca, - 0xe1, 0xf8, 0xb7, 0xae, 0x85, 0x9c, 0x96, 0x8f, 0xa4, 0xbd, - 0xf2, 0xeb, 0xc0, 0xd9, 0x5e, 0x47, 0x6c, 0x75, 0x3a, 0x23, - 0x08, 0x11, 0x12, 0x0b, 0x20, 0x39, 0x76, 0x6f, 0x44, 0x5d, - 0xda, 0xc3, 0xe8, 0xf1, 0xbe, 0xa7, 0x8c, 0x95, 0x9f, 0x86, - 0xad, 0xb4, 0xfb, 0xe2, 0xc9, 0xd0, 0x57, 0x4e, 0x65, 0x7c, - 0x33, 0x2a, 0x01, 0x18, 0x15, 0x0c, 0x27, 0x3e, 0x71, 0x68, - 0x43, 0x5a, 0xdd, 0xc4, 0xef, 0xf6, 0xb9, 0xa0, 0x8b, 0x92, - 0x98, 0x81, 0xaa, 0xb3, 0xfc, 0xe5, 0xce, 0xd7, 0x50, 0x49, - 0x62, 0x7b, 0x34, 0x2d, 0x06, 0x1f, 0x00, 0x1a, 0x34, 0x2e, - 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, - 0x8c, 0x96, 0xbd, 0xa7, 0x89, 0x93, 0xd5, 0xcf, 0xe1, 0xfb, - 0x6d, 0x77, 0x59, 0x43, 0x05, 0x1f, 0x31, 0x2b, 0x67, 0x7d, - 0x53, 0x49, 0x0f, 0x15, 0x3b, 0x21, 0xb7, 0xad, 0x83, 0x99, - 0xdf, 0xc5, 0xeb, 0xf1, 0xda, 0xc0, 0xee, 0xf4, 0xb2, 0xa8, - 0x86, 0x9c, 0x0a, 0x10, 0x3e, 0x24, 0x62, 0x78, 0x56, 0x4c, - 0xce, 0xd4, 0xfa, 0xe0, 0xa6, 0xbc, 0x92, 0x88, 0x1e, 0x04, - 0x2a, 0x30, 0x76, 0x6c, 0x42, 0x58, 0x73, 0x69, 0x47, 0x5d, - 0x1b, 0x01, 0x2f, 0x35, 0xa3, 0xb9, 0x97, 0x8d, 0xcb, 0xd1, - 0xff, 0xe5, 0xa9, 0xb3, 0x9d, 0x87, 0xc1, 0xdb, 0xf5, 0xef, - 0x79, 0x63, 0x4d, 0x57, 0x11, 0x0b, 0x25, 0x3f, 0x14, 0x0e, - 0x20, 0x3a, 0x7c, 0x66, 0x48, 0x52, 0xc4, 0xde, 0xf0, 0xea, - 0xac, 0xb6, 0x98, 0x82, 0x81, 0x9b, 0xb5, 0xaf, 0xe9, 0xf3, - 0xdd, 0xc7, 0x51, 0x4b, 0x65, 0x7f, 0x39, 0x23, 0x0d, 0x17, - 0x3c, 0x26, 0x08, 0x12, 0x54, 0x4e, 0x60, 0x7a, 0xec, 0xf6, - 0xd8, 0xc2, 0x84, 0x9e, 0xb0, 0xaa, 0xe6, 0xfc, 0xd2, 0xc8, - 0x8e, 0x94, 0xba, 0xa0, 0x36, 0x2c, 0x02, 0x18, 0x5e, 0x44, - 0x6a, 0x70, 0x5b, 0x41, 0x6f, 0x75, 0x33, 0x29, 0x07, 0x1d, - 0x8b, 0x91, 0xbf, 0xa5, 0xe3, 0xf9, 0xd7, 0xcd, 0x4f, 0x55, - 0x7b, 0x61, 0x27, 0x3d, 0x13, 0x09, 0x9f, 0x85, 0xab, 0xb1, - 0xf7, 0xed, 0xc3, 0xd9, 0xf2, 0xe8, 0xc6, 0xdc, 0x9a, 0x80, - 0xae, 0xb4, 0x22, 0x38, 0x16, 0x0c, 0x4a, 0x50, 0x7e, 0x64, - 0x28, 0x32, 0x1c, 0x06, 0x40, 0x5a, 0x74, 0x6e, 0xf8, 0xe2, - 0xcc, 0xd6, 0x90, 0x8a, 0xa4, 0xbe, 0x95, 0x8f, 0xa1, 0xbb, - 0xfd, 0xe7, 0xc9, 0xd3, 0x45, 0x5f, 0x71, 0x6b, 0x2d, 0x37, - 0x19, 0x03, 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, - 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99, 0xad, 0xb6, - 0x9b, 0x80, 0xc1, 0xda, 0xf7, 0xec, 0x75, 0x6e, 0x43, 0x58, - 0x19, 0x02, 0x2f, 0x34, 0x47, 0x5c, 0x71, 0x6a, 0x2b, 0x30, - 0x1d, 0x06, 0x9f, 0x84, 0xa9, 0xb2, 0xf3, 0xe8, 0xc5, 0xde, - 0xea, 0xf1, 0xdc, 0xc7, 0x86, 0x9d, 0xb0, 0xab, 0x32, 0x29, - 0x04, 0x1f, 0x5e, 0x45, 0x68, 0x73, 0x8e, 0x95, 0xb8, 0xa3, - 0xe2, 0xf9, 0xd4, 0xcf, 0x56, 0x4d, 0x60, 0x7b, 0x3a, 0x21, - 0x0c, 0x17, 0x23, 0x38, 0x15, 0x0e, 0x4f, 0x54, 0x79, 0x62, - 0xfb, 0xe0, 0xcd, 0xd6, 0x97, 0x8c, 0xa1, 0xba, 0xc9, 0xd2, - 0xff, 0xe4, 0xa5, 0xbe, 0x93, 0x88, 0x11, 0x0a, 0x27, 0x3c, - 0x7d, 0x66, 0x4b, 0x50, 0x64, 0x7f, 0x52, 0x49, 0x08, 0x13, - 0x3e, 0x25, 0xbc, 0xa7, 0x8a, 0x91, 0xd0, 0xcb, 0xe6, 0xfd, - 0x01, 0x1a, 0x37, 0x2c, 0x6d, 0x76, 0x5b, 0x40, 0xd9, 0xc2, - 0xef, 0xf4, 0xb5, 0xae, 0x83, 0x98, 0xac, 0xb7, 0x9a, 0x81, - 0xc0, 0xdb, 0xf6, 0xed, 0x74, 0x6f, 0x42, 0x59, 0x18, 0x03, - 0x2e, 0x35, 0x46, 0x5d, 0x70, 0x6b, 0x2a, 0x31, 0x1c, 0x07, - 0x9e, 0x85, 0xa8, 0xb3, 0xf2, 0xe9, 0xc4, 0xdf, 0xeb, 0xf0, - 0xdd, 0xc6, 0x87, 0x9c, 0xb1, 0xaa, 0x33, 0x28, 0x05, 0x1e, - 0x5f, 0x44, 0x69, 0x72, 0x8f, 0x94, 0xb9, 0xa2, 0xe3, 0xf8, - 0xd5, 0xce, 0x57, 0x4c, 0x61, 0x7a, 0x3b, 0x20, 0x0d, 0x16, - 0x22, 0x39, 0x14, 0x0f, 0x4e, 0x55, 0x78, 0x63, 0xfa, 0xe1, - 0xcc, 0xd7, 0x96, 0x8d, 0xa0, 0xbb, 0xc8, 0xd3, 0xfe, 0xe5, - 0xa4, 0xbf, 0x92, 0x89, 0x10, 0x0b, 0x26, 0x3d, 0x7c, 0x67, - 0x4a, 0x51, 0x65, 0x7e, 0x53, 0x48, 0x09, 0x12, 0x3f, 0x24, - 0xbd, 0xa6, 0x8b, 0x90, 0xd1, 0xca, 0xe7, 0xfc, 0x00, 0x1c, - 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, - 0x90, 0x8c, 0xa8, 0xb4, 0xdd, 0xc1, 0xe5, 0xf9, 0xad, 0xb1, - 0x95, 0x89, 0x3d, 0x21, 0x05, 0x19, 0x4d, 0x51, 0x75, 0x69, - 0xa7, 0xbb, 0x9f, 0x83, 0xd7, 0xcb, 0xef, 0xf3, 0x47, 0x5b, - 0x7f, 0x63, 0x37, 0x2b, 0x0f, 0x13, 0x7a, 0x66, 0x42, 0x5e, - 0x0a, 0x16, 0x32, 0x2e, 0x9a, 0x86, 0xa2, 0xbe, 0xea, 0xf6, - 0xd2, 0xce, 0x53, 0x4f, 0x6b, 0x77, 0x23, 0x3f, 0x1b, 0x07, - 0xb3, 0xaf, 0x8b, 0x97, 0xc3, 0xdf, 0xfb, 0xe7, 0x8e, 0x92, - 0xb6, 0xaa, 0xfe, 0xe2, 0xc6, 0xda, 0x6e, 0x72, 0x56, 0x4a, - 0x1e, 0x02, 0x26, 0x3a, 0xf4, 0xe8, 0xcc, 0xd0, 0x84, 0x98, - 0xbc, 0xa0, 0x14, 0x08, 0x2c, 0x30, 0x64, 0x78, 0x5c, 0x40, - 0x29, 0x35, 0x11, 0x0d, 0x59, 0x45, 0x61, 0x7d, 0xc9, 0xd5, - 0xf1, 0xed, 0xb9, 0xa5, 0x81, 0x9d, 0xa6, 0xba, 0x9e, 0x82, - 0xd6, 0xca, 0xee, 0xf2, 0x46, 0x5a, 0x7e, 0x62, 0x36, 0x2a, - 0x0e, 0x12, 0x7b, 0x67, 0x43, 0x5f, 0x0b, 0x17, 0x33, 0x2f, - 0x9b, 0x87, 0xa3, 0xbf, 0xeb, 0xf7, 0xd3, 0xcf, 0x01, 0x1d, - 0x39, 0x25, 0x71, 0x6d, 0x49, 0x55, 0xe1, 0xfd, 0xd9, 0xc5, - 0x91, 0x8d, 0xa9, 0xb5, 0xdc, 0xc0, 0xe4, 0xf8, 0xac, 0xb0, - 0x94, 0x88, 0x3c, 0x20, 0x04, 0x18, 0x4c, 0x50, 0x74, 0x68, - 0xf5, 0xe9, 0xcd, 0xd1, 0x85, 0x99, 0xbd, 0xa1, 0x15, 0x09, - 0x2d, 0x31, 0x65, 0x79, 0x5d, 0x41, 0x28, 0x34, 0x10, 0x0c, - 0x58, 0x44, 0x60, 0x7c, 0xc8, 0xd4, 0xf0, 0xec, 0xb8, 0xa4, - 0x80, 0x9c, 0x52, 0x4e, 0x6a, 0x76, 0x22, 0x3e, 0x1a, 0x06, - 0xb2, 0xae, 0x8a, 0x96, 0xc2, 0xde, 0xfa, 0xe6, 0x8f, 0x93, - 0xb7, 0xab, 0xff, 0xe3, 0xc7, 0xdb, 0x6f, 0x73, 0x57, 0x4b, - 0x1f, 0x03, 0x27, 0x3b, 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, - 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, - 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, 0x25, 0x38, - 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 0x87, 0x9a, 0xbd, 0xa0, - 0xf3, 0xee, 0xc9, 0xd4, 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, - 0x21, 0x3c, 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, - 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, 0x13, 0x0e, - 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, 0xfb, 0xe6, 0xc1, 0xdc, - 0x8f, 0x92, 0xb5, 0xa8, 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, - 0x90, 0x8d, 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, - 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 0x7c, 0x61, - 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, 0x59, 0x44, 0x63, 0x7e, - 0x2d, 0x30, 0x17, 0x0a, 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, - 0xff, 0xe2, 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, - 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, 0xeb, 0xf6, - 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 0x03, 0x1e, 0x39, 0x24, - 0x77, 0x6a, 0x4d, 0x50, 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, - 0xef, 0xf2, 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, - 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, 0x84, 0x99, - 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, 0x35, 0x28, 0x0f, 0x12, - 0x41, 0x5c, 0x7b, 0x66, 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, - 0x93, 0x8e, 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, - 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 0xb2, 0xaf, - 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, 0x5a, 0x47, 0x60, 0x7d, - 0x2e, 0x33, 0x14, 0x09, 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, - 0x31, 0x2c, 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4, - 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, - 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa, 0xfd, 0xe3, 0xc1, 0xdf, - 0x85, 0x9b, 0xb9, 0xa7, 0x0d, 0x13, 0x31, 0x2f, 0x75, 0x6b, - 0x49, 0x57, 0xe7, 0xf9, 0xdb, 0xc5, 0x9f, 0x81, 0xa3, 0xbd, - 0x17, 0x09, 0x2b, 0x35, 0x6f, 0x71, 0x53, 0x4d, 0x1a, 0x04, - 0x26, 0x38, 0x62, 0x7c, 0x5e, 0x40, 0xea, 0xf4, 0xd6, 0xc8, - 0x92, 0x8c, 0xae, 0xb0, 0xd3, 0xcd, 0xef, 0xf1, 0xab, 0xb5, - 0x97, 0x89, 0x23, 0x3d, 0x1f, 0x01, 0x5b, 0x45, 0x67, 0x79, - 0x2e, 0x30, 0x12, 0x0c, 0x56, 0x48, 0x6a, 0x74, 0xde, 0xc0, - 0xe2, 0xfc, 0xa6, 0xb8, 0x9a, 0x84, 0x34, 0x2a, 0x08, 0x16, - 0x4c, 0x52, 0x70, 0x6e, 0xc4, 0xda, 0xf8, 0xe6, 0xbc, 0xa2, - 0x80, 0x9e, 0xc9, 0xd7, 0xf5, 0xeb, 0xb1, 0xaf, 0x8d, 0x93, - 0x39, 0x27, 0x05, 0x1b, 0x41, 0x5f, 0x7d, 0x63, 0xbb, 0xa5, - 0x87, 0x99, 0xc3, 0xdd, 0xff, 0xe1, 0x4b, 0x55, 0x77, 0x69, - 0x33, 0x2d, 0x0f, 0x11, 0x46, 0x58, 0x7a, 0x64, 0x3e, 0x20, - 0x02, 0x1c, 0xb6, 0xa8, 0x8a, 0x94, 0xce, 0xd0, 0xf2, 0xec, - 0x5c, 0x42, 0x60, 0x7e, 0x24, 0x3a, 0x18, 0x06, 0xac, 0xb2, - 0x90, 0x8e, 0xd4, 0xca, 0xe8, 0xf6, 0xa1, 0xbf, 0x9d, 0x83, - 0xd9, 0xc7, 0xe5, 0xfb, 0x51, 0x4f, 0x6d, 0x73, 0x29, 0x37, - 0x15, 0x0b, 0x68, 0x76, 0x54, 0x4a, 0x10, 0x0e, 0x2c, 0x32, - 0x98, 0x86, 0xa4, 0xba, 0xe0, 0xfe, 0xdc, 0xc2, 0x95, 0x8b, - 0xa9, 0xb7, 0xed, 0xf3, 0xd1, 0xcf, 0x65, 0x7b, 0x59, 0x47, - 0x1d, 0x03, 0x21, 0x3f, 0x8f, 0x91, 0xb3, 0xad, 0xf7, 0xe9, - 0xcb, 0xd5, 0x7f, 0x61, 0x43, 0x5d, 0x07, 0x19, 0x3b, 0x25, - 0x72, 0x6c, 0x4e, 0x50, 0x0a, 0x14, 0x36, 0x28, 0x82, 0x9c, - 0xbe, 0xa0, 0xfa, 0xe4, 0xc6, 0xd8, 0x00, 0x1f, 0x3e, 0x21, - 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, - 0xba, 0xa5, 0xed, 0xf2, 0xd3, 0xcc, 0x91, 0x8e, 0xaf, 0xb0, - 0x15, 0x0a, 0x2b, 0x34, 0x69, 0x76, 0x57, 0x48, 0xc7, 0xd8, - 0xf9, 0xe6, 0xbb, 0xa4, 0x85, 0x9a, 0x3f, 0x20, 0x01, 0x1e, - 0x43, 0x5c, 0x7d, 0x62, 0x2a, 0x35, 0x14, 0x0b, 0x56, 0x49, - 0x68, 0x77, 0xd2, 0xcd, 0xec, 0xf3, 0xae, 0xb1, 0x90, 0x8f, - 0x93, 0x8c, 0xad, 0xb2, 0xef, 0xf0, 0xd1, 0xce, 0x6b, 0x74, - 0x55, 0x4a, 0x17, 0x08, 0x29, 0x36, 0x7e, 0x61, 0x40, 0x5f, - 0x02, 0x1d, 0x3c, 0x23, 0x86, 0x99, 0xb8, 0xa7, 0xfa, 0xe5, - 0xc4, 0xdb, 0x54, 0x4b, 0x6a, 0x75, 0x28, 0x37, 0x16, 0x09, - 0xac, 0xb3, 0x92, 0x8d, 0xd0, 0xcf, 0xee, 0xf1, 0xb9, 0xa6, - 0x87, 0x98, 0xc5, 0xda, 0xfb, 0xe4, 0x41, 0x5e, 0x7f, 0x60, - 0x3d, 0x22, 0x03, 0x1c, 0x3b, 0x24, 0x05, 0x1a, 0x47, 0x58, - 0x79, 0x66, 0xc3, 0xdc, 0xfd, 0xe2, 0xbf, 0xa0, 0x81, 0x9e, - 0xd6, 0xc9, 0xe8, 0xf7, 0xaa, 0xb5, 0x94, 0x8b, 0x2e, 0x31, - 0x10, 0x0f, 0x52, 0x4d, 0x6c, 0x73, 0xfc, 0xe3, 0xc2, 0xdd, - 0x80, 0x9f, 0xbe, 0xa1, 0x04, 0x1b, 0x3a, 0x25, 0x78, 0x67, - 0x46, 0x59, 0x11, 0x0e, 0x2f, 0x30, 0x6d, 0x72, 0x53, 0x4c, - 0xe9, 0xf6, 0xd7, 0xc8, 0x95, 0x8a, 0xab, 0xb4, 0xa8, 0xb7, - 0x96, 0x89, 0xd4, 0xcb, 0xea, 0xf5, 0x50, 0x4f, 0x6e, 0x71, - 0x2c, 0x33, 0x12, 0x0d, 0x45, 0x5a, 0x7b, 0x64, 0x39, 0x26, - 0x07, 0x18, 0xbd, 0xa2, 0x83, 0x9c, 0xc1, 0xde, 0xff, 0xe0, - 0x6f, 0x70, 0x51, 0x4e, 0x13, 0x0c, 0x2d, 0x32, 0x97, 0x88, - 0xa9, 0xb6, 0xeb, 0xf4, 0xd5, 0xca, 0x82, 0x9d, 0xbc, 0xa3, - 0xfe, 0xe1, 0xc0, 0xdf, 0x7a, 0x65, 0x44, 0x5b, 0x06, 0x19, - 0x38, 0x27, 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, - 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd, 0x3a, 0x1a, - 0x7a, 0x5a, 0xba, 0x9a, 0xfa, 0xda, 0x27, 0x07, 0x67, 0x47, - 0xa7, 0x87, 0xe7, 0xc7, 0x74, 0x54, 0x34, 0x14, 0xf4, 0xd4, - 0xb4, 0x94, 0x69, 0x49, 0x29, 0x09, 0xe9, 0xc9, 0xa9, 0x89, - 0x4e, 0x6e, 0x0e, 0x2e, 0xce, 0xee, 0x8e, 0xae, 0x53, 0x73, - 0x13, 0x33, 0xd3, 0xf3, 0x93, 0xb3, 0xe8, 0xc8, 0xa8, 0x88, - 0x68, 0x48, 0x28, 0x08, 0xf5, 0xd5, 0xb5, 0x95, 0x75, 0x55, - 0x35, 0x15, 0xd2, 0xf2, 0x92, 0xb2, 0x52, 0x72, 0x12, 0x32, - 0xcf, 0xef, 0x8f, 0xaf, 0x4f, 0x6f, 0x0f, 0x2f, 0x9c, 0xbc, - 0xdc, 0xfc, 0x1c, 0x3c, 0x5c, 0x7c, 0x81, 0xa1, 0xc1, 0xe1, - 0x01, 0x21, 0x41, 0x61, 0xa6, 0x86, 0xe6, 0xc6, 0x26, 0x06, - 0x66, 0x46, 0xbb, 0x9b, 0xfb, 0xdb, 0x3b, 0x1b, 0x7b, 0x5b, - 0xcd, 0xed, 0x8d, 0xad, 0x4d, 0x6d, 0x0d, 0x2d, 0xd0, 0xf0, - 0x90, 0xb0, 0x50, 0x70, 0x10, 0x30, 0xf7, 0xd7, 0xb7, 0x97, - 0x77, 0x57, 0x37, 0x17, 0xea, 0xca, 0xaa, 0x8a, 0x6a, 0x4a, - 0x2a, 0x0a, 0xb9, 0x99, 0xf9, 0xd9, 0x39, 0x19, 0x79, 0x59, - 0xa4, 0x84, 0xe4, 0xc4, 0x24, 0x04, 0x64, 0x44, 0x83, 0xa3, - 0xc3, 0xe3, 0x03, 0x23, 0x43, 0x63, 0x9e, 0xbe, 0xde, 0xfe, - 0x1e, 0x3e, 0x5e, 0x7e, 0x25, 0x05, 0x65, 0x45, 0xa5, 0x85, - 0xe5, 0xc5, 0x38, 0x18, 0x78, 0x58, 0xb8, 0x98, 0xf8, 0xd8, - 0x1f, 0x3f, 0x5f, 0x7f, 0x9f, 0xbf, 0xdf, 0xff, 0x02, 0x22, - 0x42, 0x62, 0x82, 0xa2, 0xc2, 0xe2, 0x51, 0x71, 0x11, 0x31, - 0xd1, 0xf1, 0x91, 0xb1, 0x4c, 0x6c, 0x0c, 0x2c, 0xcc, 0xec, - 0x8c, 0xac, 0x6b, 0x4b, 0x2b, 0x0b, 0xeb, 0xcb, 0xab, 0x8b, - 0x76, 0x56, 0x36, 0x16, 0xf6, 0xd6, 0xb6, 0x96, 0x00, 0x21, - 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, - 0x91, 0xb0, 0xd3, 0xf2, 0x2a, 0x0b, 0x68, 0x49, 0xae, 0x8f, - 0xec, 0xcd, 0x3f, 0x1e, 0x7d, 0x5c, 0xbb, 0x9a, 0xf9, 0xd8, - 0x54, 0x75, 0x16, 0x37, 0xd0, 0xf1, 0x92, 0xb3, 0x41, 0x60, - 0x03, 0x22, 0xc5, 0xe4, 0x87, 0xa6, 0x7e, 0x5f, 0x3c, 0x1d, - 0xfa, 0xdb, 0xb8, 0x99, 0x6b, 0x4a, 0x29, 0x08, 0xef, 0xce, - 0xad, 0x8c, 0xa8, 0x89, 0xea, 0xcb, 0x2c, 0x0d, 0x6e, 0x4f, - 0xbd, 0x9c, 0xff, 0xde, 0x39, 0x18, 0x7b, 0x5a, 0x82, 0xa3, - 0xc0, 0xe1, 0x06, 0x27, 0x44, 0x65, 0x97, 0xb6, 0xd5, 0xf4, - 0x13, 0x32, 0x51, 0x70, 0xfc, 0xdd, 0xbe, 0x9f, 0x78, 0x59, - 0x3a, 0x1b, 0xe9, 0xc8, 0xab, 0x8a, 0x6d, 0x4c, 0x2f, 0x0e, - 0xd6, 0xf7, 0x94, 0xb5, 0x52, 0x73, 0x10, 0x31, 0xc3, 0xe2, - 0x81, 0xa0, 0x47, 0x66, 0x05, 0x24, 0x4d, 0x6c, 0x0f, 0x2e, - 0xc9, 0xe8, 0x8b, 0xaa, 0x58, 0x79, 0x1a, 0x3b, 0xdc, 0xfd, - 0x9e, 0xbf, 0x67, 0x46, 0x25, 0x04, 0xe3, 0xc2, 0xa1, 0x80, - 0x72, 0x53, 0x30, 0x11, 0xf6, 0xd7, 0xb4, 0x95, 0x19, 0x38, - 0x5b, 0x7a, 0x9d, 0xbc, 0xdf, 0xfe, 0x0c, 0x2d, 0x4e, 0x6f, - 0x88, 0xa9, 0xca, 0xeb, 0x33, 0x12, 0x71, 0x50, 0xb7, 0x96, - 0xf5, 0xd4, 0x26, 0x07, 0x64, 0x45, 0xa2, 0x83, 0xe0, 0xc1, - 0xe5, 0xc4, 0xa7, 0x86, 0x61, 0x40, 0x23, 0x02, 0xf0, 0xd1, - 0xb2, 0x93, 0x74, 0x55, 0x36, 0x17, 0xcf, 0xee, 0x8d, 0xac, - 0x4b, 0x6a, 0x09, 0x28, 0xda, 0xfb, 0x98, 0xb9, 0x5e, 0x7f, - 0x1c, 0x3d, 0xb1, 0x90, 0xf3, 0xd2, 0x35, 0x14, 0x77, 0x56, - 0xa4, 0x85, 0xe6, 0xc7, 0x20, 0x01, 0x62, 0x43, 0x9b, 0xba, - 0xd9, 0xf8, 0x1f, 0x3e, 0x5d, 0x7c, 0x8e, 0xaf, 0xcc, 0xed, - 0x0a, 0x2b, 0x48, 0x69, 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, - 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3, - 0x1a, 0x38, 0x5e, 0x7c, 0x92, 0xb0, 0xd6, 0xf4, 0x17, 0x35, - 0x53, 0x71, 0x9f, 0xbd, 0xdb, 0xf9, 0x34, 0x16, 0x70, 0x52, - 0xbc, 0x9e, 0xf8, 0xda, 0x39, 0x1b, 0x7d, 0x5f, 0xb1, 0x93, - 0xf5, 0xd7, 0x2e, 0x0c, 0x6a, 0x48, 0xa6, 0x84, 0xe2, 0xc0, - 0x23, 0x01, 0x67, 0x45, 0xab, 0x89, 0xef, 0xcd, 0x68, 0x4a, - 0x2c, 0x0e, 0xe0, 0xc2, 0xa4, 0x86, 0x65, 0x47, 0x21, 0x03, - 0xed, 0xcf, 0xa9, 0x8b, 0x72, 0x50, 0x36, 0x14, 0xfa, 0xd8, - 0xbe, 0x9c, 0x7f, 0x5d, 0x3b, 0x19, 0xf7, 0xd5, 0xb3, 0x91, - 0x5c, 0x7e, 0x18, 0x3a, 0xd4, 0xf6, 0x90, 0xb2, 0x51, 0x73, - 0x15, 0x37, 0xd9, 0xfb, 0x9d, 0xbf, 0x46, 0x64, 0x02, 0x20, - 0xce, 0xec, 0x8a, 0xa8, 0x4b, 0x69, 0x0f, 0x2d, 0xc3, 0xe1, - 0x87, 0xa5, 0xd0, 0xf2, 0x94, 0xb6, 0x58, 0x7a, 0x1c, 0x3e, - 0xdd, 0xff, 0x99, 0xbb, 0x55, 0x77, 0x11, 0x33, 0xca, 0xe8, - 0x8e, 0xac, 0x42, 0x60, 0x06, 0x24, 0xc7, 0xe5, 0x83, 0xa1, - 0x4f, 0x6d, 0x0b, 0x29, 0xe4, 0xc6, 0xa0, 0x82, 0x6c, 0x4e, - 0x28, 0x0a, 0xe9, 0xcb, 0xad, 0x8f, 0x61, 0x43, 0x25, 0x07, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf3, 0xd1, - 0xb7, 0x95, 0x7b, 0x59, 0x3f, 0x1d, 0xb8, 0x9a, 0xfc, 0xde, - 0x30, 0x12, 0x74, 0x56, 0xb5, 0x97, 0xf1, 0xd3, 0x3d, 0x1f, - 0x79, 0x5b, 0xa2, 0x80, 0xe6, 0xc4, 0x2a, 0x08, 0x6e, 0x4c, - 0xaf, 0x8d, 0xeb, 0xc9, 0x27, 0x05, 0x63, 0x41, 0x8c, 0xae, - 0xc8, 0xea, 0x04, 0x26, 0x40, 0x62, 0x81, 0xa3, 0xc5, 0xe7, - 0x09, 0x2b, 0x4d, 0x6f, 0x96, 0xb4, 0xd2, 0xf0, 0x1e, 0x3c, - 0x5a, 0x78, 0x9b, 0xb9, 0xdf, 0xfd, 0x13, 0x31, 0x57, 0x75, - 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, - 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec, 0x0a, 0x29, 0x4c, 0x6f, - 0x86, 0xa5, 0xc0, 0xe3, 0x0f, 0x2c, 0x49, 0x6a, 0x83, 0xa0, - 0xc5, 0xe6, 0x14, 0x37, 0x52, 0x71, 0x98, 0xbb, 0xde, 0xfd, - 0x11, 0x32, 0x57, 0x74, 0x9d, 0xbe, 0xdb, 0xf8, 0x1e, 0x3d, - 0x58, 0x7b, 0x92, 0xb1, 0xd4, 0xf7, 0x1b, 0x38, 0x5d, 0x7e, - 0x97, 0xb4, 0xd1, 0xf2, 0x28, 0x0b, 0x6e, 0x4d, 0xa4, 0x87, - 0xe2, 0xc1, 0x2d, 0x0e, 0x6b, 0x48, 0xa1, 0x82, 0xe7, 0xc4, - 0x22, 0x01, 0x64, 0x47, 0xae, 0x8d, 0xe8, 0xcb, 0x27, 0x04, - 0x61, 0x42, 0xab, 0x88, 0xed, 0xce, 0x3c, 0x1f, 0x7a, 0x59, - 0xb0, 0x93, 0xf6, 0xd5, 0x39, 0x1a, 0x7f, 0x5c, 0xb5, 0x96, - 0xf3, 0xd0, 0x36, 0x15, 0x70, 0x53, 0xba, 0x99, 0xfc, 0xdf, - 0x33, 0x10, 0x75, 0x56, 0xbf, 0x9c, 0xf9, 0xda, 0x50, 0x73, - 0x16, 0x35, 0xdc, 0xff, 0x9a, 0xb9, 0x55, 0x76, 0x13, 0x30, - 0xd9, 0xfa, 0x9f, 0xbc, 0x5a, 0x79, 0x1c, 0x3f, 0xd6, 0xf5, - 0x90, 0xb3, 0x5f, 0x7c, 0x19, 0x3a, 0xd3, 0xf0, 0x95, 0xb6, - 0x44, 0x67, 0x02, 0x21, 0xc8, 0xeb, 0x8e, 0xad, 0x41, 0x62, - 0x07, 0x24, 0xcd, 0xee, 0x8b, 0xa8, 0x4e, 0x6d, 0x08, 0x2b, - 0xc2, 0xe1, 0x84, 0xa7, 0x4b, 0x68, 0x0d, 0x2e, 0xc7, 0xe4, - 0x81, 0xa2, 0x78, 0x5b, 0x3e, 0x1d, 0xf4, 0xd7, 0xb2, 0x91, - 0x7d, 0x5e, 0x3b, 0x18, 0xf1, 0xd2, 0xb7, 0x94, 0x72, 0x51, - 0x34, 0x17, 0xfe, 0xdd, 0xb8, 0x9b, 0x77, 0x54, 0x31, 0x12, - 0xfb, 0xd8, 0xbd, 0x9e, 0x6c, 0x4f, 0x2a, 0x09, 0xe0, 0xc3, - 0xa6, 0x85, 0x69, 0x4a, 0x2f, 0x0c, 0xe5, 0xc6, 0xa3, 0x80, - 0x66, 0x45, 0x20, 0x03, 0xea, 0xc9, 0xac, 0x8f, 0x63, 0x40, - 0x25, 0x06, 0xef, 0xcc, 0xa9, 0x8a, 0x00, 0x24, 0x48, 0x6c, - 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, - 0xe5, 0xc1, 0x7a, 0x5e, 0x32, 0x16, 0xea, 0xce, 0xa2, 0x86, - 0x47, 0x63, 0x0f, 0x2b, 0xd7, 0xf3, 0x9f, 0xbb, 0xf4, 0xd0, - 0xbc, 0x98, 0x64, 0x40, 0x2c, 0x08, 0xc9, 0xed, 0x81, 0xa5, - 0x59, 0x7d, 0x11, 0x35, 0x8e, 0xaa, 0xc6, 0xe2, 0x1e, 0x3a, - 0x56, 0x72, 0xb3, 0x97, 0xfb, 0xdf, 0x23, 0x07, 0x6b, 0x4f, - 0xf5, 0xd1, 0xbd, 0x99, 0x65, 0x41, 0x2d, 0x09, 0xc8, 0xec, - 0x80, 0xa4, 0x58, 0x7c, 0x10, 0x34, 0x8f, 0xab, 0xc7, 0xe3, - 0x1f, 0x3b, 0x57, 0x73, 0xb2, 0x96, 0xfa, 0xde, 0x22, 0x06, - 0x6a, 0x4e, 0x01, 0x25, 0x49, 0x6d, 0x91, 0xb5, 0xd9, 0xfd, - 0x3c, 0x18, 0x74, 0x50, 0xac, 0x88, 0xe4, 0xc0, 0x7b, 0x5f, - 0x33, 0x17, 0xeb, 0xcf, 0xa3, 0x87, 0x46, 0x62, 0x0e, 0x2a, - 0xd6, 0xf2, 0x9e, 0xba, 0xf7, 0xd3, 0xbf, 0x9b, 0x67, 0x43, - 0x2f, 0x0b, 0xca, 0xee, 0x82, 0xa6, 0x5a, 0x7e, 0x12, 0x36, - 0x8d, 0xa9, 0xc5, 0xe1, 0x1d, 0x39, 0x55, 0x71, 0xb0, 0x94, - 0xf8, 0xdc, 0x20, 0x04, 0x68, 0x4c, 0x03, 0x27, 0x4b, 0x6f, - 0x93, 0xb7, 0xdb, 0xff, 0x3e, 0x1a, 0x76, 0x52, 0xae, 0x8a, - 0xe6, 0xc2, 0x79, 0x5d, 0x31, 0x15, 0xe9, 0xcd, 0xa1, 0x85, - 0x44, 0x60, 0x0c, 0x28, 0xd4, 0xf0, 0x9c, 0xb8, 0x02, 0x26, - 0x4a, 0x6e, 0x92, 0xb6, 0xda, 0xfe, 0x3f, 0x1b, 0x77, 0x53, - 0xaf, 0x8b, 0xe7, 0xc3, 0x78, 0x5c, 0x30, 0x14, 0xe8, 0xcc, - 0xa0, 0x84, 0x45, 0x61, 0x0d, 0x29, 0xd5, 0xf1, 0x9d, 0xb9, - 0xf6, 0xd2, 0xbe, 0x9a, 0x66, 0x42, 0x2e, 0x0a, 0xcb, 0xef, - 0x83, 0xa7, 0x5b, 0x7f, 0x13, 0x37, 0x8c, 0xa8, 0xc4, 0xe0, - 0x1c, 0x38, 0x54, 0x70, 0xb1, 0x95, 0xf9, 0xdd, 0x21, 0x05, - 0x69, 0x4d, 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, - 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce, 0x6a, 0x4f, - 0x20, 0x05, 0xfe, 0xdb, 0xb4, 0x91, 0x5f, 0x7a, 0x15, 0x30, - 0xcb, 0xee, 0x81, 0xa4, 0xd4, 0xf1, 0x9e, 0xbb, 0x40, 0x65, - 0x0a, 0x2f, 0xe1, 0xc4, 0xab, 0x8e, 0x75, 0x50, 0x3f, 0x1a, - 0xbe, 0x9b, 0xf4, 0xd1, 0x2a, 0x0f, 0x60, 0x45, 0x8b, 0xae, - 0xc1, 0xe4, 0x1f, 0x3a, 0x55, 0x70, 0xb5, 0x90, 0xff, 0xda, - 0x21, 0x04, 0x6b, 0x4e, 0x80, 0xa5, 0xca, 0xef, 0x14, 0x31, - 0x5e, 0x7b, 0xdf, 0xfa, 0x95, 0xb0, 0x4b, 0x6e, 0x01, 0x24, - 0xea, 0xcf, 0xa0, 0x85, 0x7e, 0x5b, 0x34, 0x11, 0x61, 0x44, - 0x2b, 0x0e, 0xf5, 0xd0, 0xbf, 0x9a, 0x54, 0x71, 0x1e, 0x3b, - 0xc0, 0xe5, 0x8a, 0xaf, 0x0b, 0x2e, 0x41, 0x64, 0x9f, 0xba, - 0xd5, 0xf0, 0x3e, 0x1b, 0x74, 0x51, 0xaa, 0x8f, 0xe0, 0xc5, - 0x77, 0x52, 0x3d, 0x18, 0xe3, 0xc6, 0xa9, 0x8c, 0x42, 0x67, - 0x08, 0x2d, 0xd6, 0xf3, 0x9c, 0xb9, 0x1d, 0x38, 0x57, 0x72, - 0x89, 0xac, 0xc3, 0xe6, 0x28, 0x0d, 0x62, 0x47, 0xbc, 0x99, - 0xf6, 0xd3, 0xa3, 0x86, 0xe9, 0xcc, 0x37, 0x12, 0x7d, 0x58, - 0x96, 0xb3, 0xdc, 0xf9, 0x02, 0x27, 0x48, 0x6d, 0xc9, 0xec, - 0x83, 0xa6, 0x5d, 0x78, 0x17, 0x32, 0xfc, 0xd9, 0xb6, 0x93, - 0x68, 0x4d, 0x22, 0x07, 0xc2, 0xe7, 0x88, 0xad, 0x56, 0x73, - 0x1c, 0x39, 0xf7, 0xd2, 0xbd, 0x98, 0x63, 0x46, 0x29, 0x0c, - 0xa8, 0x8d, 0xe2, 0xc7, 0x3c, 0x19, 0x76, 0x53, 0x9d, 0xb8, - 0xd7, 0xf2, 0x09, 0x2c, 0x43, 0x66, 0x16, 0x33, 0x5c, 0x79, - 0x82, 0xa7, 0xc8, 0xed, 0x23, 0x06, 0x69, 0x4c, 0xb7, 0x92, - 0xfd, 0xd8, 0x7c, 0x59, 0x36, 0x13, 0xe8, 0xcd, 0xa2, 0x87, - 0x49, 0x6c, 0x03, 0x26, 0xdd, 0xf8, 0x97, 0xb2, 0x00, 0x26, - 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, - 0xb5, 0x93, 0xf9, 0xdf, 0x5a, 0x7c, 0x16, 0x30, 0xc2, 0xe4, - 0x8e, 0xa8, 0x77, 0x51, 0x3b, 0x1d, 0xef, 0xc9, 0xa3, 0x85, - 0xb4, 0x92, 0xf8, 0xde, 0x2c, 0x0a, 0x60, 0x46, 0x99, 0xbf, - 0xd5, 0xf3, 0x01, 0x27, 0x4d, 0x6b, 0xee, 0xc8, 0xa2, 0x84, - 0x76, 0x50, 0x3a, 0x1c, 0xc3, 0xe5, 0x8f, 0xa9, 0x5b, 0x7d, - 0x17, 0x31, 0x75, 0x53, 0x39, 0x1f, 0xed, 0xcb, 0xa1, 0x87, - 0x58, 0x7e, 0x14, 0x32, 0xc0, 0xe6, 0x8c, 0xaa, 0x2f, 0x09, - 0x63, 0x45, 0xb7, 0x91, 0xfb, 0xdd, 0x02, 0x24, 0x4e, 0x68, - 0x9a, 0xbc, 0xd6, 0xf0, 0xc1, 0xe7, 0x8d, 0xab, 0x59, 0x7f, - 0x15, 0x33, 0xec, 0xca, 0xa0, 0x86, 0x74, 0x52, 0x38, 0x1e, - 0x9b, 0xbd, 0xd7, 0xf1, 0x03, 0x25, 0x4f, 0x69, 0xb6, 0x90, - 0xfa, 0xdc, 0x2e, 0x08, 0x62, 0x44, 0xea, 0xcc, 0xa6, 0x80, - 0x72, 0x54, 0x3e, 0x18, 0xc7, 0xe1, 0x8b, 0xad, 0x5f, 0x79, - 0x13, 0x35, 0xb0, 0x96, 0xfc, 0xda, 0x28, 0x0e, 0x64, 0x42, - 0x9d, 0xbb, 0xd1, 0xf7, 0x05, 0x23, 0x49, 0x6f, 0x5e, 0x78, - 0x12, 0x34, 0xc6, 0xe0, 0x8a, 0xac, 0x73, 0x55, 0x3f, 0x19, - 0xeb, 0xcd, 0xa7, 0x81, 0x04, 0x22, 0x48, 0x6e, 0x9c, 0xba, - 0xd0, 0xf6, 0x29, 0x0f, 0x65, 0x43, 0xb1, 0x97, 0xfd, 0xdb, - 0x9f, 0xb9, 0xd3, 0xf5, 0x07, 0x21, 0x4b, 0x6d, 0xb2, 0x94, - 0xfe, 0xd8, 0x2a, 0x0c, 0x66, 0x40, 0xc5, 0xe3, 0x89, 0xaf, - 0x5d, 0x7b, 0x11, 0x37, 0xe8, 0xce, 0xa4, 0x82, 0x70, 0x56, - 0x3c, 0x1a, 0x2b, 0x0d, 0x67, 0x41, 0xb3, 0x95, 0xff, 0xd9, - 0x06, 0x20, 0x4a, 0x6c, 0x9e, 0xb8, 0xd2, 0xf4, 0x71, 0x57, - 0x3d, 0x1b, 0xe9, 0xcf, 0xa5, 0x83, 0x5c, 0x7a, 0x10, 0x36, - 0xc4, 0xe2, 0x88, 0xae, 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, - 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0, - 0x4a, 0x6d, 0x04, 0x23, 0xd6, 0xf1, 0x98, 0xbf, 0x6f, 0x48, - 0x21, 0x06, 0xf3, 0xd4, 0xbd, 0x9a, 0x94, 0xb3, 0xda, 0xfd, - 0x08, 0x2f, 0x46, 0x61, 0xb1, 0x96, 0xff, 0xd8, 0x2d, 0x0a, - 0x63, 0x44, 0xde, 0xf9, 0x90, 0xb7, 0x42, 0x65, 0x0c, 0x2b, - 0xfb, 0xdc, 0xb5, 0x92, 0x67, 0x40, 0x29, 0x0e, 0x35, 0x12, - 0x7b, 0x5c, 0xa9, 0x8e, 0xe7, 0xc0, 0x10, 0x37, 0x5e, 0x79, - 0x8c, 0xab, 0xc2, 0xe5, 0x7f, 0x58, 0x31, 0x16, 0xe3, 0xc4, - 0xad, 0x8a, 0x5a, 0x7d, 0x14, 0x33, 0xc6, 0xe1, 0x88, 0xaf, - 0xa1, 0x86, 0xef, 0xc8, 0x3d, 0x1a, 0x73, 0x54, 0x84, 0xa3, - 0xca, 0xed, 0x18, 0x3f, 0x56, 0x71, 0xeb, 0xcc, 0xa5, 0x82, - 0x77, 0x50, 0x39, 0x1e, 0xce, 0xe9, 0x80, 0xa7, 0x52, 0x75, - 0x1c, 0x3b, 0x6a, 0x4d, 0x24, 0x03, 0xf6, 0xd1, 0xb8, 0x9f, - 0x4f, 0x68, 0x01, 0x26, 0xd3, 0xf4, 0x9d, 0xba, 0x20, 0x07, - 0x6e, 0x49, 0xbc, 0x9b, 0xf2, 0xd5, 0x05, 0x22, 0x4b, 0x6c, - 0x99, 0xbe, 0xd7, 0xf0, 0xfe, 0xd9, 0xb0, 0x97, 0x62, 0x45, - 0x2c, 0x0b, 0xdb, 0xfc, 0x95, 0xb2, 0x47, 0x60, 0x09, 0x2e, - 0xb4, 0x93, 0xfa, 0xdd, 0x28, 0x0f, 0x66, 0x41, 0x91, 0xb6, - 0xdf, 0xf8, 0x0d, 0x2a, 0x43, 0x64, 0x5f, 0x78, 0x11, 0x36, - 0xc3, 0xe4, 0x8d, 0xaa, 0x7a, 0x5d, 0x34, 0x13, 0xe6, 0xc1, - 0xa8, 0x8f, 0x15, 0x32, 0x5b, 0x7c, 0x89, 0xae, 0xc7, 0xe0, - 0x30, 0x17, 0x7e, 0x59, 0xac, 0x8b, 0xe2, 0xc5, 0xcb, 0xec, - 0x85, 0xa2, 0x57, 0x70, 0x19, 0x3e, 0xee, 0xc9, 0xa0, 0x87, - 0x72, 0x55, 0x3c, 0x1b, 0x81, 0xa6, 0xcf, 0xe8, 0x1d, 0x3a, - 0x53, 0x74, 0xa4, 0x83, 0xea, 0xcd, 0x38, 0x1f, 0x76, 0x51, - 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, - 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85, 0xba, 0x92, 0xea, 0xc2, - 0x1a, 0x32, 0x4a, 0x62, 0xe7, 0xcf, 0xb7, 0x9f, 0x47, 0x6f, - 0x17, 0x3f, 0x69, 0x41, 0x39, 0x11, 0xc9, 0xe1, 0x99, 0xb1, - 0x34, 0x1c, 0x64, 0x4c, 0x94, 0xbc, 0xc4, 0xec, 0xd3, 0xfb, - 0x83, 0xab, 0x73, 0x5b, 0x23, 0x0b, 0x8e, 0xa6, 0xde, 0xf6, - 0x2e, 0x06, 0x7e, 0x56, 0xd2, 0xfa, 0x82, 0xaa, 0x72, 0x5a, - 0x22, 0x0a, 0x8f, 0xa7, 0xdf, 0xf7, 0x2f, 0x07, 0x7f, 0x57, - 0x68, 0x40, 0x38, 0x10, 0xc8, 0xe0, 0x98, 0xb0, 0x35, 0x1d, - 0x65, 0x4d, 0x95, 0xbd, 0xc5, 0xed, 0xbb, 0x93, 0xeb, 0xc3, - 0x1b, 0x33, 0x4b, 0x63, 0xe6, 0xce, 0xb6, 0x9e, 0x46, 0x6e, - 0x16, 0x3e, 0x01, 0x29, 0x51, 0x79, 0xa1, 0x89, 0xf1, 0xd9, - 0x5c, 0x74, 0x0c, 0x24, 0xfc, 0xd4, 0xac, 0x84, 0xb9, 0x91, - 0xe9, 0xc1, 0x19, 0x31, 0x49, 0x61, 0xe4, 0xcc, 0xb4, 0x9c, - 0x44, 0x6c, 0x14, 0x3c, 0x03, 0x2b, 0x53, 0x7b, 0xa3, 0x8b, - 0xf3, 0xdb, 0x5e, 0x76, 0x0e, 0x26, 0xfe, 0xd6, 0xae, 0x86, - 0xd0, 0xf8, 0x80, 0xa8, 0x70, 0x58, 0x20, 0x08, 0x8d, 0xa5, - 0xdd, 0xf5, 0x2d, 0x05, 0x7d, 0x55, 0x6a, 0x42, 0x3a, 0x12, - 0xca, 0xe2, 0x9a, 0xb2, 0x37, 0x1f, 0x67, 0x4f, 0x97, 0xbf, - 0xc7, 0xef, 0x6b, 0x43, 0x3b, 0x13, 0xcb, 0xe3, 0x9b, 0xb3, - 0x36, 0x1e, 0x66, 0x4e, 0x96, 0xbe, 0xc6, 0xee, 0xd1, 0xf9, - 0x81, 0xa9, 0x71, 0x59, 0x21, 0x09, 0x8c, 0xa4, 0xdc, 0xf4, - 0x2c, 0x04, 0x7c, 0x54, 0x02, 0x2a, 0x52, 0x7a, 0xa2, 0x8a, - 0xf2, 0xda, 0x5f, 0x77, 0x0f, 0x27, 0xff, 0xd7, 0xaf, 0x87, - 0xb8, 0x90, 0xe8, 0xc0, 0x18, 0x30, 0x48, 0x60, 0xe5, 0xcd, - 0xb5, 0x9d, 0x45, 0x6d, 0x15, 0x3d, 0x00, 0x29, 0x52, 0x7b, - 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, - 0xa3, 0x8a, 0xaa, 0x83, 0xf8, 0xd1, 0x0e, 0x27, 0x5c, 0x75, - 0xff, 0xd6, 0xad, 0x84, 0x5b, 0x72, 0x09, 0x20, 0x49, 0x60, - 0x1b, 0x32, 0xed, 0xc4, 0xbf, 0x96, 0x1c, 0x35, 0x4e, 0x67, - 0xb8, 0x91, 0xea, 0xc3, 0xe3, 0xca, 0xb1, 0x98, 0x47, 0x6e, - 0x15, 0x3c, 0xb6, 0x9f, 0xe4, 0xcd, 0x12, 0x3b, 0x40, 0x69, - 0x92, 0xbb, 0xc0, 0xe9, 0x36, 0x1f, 0x64, 0x4d, 0xc7, 0xee, - 0x95, 0xbc, 0x63, 0x4a, 0x31, 0x18, 0x38, 0x11, 0x6a, 0x43, - 0x9c, 0xb5, 0xce, 0xe7, 0x6d, 0x44, 0x3f, 0x16, 0xc9, 0xe0, - 0x9b, 0xb2, 0xdb, 0xf2, 0x89, 0xa0, 0x7f, 0x56, 0x2d, 0x04, - 0x8e, 0xa7, 0xdc, 0xf5, 0x2a, 0x03, 0x78, 0x51, 0x71, 0x58, - 0x23, 0x0a, 0xd5, 0xfc, 0x87, 0xae, 0x24, 0x0d, 0x76, 0x5f, - 0x80, 0xa9, 0xd2, 0xfb, 0x39, 0x10, 0x6b, 0x42, 0x9d, 0xb4, - 0xcf, 0xe6, 0x6c, 0x45, 0x3e, 0x17, 0xc8, 0xe1, 0x9a, 0xb3, - 0x93, 0xba, 0xc1, 0xe8, 0x37, 0x1e, 0x65, 0x4c, 0xc6, 0xef, - 0x94, 0xbd, 0x62, 0x4b, 0x30, 0x19, 0x70, 0x59, 0x22, 0x0b, - 0xd4, 0xfd, 0x86, 0xaf, 0x25, 0x0c, 0x77, 0x5e, 0x81, 0xa8, - 0xd3, 0xfa, 0xda, 0xf3, 0x88, 0xa1, 0x7e, 0x57, 0x2c, 0x05, - 0x8f, 0xa6, 0xdd, 0xf4, 0x2b, 0x02, 0x79, 0x50, 0xab, 0x82, - 0xf9, 0xd0, 0x0f, 0x26, 0x5d, 0x74, 0xfe, 0xd7, 0xac, 0x85, - 0x5a, 0x73, 0x08, 0x21, 0x01, 0x28, 0x53, 0x7a, 0xa5, 0x8c, - 0xf7, 0xde, 0x54, 0x7d, 0x06, 0x2f, 0xf0, 0xd9, 0xa2, 0x8b, - 0xe2, 0xcb, 0xb0, 0x99, 0x46, 0x6f, 0x14, 0x3d, 0xb7, 0x9e, - 0xe5, 0xcc, 0x13, 0x3a, 0x41, 0x68, 0x48, 0x61, 0x1a, 0x33, - 0xec, 0xc5, 0xbe, 0x97, 0x1d, 0x34, 0x4f, 0x66, 0xb9, 0x90, - 0xeb, 0xc2, 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, - 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b, 0x9a, 0xb0, - 0xce, 0xe4, 0x32, 0x18, 0x66, 0x4c, 0xd7, 0xfd, 0x83, 0xa9, - 0x7f, 0x55, 0x2b, 0x01, 0x29, 0x03, 0x7d, 0x57, 0x81, 0xab, - 0xd5, 0xff, 0x64, 0x4e, 0x30, 0x1a, 0xcc, 0xe6, 0x98, 0xb2, - 0xb3, 0x99, 0xe7, 0xcd, 0x1b, 0x31, 0x4f, 0x65, 0xfe, 0xd4, - 0xaa, 0x80, 0x56, 0x7c, 0x02, 0x28, 0x52, 0x78, 0x06, 0x2c, - 0xfa, 0xd0, 0xae, 0x84, 0x1f, 0x35, 0x4b, 0x61, 0xb7, 0x9d, - 0xe3, 0xc9, 0xc8, 0xe2, 0x9c, 0xb6, 0x60, 0x4a, 0x34, 0x1e, - 0x85, 0xaf, 0xd1, 0xfb, 0x2d, 0x07, 0x79, 0x53, 0x7b, 0x51, - 0x2f, 0x05, 0xd3, 0xf9, 0x87, 0xad, 0x36, 0x1c, 0x62, 0x48, - 0x9e, 0xb4, 0xca, 0xe0, 0xe1, 0xcb, 0xb5, 0x9f, 0x49, 0x63, - 0x1d, 0x37, 0xac, 0x86, 0xf8, 0xd2, 0x04, 0x2e, 0x50, 0x7a, - 0xa4, 0x8e, 0xf0, 0xda, 0x0c, 0x26, 0x58, 0x72, 0xe9, 0xc3, - 0xbd, 0x97, 0x41, 0x6b, 0x15, 0x3f, 0x3e, 0x14, 0x6a, 0x40, - 0x96, 0xbc, 0xc2, 0xe8, 0x73, 0x59, 0x27, 0x0d, 0xdb, 0xf1, - 0x8f, 0xa5, 0x8d, 0xa7, 0xd9, 0xf3, 0x25, 0x0f, 0x71, 0x5b, - 0xc0, 0xea, 0x94, 0xbe, 0x68, 0x42, 0x3c, 0x16, 0x17, 0x3d, - 0x43, 0x69, 0xbf, 0x95, 0xeb, 0xc1, 0x5a, 0x70, 0x0e, 0x24, - 0xf2, 0xd8, 0xa6, 0x8c, 0xf6, 0xdc, 0xa2, 0x88, 0x5e, 0x74, - 0x0a, 0x20, 0xbb, 0x91, 0xef, 0xc5, 0x13, 0x39, 0x47, 0x6d, - 0x6c, 0x46, 0x38, 0x12, 0xc4, 0xee, 0x90, 0xba, 0x21, 0x0b, - 0x75, 0x5f, 0x89, 0xa3, 0xdd, 0xf7, 0xdf, 0xf5, 0x8b, 0xa1, - 0x77, 0x5d, 0x23, 0x09, 0x92, 0xb8, 0xc6, 0xec, 0x3a, 0x10, - 0x6e, 0x44, 0x45, 0x6f, 0x11, 0x3b, 0xed, 0xc7, 0xb9, 0x93, - 0x08, 0x22, 0x5c, 0x76, 0xa0, 0x8a, 0xf4, 0xde, 0x00, 0x2b, - 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, - 0xe9, 0xc2, 0xbf, 0x94, 0x8a, 0xa1, 0xdc, 0xf7, 0x26, 0x0d, - 0x70, 0x5b, 0xcf, 0xe4, 0x99, 0xb2, 0x63, 0x48, 0x35, 0x1e, - 0x09, 0x22, 0x5f, 0x74, 0xa5, 0x8e, 0xf3, 0xd8, 0x4c, 0x67, - 0x1a, 0x31, 0xe0, 0xcb, 0xb6, 0x9d, 0x83, 0xa8, 0xd5, 0xfe, - 0x2f, 0x04, 0x79, 0x52, 0xc6, 0xed, 0x90, 0xbb, 0x6a, 0x41, - 0x3c, 0x17, 0x12, 0x39, 0x44, 0x6f, 0xbe, 0x95, 0xe8, 0xc3, - 0x57, 0x7c, 0x01, 0x2a, 0xfb, 0xd0, 0xad, 0x86, 0x98, 0xb3, - 0xce, 0xe5, 0x34, 0x1f, 0x62, 0x49, 0xdd, 0xf6, 0x8b, 0xa0, - 0x71, 0x5a, 0x27, 0x0c, 0x1b, 0x30, 0x4d, 0x66, 0xb7, 0x9c, - 0xe1, 0xca, 0x5e, 0x75, 0x08, 0x23, 0xf2, 0xd9, 0xa4, 0x8f, - 0x91, 0xba, 0xc7, 0xec, 0x3d, 0x16, 0x6b, 0x40, 0xd4, 0xff, - 0x82, 0xa9, 0x78, 0x53, 0x2e, 0x05, 0x24, 0x0f, 0x72, 0x59, - 0x88, 0xa3, 0xde, 0xf5, 0x61, 0x4a, 0x37, 0x1c, 0xcd, 0xe6, - 0x9b, 0xb0, 0xae, 0x85, 0xf8, 0xd3, 0x02, 0x29, 0x54, 0x7f, - 0xeb, 0xc0, 0xbd, 0x96, 0x47, 0x6c, 0x11, 0x3a, 0x2d, 0x06, - 0x7b, 0x50, 0x81, 0xaa, 0xd7, 0xfc, 0x68, 0x43, 0x3e, 0x15, - 0xc4, 0xef, 0x92, 0xb9, 0xa7, 0x8c, 0xf1, 0xda, 0x0b, 0x20, - 0x5d, 0x76, 0xe2, 0xc9, 0xb4, 0x9f, 0x4e, 0x65, 0x18, 0x33, - 0x36, 0x1d, 0x60, 0x4b, 0x9a, 0xb1, 0xcc, 0xe7, 0x73, 0x58, - 0x25, 0x0e, 0xdf, 0xf4, 0x89, 0xa2, 0xbc, 0x97, 0xea, 0xc1, - 0x10, 0x3b, 0x46, 0x6d, 0xf9, 0xd2, 0xaf, 0x84, 0x55, 0x7e, - 0x03, 0x28, 0x3f, 0x14, 0x69, 0x42, 0x93, 0xb8, 0xc5, 0xee, - 0x7a, 0x51, 0x2c, 0x07, 0xd6, 0xfd, 0x80, 0xab, 0xb5, 0x9e, - 0xe3, 0xc8, 0x19, 0x32, 0x4f, 0x64, 0xf0, 0xdb, 0xa6, 0x8d, - 0x5c, 0x77, 0x0a, 0x21, 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, - 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9, - 0xfa, 0xd6, 0xa2, 0x8e, 0x4a, 0x66, 0x12, 0x3e, 0x87, 0xab, - 0xdf, 0xf3, 0x37, 0x1b, 0x6f, 0x43, 0xe9, 0xc5, 0xb1, 0x9d, - 0x59, 0x75, 0x01, 0x2d, 0x94, 0xb8, 0xcc, 0xe0, 0x24, 0x08, - 0x7c, 0x50, 0x13, 0x3f, 0x4b, 0x67, 0xa3, 0x8f, 0xfb, 0xd7, - 0x6e, 0x42, 0x36, 0x1a, 0xde, 0xf2, 0x86, 0xaa, 0xcf, 0xe3, - 0x97, 0xbb, 0x7f, 0x53, 0x27, 0x0b, 0xb2, 0x9e, 0xea, 0xc6, - 0x02, 0x2e, 0x5a, 0x76, 0x35, 0x19, 0x6d, 0x41, 0x85, 0xa9, - 0xdd, 0xf1, 0x48, 0x64, 0x10, 0x3c, 0xf8, 0xd4, 0xa0, 0x8c, - 0x26, 0x0a, 0x7e, 0x52, 0x96, 0xba, 0xce, 0xe2, 0x5b, 0x77, - 0x03, 0x2f, 0xeb, 0xc7, 0xb3, 0x9f, 0xdc, 0xf0, 0x84, 0xa8, - 0x6c, 0x40, 0x34, 0x18, 0xa1, 0x8d, 0xf9, 0xd5, 0x11, 0x3d, - 0x49, 0x65, 0x83, 0xaf, 0xdb, 0xf7, 0x33, 0x1f, 0x6b, 0x47, - 0xfe, 0xd2, 0xa6, 0x8a, 0x4e, 0x62, 0x16, 0x3a, 0x79, 0x55, - 0x21, 0x0d, 0xc9, 0xe5, 0x91, 0xbd, 0x04, 0x28, 0x5c, 0x70, - 0xb4, 0x98, 0xec, 0xc0, 0x6a, 0x46, 0x32, 0x1e, 0xda, 0xf6, - 0x82, 0xae, 0x17, 0x3b, 0x4f, 0x63, 0xa7, 0x8b, 0xff, 0xd3, - 0x90, 0xbc, 0xc8, 0xe4, 0x20, 0x0c, 0x78, 0x54, 0xed, 0xc1, - 0xb5, 0x99, 0x5d, 0x71, 0x05, 0x29, 0x4c, 0x60, 0x14, 0x38, - 0xfc, 0xd0, 0xa4, 0x88, 0x31, 0x1d, 0x69, 0x45, 0x81, 0xad, - 0xd9, 0xf5, 0xb6, 0x9a, 0xee, 0xc2, 0x06, 0x2a, 0x5e, 0x72, - 0xcb, 0xe7, 0x93, 0xbf, 0x7b, 0x57, 0x23, 0x0f, 0xa5, 0x89, - 0xfd, 0xd1, 0x15, 0x39, 0x4d, 0x61, 0xd8, 0xf4, 0x80, 0xac, - 0x68, 0x44, 0x30, 0x1c, 0x5f, 0x73, 0x07, 0x2b, 0xef, 0xc3, - 0xb7, 0x9b, 0x22, 0x0e, 0x7a, 0x56, 0x92, 0xbe, 0xca, 0xe6, - 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, - 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6, 0xea, 0xc7, 0xb0, 0x9d, - 0x5e, 0x73, 0x04, 0x29, 0x9f, 0xb2, 0xc5, 0xe8, 0x2b, 0x06, - 0x71, 0x5c, 0xc9, 0xe4, 0x93, 0xbe, 0x7d, 0x50, 0x27, 0x0a, - 0xbc, 0x91, 0xe6, 0xcb, 0x08, 0x25, 0x52, 0x7f, 0x23, 0x0e, - 0x79, 0x54, 0x97, 0xba, 0xcd, 0xe0, 0x56, 0x7b, 0x0c, 0x21, - 0xe2, 0xcf, 0xb8, 0x95, 0x8f, 0xa2, 0xd5, 0xf8, 0x3b, 0x16, - 0x61, 0x4c, 0xfa, 0xd7, 0xa0, 0x8d, 0x4e, 0x63, 0x14, 0x39, - 0x65, 0x48, 0x3f, 0x12, 0xd1, 0xfc, 0x8b, 0xa6, 0x10, 0x3d, - 0x4a, 0x67, 0xa4, 0x89, 0xfe, 0xd3, 0x46, 0x6b, 0x1c, 0x31, - 0xf2, 0xdf, 0xa8, 0x85, 0x33, 0x1e, 0x69, 0x44, 0x87, 0xaa, - 0xdd, 0xf0, 0xac, 0x81, 0xf6, 0xdb, 0x18, 0x35, 0x42, 0x6f, - 0xd9, 0xf4, 0x83, 0xae, 0x6d, 0x40, 0x37, 0x1a, 0x03, 0x2e, - 0x59, 0x74, 0xb7, 0x9a, 0xed, 0xc0, 0x76, 0x5b, 0x2c, 0x01, - 0xc2, 0xef, 0x98, 0xb5, 0xe9, 0xc4, 0xb3, 0x9e, 0x5d, 0x70, - 0x07, 0x2a, 0x9c, 0xb1, 0xc6, 0xeb, 0x28, 0x05, 0x72, 0x5f, - 0xca, 0xe7, 0x90, 0xbd, 0x7e, 0x53, 0x24, 0x09, 0xbf, 0x92, - 0xe5, 0xc8, 0x0b, 0x26, 0x51, 0x7c, 0x20, 0x0d, 0x7a, 0x57, - 0x94, 0xb9, 0xce, 0xe3, 0x55, 0x78, 0x0f, 0x22, 0xe1, 0xcc, - 0xbb, 0x96, 0x8c, 0xa1, 0xd6, 0xfb, 0x38, 0x15, 0x62, 0x4f, - 0xf9, 0xd4, 0xa3, 0x8e, 0x4d, 0x60, 0x17, 0x3a, 0x66, 0x4b, - 0x3c, 0x11, 0xd2, 0xff, 0x88, 0xa5, 0x13, 0x3e, 0x49, 0x64, - 0xa7, 0x8a, 0xfd, 0xd0, 0x45, 0x68, 0x1f, 0x32, 0xf1, 0xdc, - 0xab, 0x86, 0x30, 0x1d, 0x6a, 0x47, 0x84, 0xa9, 0xde, 0xf3, - 0xaf, 0x82, 0xf5, 0xd8, 0x1b, 0x36, 0x41, 0x6c, 0xda, 0xf7, - 0x80, 0xad, 0x6e, 0x43, 0x34, 0x19, 0x00, 0x2e, 0x5c, 0x72, - 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, - 0x89, 0xa7, 0xda, 0xf4, 0x86, 0xa8, 0x62, 0x4c, 0x3e, 0x10, - 0xb7, 0x99, 0xeb, 0xc5, 0x0f, 0x21, 0x53, 0x7d, 0xa9, 0x87, - 0xf5, 0xdb, 0x11, 0x3f, 0x4d, 0x63, 0xc4, 0xea, 0x98, 0xb6, - 0x7c, 0x52, 0x20, 0x0e, 0x73, 0x5d, 0x2f, 0x01, 0xcb, 0xe5, - 0x97, 0xb9, 0x1e, 0x30, 0x42, 0x6c, 0xa6, 0x88, 0xfa, 0xd4, - 0x4f, 0x61, 0x13, 0x3d, 0xf7, 0xd9, 0xab, 0x85, 0x22, 0x0c, - 0x7e, 0x50, 0x9a, 0xb4, 0xc6, 0xe8, 0x95, 0xbb, 0xc9, 0xe7, - 0x2d, 0x03, 0x71, 0x5f, 0xf8, 0xd6, 0xa4, 0x8a, 0x40, 0x6e, - 0x1c, 0x32, 0xe6, 0xc8, 0xba, 0x94, 0x5e, 0x70, 0x02, 0x2c, - 0x8b, 0xa5, 0xd7, 0xf9, 0x33, 0x1d, 0x6f, 0x41, 0x3c, 0x12, - 0x60, 0x4e, 0x84, 0xaa, 0xd8, 0xf6, 0x51, 0x7f, 0x0d, 0x23, - 0xe9, 0xc7, 0xb5, 0x9b, 0x9e, 0xb0, 0xc2, 0xec, 0x26, 0x08, - 0x7a, 0x54, 0xf3, 0xdd, 0xaf, 0x81, 0x4b, 0x65, 0x17, 0x39, - 0x44, 0x6a, 0x18, 0x36, 0xfc, 0xd2, 0xa0, 0x8e, 0x29, 0x07, - 0x75, 0x5b, 0x91, 0xbf, 0xcd, 0xe3, 0x37, 0x19, 0x6b, 0x45, - 0x8f, 0xa1, 0xd3, 0xfd, 0x5a, 0x74, 0x06, 0x28, 0xe2, 0xcc, - 0xbe, 0x90, 0xed, 0xc3, 0xb1, 0x9f, 0x55, 0x7b, 0x09, 0x27, - 0x80, 0xae, 0xdc, 0xf2, 0x38, 0x16, 0x64, 0x4a, 0xd1, 0xff, - 0x8d, 0xa3, 0x69, 0x47, 0x35, 0x1b, 0xbc, 0x92, 0xe0, 0xce, - 0x04, 0x2a, 0x58, 0x76, 0x0b, 0x25, 0x57, 0x79, 0xb3, 0x9d, - 0xef, 0xc1, 0x66, 0x48, 0x3a, 0x14, 0xde, 0xf0, 0x82, 0xac, - 0x78, 0x56, 0x24, 0x0a, 0xc0, 0xee, 0x9c, 0xb2, 0x15, 0x3b, - 0x49, 0x67, 0xad, 0x83, 0xf1, 0xdf, 0xa2, 0x8c, 0xfe, 0xd0, - 0x1a, 0x34, 0x46, 0x68, 0xcf, 0xe1, 0x93, 0xbd, 0x77, 0x59, - 0x2b, 0x05, 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, - 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8, 0xca, 0xe5, - 0x94, 0xbb, 0x76, 0x59, 0x28, 0x07, 0xaf, 0x80, 0xf1, 0xde, - 0x13, 0x3c, 0x4d, 0x62, 0x89, 0xa6, 0xd7, 0xf8, 0x35, 0x1a, - 0x6b, 0x44, 0xec, 0xc3, 0xb2, 0x9d, 0x50, 0x7f, 0x0e, 0x21, - 0x43, 0x6c, 0x1d, 0x32, 0xff, 0xd0, 0xa1, 0x8e, 0x26, 0x09, - 0x78, 0x57, 0x9a, 0xb5, 0xc4, 0xeb, 0x0f, 0x20, 0x51, 0x7e, - 0xb3, 0x9c, 0xed, 0xc2, 0x6a, 0x45, 0x34, 0x1b, 0xd6, 0xf9, - 0x88, 0xa7, 0xc5, 0xea, 0x9b, 0xb4, 0x79, 0x56, 0x27, 0x08, - 0xa0, 0x8f, 0xfe, 0xd1, 0x1c, 0x33, 0x42, 0x6d, 0x86, 0xa9, - 0xd8, 0xf7, 0x3a, 0x15, 0x64, 0x4b, 0xe3, 0xcc, 0xbd, 0x92, - 0x5f, 0x70, 0x01, 0x2e, 0x4c, 0x63, 0x12, 0x3d, 0xf0, 0xdf, - 0xae, 0x81, 0x29, 0x06, 0x77, 0x58, 0x95, 0xba, 0xcb, 0xe4, - 0x1e, 0x31, 0x40, 0x6f, 0xa2, 0x8d, 0xfc, 0xd3, 0x7b, 0x54, - 0x25, 0x0a, 0xc7, 0xe8, 0x99, 0xb6, 0xd4, 0xfb, 0x8a, 0xa5, - 0x68, 0x47, 0x36, 0x19, 0xb1, 0x9e, 0xef, 0xc0, 0x0d, 0x22, - 0x53, 0x7c, 0x97, 0xb8, 0xc9, 0xe6, 0x2b, 0x04, 0x75, 0x5a, - 0xf2, 0xdd, 0xac, 0x83, 0x4e, 0x61, 0x10, 0x3f, 0x5d, 0x72, - 0x03, 0x2c, 0xe1, 0xce, 0xbf, 0x90, 0x38, 0x17, 0x66, 0x49, - 0x84, 0xab, 0xda, 0xf5, 0x11, 0x3e, 0x4f, 0x60, 0xad, 0x82, - 0xf3, 0xdc, 0x74, 0x5b, 0x2a, 0x05, 0xc8, 0xe7, 0x96, 0xb9, - 0xdb, 0xf4, 0x85, 0xaa, 0x67, 0x48, 0x39, 0x16, 0xbe, 0x91, - 0xe0, 0xcf, 0x02, 0x2d, 0x5c, 0x73, 0x98, 0xb7, 0xc6, 0xe9, - 0x24, 0x0b, 0x7a, 0x55, 0xfd, 0xd2, 0xa3, 0x8c, 0x41, 0x6e, - 0x1f, 0x30, 0x52, 0x7d, 0x0c, 0x23, 0xee, 0xc1, 0xb0, 0x9f, - 0x37, 0x18, 0x69, 0x46, 0x8b, 0xa4, 0xd5, 0xfa, 0x00, 0x30, - 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, - 0x5d, 0x6d, 0x3d, 0x0d, 0x27, 0x17, 0x47, 0x77, 0xe7, 0xd7, - 0x87, 0xb7, 0xba, 0x8a, 0xda, 0xea, 0x7a, 0x4a, 0x1a, 0x2a, - 0x4e, 0x7e, 0x2e, 0x1e, 0x8e, 0xbe, 0xee, 0xde, 0xd3, 0xe3, - 0xb3, 0x83, 0x13, 0x23, 0x73, 0x43, 0x69, 0x59, 0x09, 0x39, - 0xa9, 0x99, 0xc9, 0xf9, 0xf4, 0xc4, 0x94, 0xa4, 0x34, 0x04, - 0x54, 0x64, 0x9c, 0xac, 0xfc, 0xcc, 0x5c, 0x6c, 0x3c, 0x0c, - 0x01, 0x31, 0x61, 0x51, 0xc1, 0xf1, 0xa1, 0x91, 0xbb, 0x8b, - 0xdb, 0xeb, 0x7b, 0x4b, 0x1b, 0x2b, 0x26, 0x16, 0x46, 0x76, - 0xe6, 0xd6, 0x86, 0xb6, 0xd2, 0xe2, 0xb2, 0x82, 0x12, 0x22, - 0x72, 0x42, 0x4f, 0x7f, 0x2f, 0x1f, 0x8f, 0xbf, 0xef, 0xdf, - 0xf5, 0xc5, 0x95, 0xa5, 0x35, 0x05, 0x55, 0x65, 0x68, 0x58, - 0x08, 0x38, 0xa8, 0x98, 0xc8, 0xf8, 0x25, 0x15, 0x45, 0x75, - 0xe5, 0xd5, 0x85, 0xb5, 0xb8, 0x88, 0xd8, 0xe8, 0x78, 0x48, - 0x18, 0x28, 0x02, 0x32, 0x62, 0x52, 0xc2, 0xf2, 0xa2, 0x92, - 0x9f, 0xaf, 0xff, 0xcf, 0x5f, 0x6f, 0x3f, 0x0f, 0x6b, 0x5b, - 0x0b, 0x3b, 0xab, 0x9b, 0xcb, 0xfb, 0xf6, 0xc6, 0x96, 0xa6, - 0x36, 0x06, 0x56, 0x66, 0x4c, 0x7c, 0x2c, 0x1c, 0x8c, 0xbc, - 0xec, 0xdc, 0xd1, 0xe1, 0xb1, 0x81, 0x11, 0x21, 0x71, 0x41, - 0xb9, 0x89, 0xd9, 0xe9, 0x79, 0x49, 0x19, 0x29, 0x24, 0x14, - 0x44, 0x74, 0xe4, 0xd4, 0x84, 0xb4, 0x9e, 0xae, 0xfe, 0xce, - 0x5e, 0x6e, 0x3e, 0x0e, 0x03, 0x33, 0x63, 0x53, 0xc3, 0xf3, - 0xa3, 0x93, 0xf7, 0xc7, 0x97, 0xa7, 0x37, 0x07, 0x57, 0x67, - 0x6a, 0x5a, 0x0a, 0x3a, 0xaa, 0x9a, 0xca, 0xfa, 0xd0, 0xe0, - 0xb0, 0x80, 0x10, 0x20, 0x70, 0x40, 0x4d, 0x7d, 0x2d, 0x1d, - 0x8d, 0xbd, 0xed, 0xdd, 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, - 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02, - 0x37, 0x06, 0x55, 0x64, 0xf3, 0xc2, 0x91, 0xa0, 0xa2, 0x93, - 0xc0, 0xf1, 0x66, 0x57, 0x04, 0x35, 0x6e, 0x5f, 0x0c, 0x3d, - 0xaa, 0x9b, 0xc8, 0xf9, 0xfb, 0xca, 0x99, 0xa8, 0x3f, 0x0e, - 0x5d, 0x6c, 0x59, 0x68, 0x3b, 0x0a, 0x9d, 0xac, 0xff, 0xce, - 0xcc, 0xfd, 0xae, 0x9f, 0x08, 0x39, 0x6a, 0x5b, 0xdc, 0xed, - 0xbe, 0x8f, 0x18, 0x29, 0x7a, 0x4b, 0x49, 0x78, 0x2b, 0x1a, - 0x8d, 0xbc, 0xef, 0xde, 0xeb, 0xda, 0x89, 0xb8, 0x2f, 0x1e, - 0x4d, 0x7c, 0x7e, 0x4f, 0x1c, 0x2d, 0xba, 0x8b, 0xd8, 0xe9, - 0xb2, 0x83, 0xd0, 0xe1, 0x76, 0x47, 0x14, 0x25, 0x27, 0x16, - 0x45, 0x74, 0xe3, 0xd2, 0x81, 0xb0, 0x85, 0xb4, 0xe7, 0xd6, - 0x41, 0x70, 0x23, 0x12, 0x10, 0x21, 0x72, 0x43, 0xd4, 0xe5, - 0xb6, 0x87, 0xa5, 0x94, 0xc7, 0xf6, 0x61, 0x50, 0x03, 0x32, - 0x30, 0x01, 0x52, 0x63, 0xf4, 0xc5, 0x96, 0xa7, 0x92, 0xa3, - 0xf0, 0xc1, 0x56, 0x67, 0x34, 0x05, 0x07, 0x36, 0x65, 0x54, - 0xc3, 0xf2, 0xa1, 0x90, 0xcb, 0xfa, 0xa9, 0x98, 0x0f, 0x3e, - 0x6d, 0x5c, 0x5e, 0x6f, 0x3c, 0x0d, 0x9a, 0xab, 0xf8, 0xc9, - 0xfc, 0xcd, 0x9e, 0xaf, 0x38, 0x09, 0x5a, 0x6b, 0x69, 0x58, - 0x0b, 0x3a, 0xad, 0x9c, 0xcf, 0xfe, 0x79, 0x48, 0x1b, 0x2a, - 0xbd, 0x8c, 0xdf, 0xee, 0xec, 0xdd, 0x8e, 0xbf, 0x28, 0x19, - 0x4a, 0x7b, 0x4e, 0x7f, 0x2c, 0x1d, 0x8a, 0xbb, 0xe8, 0xd9, - 0xdb, 0xea, 0xb9, 0x88, 0x1f, 0x2e, 0x7d, 0x4c, 0x17, 0x26, - 0x75, 0x44, 0xd3, 0xe2, 0xb1, 0x80, 0x82, 0xb3, 0xe0, 0xd1, - 0x46, 0x77, 0x24, 0x15, 0x20, 0x11, 0x42, 0x73, 0xe4, 0xd5, - 0x86, 0xb7, 0xb5, 0x84, 0xd7, 0xe6, 0x71, 0x40, 0x13, 0x22, - 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, - 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13, 0x07, 0x35, 0x63, 0x51, - 0xcf, 0xfd, 0xab, 0x99, 0x8a, 0xb8, 0xee, 0xdc, 0x42, 0x70, - 0x26, 0x14, 0x0e, 0x3c, 0x6a, 0x58, 0xc6, 0xf4, 0xa2, 0x90, - 0x83, 0xb1, 0xe7, 0xd5, 0x4b, 0x79, 0x2f, 0x1d, 0x09, 0x3b, - 0x6d, 0x5f, 0xc1, 0xf3, 0xa5, 0x97, 0x84, 0xb6, 0xe0, 0xd2, - 0x4c, 0x7e, 0x28, 0x1a, 0x1c, 0x2e, 0x78, 0x4a, 0xd4, 0xe6, - 0xb0, 0x82, 0x91, 0xa3, 0xf5, 0xc7, 0x59, 0x6b, 0x3d, 0x0f, - 0x1b, 0x29, 0x7f, 0x4d, 0xd3, 0xe1, 0xb7, 0x85, 0x96, 0xa4, - 0xf2, 0xc0, 0x5e, 0x6c, 0x3a, 0x08, 0x12, 0x20, 0x76, 0x44, - 0xda, 0xe8, 0xbe, 0x8c, 0x9f, 0xad, 0xfb, 0xc9, 0x57, 0x65, - 0x33, 0x01, 0x15, 0x27, 0x71, 0x43, 0xdd, 0xef, 0xb9, 0x8b, - 0x98, 0xaa, 0xfc, 0xce, 0x50, 0x62, 0x34, 0x06, 0x38, 0x0a, - 0x5c, 0x6e, 0xf0, 0xc2, 0x94, 0xa6, 0xb5, 0x87, 0xd1, 0xe3, - 0x7d, 0x4f, 0x19, 0x2b, 0x3f, 0x0d, 0x5b, 0x69, 0xf7, 0xc5, - 0x93, 0xa1, 0xb2, 0x80, 0xd6, 0xe4, 0x7a, 0x48, 0x1e, 0x2c, - 0x36, 0x04, 0x52, 0x60, 0xfe, 0xcc, 0x9a, 0xa8, 0xbb, 0x89, - 0xdf, 0xed, 0x73, 0x41, 0x17, 0x25, 0x31, 0x03, 0x55, 0x67, - 0xf9, 0xcb, 0x9d, 0xaf, 0xbc, 0x8e, 0xd8, 0xea, 0x74, 0x46, - 0x10, 0x22, 0x24, 0x16, 0x40, 0x72, 0xec, 0xde, 0x88, 0xba, - 0xa9, 0x9b, 0xcd, 0xff, 0x61, 0x53, 0x05, 0x37, 0x23, 0x11, - 0x47, 0x75, 0xeb, 0xd9, 0x8f, 0xbd, 0xae, 0x9c, 0xca, 0xf8, - 0x66, 0x54, 0x02, 0x30, 0x2a, 0x18, 0x4e, 0x7c, 0xe2, 0xd0, - 0x86, 0xb4, 0xa7, 0x95, 0xc3, 0xf1, 0x6f, 0x5d, 0x0b, 0x39, - 0x2d, 0x1f, 0x49, 0x7b, 0xe5, 0xd7, 0x81, 0xb3, 0xa0, 0x92, - 0xc4, 0xf6, 0x68, 0x5a, 0x0c, 0x3e, 0x00, 0x33, 0x66, 0x55, - 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, - 0x2f, 0x1c, 0x17, 0x24, 0x71, 0x42, 0xdb, 0xe8, 0xbd, 0x8e, - 0x92, 0xa1, 0xf4, 0xc7, 0x5e, 0x6d, 0x38, 0x0b, 0x2e, 0x1d, - 0x48, 0x7b, 0xe2, 0xd1, 0x84, 0xb7, 0xab, 0x98, 0xcd, 0xfe, - 0x67, 0x54, 0x01, 0x32, 0x39, 0x0a, 0x5f, 0x6c, 0xf5, 0xc6, - 0x93, 0xa0, 0xbc, 0x8f, 0xda, 0xe9, 0x70, 0x43, 0x16, 0x25, - 0x5c, 0x6f, 0x3a, 0x09, 0x90, 0xa3, 0xf6, 0xc5, 0xd9, 0xea, - 0xbf, 0x8c, 0x15, 0x26, 0x73, 0x40, 0x4b, 0x78, 0x2d, 0x1e, - 0x87, 0xb4, 0xe1, 0xd2, 0xce, 0xfd, 0xa8, 0x9b, 0x02, 0x31, - 0x64, 0x57, 0x72, 0x41, 0x14, 0x27, 0xbe, 0x8d, 0xd8, 0xeb, - 0xf7, 0xc4, 0x91, 0xa2, 0x3b, 0x08, 0x5d, 0x6e, 0x65, 0x56, - 0x03, 0x30, 0xa9, 0x9a, 0xcf, 0xfc, 0xe0, 0xd3, 0x86, 0xb5, - 0x2c, 0x1f, 0x4a, 0x79, 0xb8, 0x8b, 0xde, 0xed, 0x74, 0x47, - 0x12, 0x21, 0x3d, 0x0e, 0x5b, 0x68, 0xf1, 0xc2, 0x97, 0xa4, - 0xaf, 0x9c, 0xc9, 0xfa, 0x63, 0x50, 0x05, 0x36, 0x2a, 0x19, - 0x4c, 0x7f, 0xe6, 0xd5, 0x80, 0xb3, 0x96, 0xa5, 0xf0, 0xc3, - 0x5a, 0x69, 0x3c, 0x0f, 0x13, 0x20, 0x75, 0x46, 0xdf, 0xec, - 0xb9, 0x8a, 0x81, 0xb2, 0xe7, 0xd4, 0x4d, 0x7e, 0x2b, 0x18, - 0x04, 0x37, 0x62, 0x51, 0xc8, 0xfb, 0xae, 0x9d, 0xe4, 0xd7, - 0x82, 0xb1, 0x28, 0x1b, 0x4e, 0x7d, 0x61, 0x52, 0x07, 0x34, - 0xad, 0x9e, 0xcb, 0xf8, 0xf3, 0xc0, 0x95, 0xa6, 0x3f, 0x0c, - 0x59, 0x6a, 0x76, 0x45, 0x10, 0x23, 0xba, 0x89, 0xdc, 0xef, - 0xca, 0xf9, 0xac, 0x9f, 0x06, 0x35, 0x60, 0x53, 0x4f, 0x7c, - 0x29, 0x1a, 0x83, 0xb0, 0xe5, 0xd6, 0xdd, 0xee, 0xbb, 0x88, - 0x11, 0x22, 0x77, 0x44, 0x58, 0x6b, 0x3e, 0x0d, 0x94, 0xa7, - 0xf2, 0xc1, 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, - 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31, 0x67, 0x53, - 0x0f, 0x3b, 0xb7, 0x83, 0xdf, 0xeb, 0xda, 0xee, 0xb2, 0x86, - 0x0a, 0x3e, 0x62, 0x56, 0xce, 0xfa, 0xa6, 0x92, 0x1e, 0x2a, - 0x76, 0x42, 0x73, 0x47, 0x1b, 0x2f, 0xa3, 0x97, 0xcb, 0xff, - 0xa9, 0x9d, 0xc1, 0xf5, 0x79, 0x4d, 0x11, 0x25, 0x14, 0x20, - 0x7c, 0x48, 0xc4, 0xf0, 0xac, 0x98, 0x81, 0xb5, 0xe9, 0xdd, - 0x51, 0x65, 0x39, 0x0d, 0x3c, 0x08, 0x54, 0x60, 0xec, 0xd8, - 0x84, 0xb0, 0xe6, 0xd2, 0x8e, 0xba, 0x36, 0x02, 0x5e, 0x6a, - 0x5b, 0x6f, 0x33, 0x07, 0x8b, 0xbf, 0xe3, 0xd7, 0x4f, 0x7b, - 0x27, 0x13, 0x9f, 0xab, 0xf7, 0xc3, 0xf2, 0xc6, 0x9a, 0xae, - 0x22, 0x16, 0x4a, 0x7e, 0x28, 0x1c, 0x40, 0x74, 0xf8, 0xcc, - 0x90, 0xa4, 0x95, 0xa1, 0xfd, 0xc9, 0x45, 0x71, 0x2d, 0x19, - 0x1f, 0x2b, 0x77, 0x43, 0xcf, 0xfb, 0xa7, 0x93, 0xa2, 0x96, - 0xca, 0xfe, 0x72, 0x46, 0x1a, 0x2e, 0x78, 0x4c, 0x10, 0x24, - 0xa8, 0x9c, 0xc0, 0xf4, 0xc5, 0xf1, 0xad, 0x99, 0x15, 0x21, - 0x7d, 0x49, 0xd1, 0xe5, 0xb9, 0x8d, 0x01, 0x35, 0x69, 0x5d, - 0x6c, 0x58, 0x04, 0x30, 0xbc, 0x88, 0xd4, 0xe0, 0xb6, 0x82, - 0xde, 0xea, 0x66, 0x52, 0x0e, 0x3a, 0x0b, 0x3f, 0x63, 0x57, - 0xdb, 0xef, 0xb3, 0x87, 0x9e, 0xaa, 0xf6, 0xc2, 0x4e, 0x7a, - 0x26, 0x12, 0x23, 0x17, 0x4b, 0x7f, 0xf3, 0xc7, 0x9b, 0xaf, - 0xf9, 0xcd, 0x91, 0xa5, 0x29, 0x1d, 0x41, 0x75, 0x44, 0x70, - 0x2c, 0x18, 0x94, 0xa0, 0xfc, 0xc8, 0x50, 0x64, 0x38, 0x0c, - 0x80, 0xb4, 0xe8, 0xdc, 0xed, 0xd9, 0x85, 0xb1, 0x3d, 0x09, - 0x55, 0x61, 0x37, 0x03, 0x5f, 0x6b, 0xe7, 0xd3, 0x8f, 0xbb, - 0x8a, 0xbe, 0xe2, 0xd6, 0x5a, 0x6e, 0x32, 0x06, 0x00, 0x35, - 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, - 0x61, 0x54, 0x0b, 0x3e, 0x77, 0x42, 0x1d, 0x28, 0xa3, 0x96, - 0xc9, 0xfc, 0xc2, 0xf7, 0xa8, 0x9d, 0x16, 0x23, 0x7c, 0x49, - 0xee, 0xdb, 0x84, 0xb1, 0x3a, 0x0f, 0x50, 0x65, 0x5b, 0x6e, - 0x31, 0x04, 0x8f, 0xba, 0xe5, 0xd0, 0x99, 0xac, 0xf3, 0xc6, - 0x4d, 0x78, 0x27, 0x12, 0x2c, 0x19, 0x46, 0x73, 0xf8, 0xcd, - 0x92, 0xa7, 0xc1, 0xf4, 0xab, 0x9e, 0x15, 0x20, 0x7f, 0x4a, - 0x74, 0x41, 0x1e, 0x2b, 0xa0, 0x95, 0xca, 0xff, 0xb6, 0x83, - 0xdc, 0xe9, 0x62, 0x57, 0x08, 0x3d, 0x03, 0x36, 0x69, 0x5c, - 0xd7, 0xe2, 0xbd, 0x88, 0x2f, 0x1a, 0x45, 0x70, 0xfb, 0xce, - 0x91, 0xa4, 0x9a, 0xaf, 0xf0, 0xc5, 0x4e, 0x7b, 0x24, 0x11, - 0x58, 0x6d, 0x32, 0x07, 0x8c, 0xb9, 0xe6, 0xd3, 0xed, 0xd8, - 0x87, 0xb2, 0x39, 0x0c, 0x53, 0x66, 0x9f, 0xaa, 0xf5, 0xc0, - 0x4b, 0x7e, 0x21, 0x14, 0x2a, 0x1f, 0x40, 0x75, 0xfe, 0xcb, - 0x94, 0xa1, 0xe8, 0xdd, 0x82, 0xb7, 0x3c, 0x09, 0x56, 0x63, - 0x5d, 0x68, 0x37, 0x02, 0x89, 0xbc, 0xe3, 0xd6, 0x71, 0x44, - 0x1b, 0x2e, 0xa5, 0x90, 0xcf, 0xfa, 0xc4, 0xf1, 0xae, 0x9b, - 0x10, 0x25, 0x7a, 0x4f, 0x06, 0x33, 0x6c, 0x59, 0xd2, 0xe7, - 0xb8, 0x8d, 0xb3, 0x86, 0xd9, 0xec, 0x67, 0x52, 0x0d, 0x38, - 0x5e, 0x6b, 0x34, 0x01, 0x8a, 0xbf, 0xe0, 0xd5, 0xeb, 0xde, - 0x81, 0xb4, 0x3f, 0x0a, 0x55, 0x60, 0x29, 0x1c, 0x43, 0x76, - 0xfd, 0xc8, 0x97, 0xa2, 0x9c, 0xa9, 0xf6, 0xc3, 0x48, 0x7d, - 0x22, 0x17, 0xb0, 0x85, 0xda, 0xef, 0x64, 0x51, 0x0e, 0x3b, - 0x05, 0x30, 0x6f, 0x5a, 0xd1, 0xe4, 0xbb, 0x8e, 0xc7, 0xf2, - 0xad, 0x98, 0x13, 0x26, 0x79, 0x4c, 0x72, 0x47, 0x18, 0x2d, - 0xa6, 0x93, 0xcc, 0xf9, 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, - 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f, - 0x47, 0x71, 0x2b, 0x1d, 0x9f, 0xa9, 0xf3, 0xc5, 0xea, 0xdc, - 0x86, 0xb0, 0x32, 0x04, 0x5e, 0x68, 0x8e, 0xb8, 0xe2, 0xd4, - 0x56, 0x60, 0x3a, 0x0c, 0x23, 0x15, 0x4f, 0x79, 0xfb, 0xcd, - 0x97, 0xa1, 0xc9, 0xff, 0xa5, 0x93, 0x11, 0x27, 0x7d, 0x4b, - 0x64, 0x52, 0x08, 0x3e, 0xbc, 0x8a, 0xd0, 0xe6, 0x01, 0x37, - 0x6d, 0x5b, 0xd9, 0xef, 0xb5, 0x83, 0xac, 0x9a, 0xc0, 0xf6, - 0x74, 0x42, 0x18, 0x2e, 0x46, 0x70, 0x2a, 0x1c, 0x9e, 0xa8, - 0xf2, 0xc4, 0xeb, 0xdd, 0x87, 0xb1, 0x33, 0x05, 0x5f, 0x69, - 0x8f, 0xb9, 0xe3, 0xd5, 0x57, 0x61, 0x3b, 0x0d, 0x22, 0x14, - 0x4e, 0x78, 0xfa, 0xcc, 0x96, 0xa0, 0xc8, 0xfe, 0xa4, 0x92, - 0x10, 0x26, 0x7c, 0x4a, 0x65, 0x53, 0x09, 0x3f, 0xbd, 0x8b, - 0xd1, 0xe7, 0x02, 0x34, 0x6e, 0x58, 0xda, 0xec, 0xb6, 0x80, - 0xaf, 0x99, 0xc3, 0xf5, 0x77, 0x41, 0x1b, 0x2d, 0x45, 0x73, - 0x29, 0x1f, 0x9d, 0xab, 0xf1, 0xc7, 0xe8, 0xde, 0x84, 0xb2, - 0x30, 0x06, 0x5c, 0x6a, 0x8c, 0xba, 0xe0, 0xd6, 0x54, 0x62, - 0x38, 0x0e, 0x21, 0x17, 0x4d, 0x7b, 0xf9, 0xcf, 0x95, 0xa3, - 0xcb, 0xfd, 0xa7, 0x91, 0x13, 0x25, 0x7f, 0x49, 0x66, 0x50, - 0x0a, 0x3c, 0xbe, 0x88, 0xd2, 0xe4, 0x03, 0x35, 0x6f, 0x59, - 0xdb, 0xed, 0xb7, 0x81, 0xae, 0x98, 0xc2, 0xf4, 0x76, 0x40, - 0x1a, 0x2c, 0x44, 0x72, 0x28, 0x1e, 0x9c, 0xaa, 0xf0, 0xc6, - 0xe9, 0xdf, 0x85, 0xb3, 0x31, 0x07, 0x5d, 0x6b, 0x8d, 0xbb, - 0xe1, 0xd7, 0x55, 0x63, 0x39, 0x0f, 0x20, 0x16, 0x4c, 0x7a, - 0xf8, 0xce, 0x94, 0xa2, 0xca, 0xfc, 0xa6, 0x90, 0x12, 0x24, - 0x7e, 0x48, 0x67, 0x51, 0x0b, 0x3d, 0xbf, 0x89, 0xd3, 0xe5, - 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, - 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20, 0x57, 0x60, 0x39, 0x0e, - 0x8b, 0xbc, 0xe5, 0xd2, 0xf2, 0xc5, 0x9c, 0xab, 0x2e, 0x19, - 0x40, 0x77, 0xae, 0x99, 0xc0, 0xf7, 0x72, 0x45, 0x1c, 0x2b, - 0x0b, 0x3c, 0x65, 0x52, 0xd7, 0xe0, 0xb9, 0x8e, 0xf9, 0xce, - 0x97, 0xa0, 0x25, 0x12, 0x4b, 0x7c, 0x5c, 0x6b, 0x32, 0x05, - 0x80, 0xb7, 0xee, 0xd9, 0x41, 0x76, 0x2f, 0x18, 0x9d, 0xaa, - 0xf3, 0xc4, 0xe4, 0xd3, 0x8a, 0xbd, 0x38, 0x0f, 0x56, 0x61, - 0x16, 0x21, 0x78, 0x4f, 0xca, 0xfd, 0xa4, 0x93, 0xb3, 0x84, - 0xdd, 0xea, 0x6f, 0x58, 0x01, 0x36, 0xef, 0xd8, 0x81, 0xb6, - 0x33, 0x04, 0x5d, 0x6a, 0x4a, 0x7d, 0x24, 0x13, 0x96, 0xa1, - 0xf8, 0xcf, 0xb8, 0x8f, 0xd6, 0xe1, 0x64, 0x53, 0x0a, 0x3d, - 0x1d, 0x2a, 0x73, 0x44, 0xc1, 0xf6, 0xaf, 0x98, 0x82, 0xb5, - 0xec, 0xdb, 0x5e, 0x69, 0x30, 0x07, 0x27, 0x10, 0x49, 0x7e, - 0xfb, 0xcc, 0x95, 0xa2, 0xd5, 0xe2, 0xbb, 0x8c, 0x09, 0x3e, - 0x67, 0x50, 0x70, 0x47, 0x1e, 0x29, 0xac, 0x9b, 0xc2, 0xf5, - 0x2c, 0x1b, 0x42, 0x75, 0xf0, 0xc7, 0x9e, 0xa9, 0x89, 0xbe, - 0xe7, 0xd0, 0x55, 0x62, 0x3b, 0x0c, 0x7b, 0x4c, 0x15, 0x22, - 0xa7, 0x90, 0xc9, 0xfe, 0xde, 0xe9, 0xb0, 0x87, 0x02, 0x35, - 0x6c, 0x5b, 0xc3, 0xf4, 0xad, 0x9a, 0x1f, 0x28, 0x71, 0x46, - 0x66, 0x51, 0x08, 0x3f, 0xba, 0x8d, 0xd4, 0xe3, 0x94, 0xa3, - 0xfa, 0xcd, 0x48, 0x7f, 0x26, 0x11, 0x31, 0x06, 0x5f, 0x68, - 0xed, 0xda, 0x83, 0xb4, 0x6d, 0x5a, 0x03, 0x34, 0xb1, 0x86, - 0xdf, 0xe8, 0xc8, 0xff, 0xa6, 0x91, 0x14, 0x23, 0x7a, 0x4d, - 0x3a, 0x0d, 0x54, 0x63, 0xe6, 0xd1, 0x88, 0xbf, 0x9f, 0xa8, - 0xf1, 0xc6, 0x43, 0x74, 0x2d, 0x1a, 0x00, 0x38, 0x70, 0x48, - 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, - 0x4d, 0x75, 0xa7, 0x9f, 0xd7, 0xef, 0x47, 0x7f, 0x37, 0x0f, - 0x7a, 0x42, 0x0a, 0x32, 0x9a, 0xa2, 0xea, 0xd2, 0x53, 0x6b, - 0x23, 0x1b, 0xb3, 0x8b, 0xc3, 0xfb, 0x8e, 0xb6, 0xfe, 0xc6, - 0x6e, 0x56, 0x1e, 0x26, 0xf4, 0xcc, 0x84, 0xbc, 0x14, 0x2c, - 0x64, 0x5c, 0x29, 0x11, 0x59, 0x61, 0xc9, 0xf1, 0xb9, 0x81, - 0xa6, 0x9e, 0xd6, 0xee, 0x46, 0x7e, 0x36, 0x0e, 0x7b, 0x43, - 0x0b, 0x33, 0x9b, 0xa3, 0xeb, 0xd3, 0x01, 0x39, 0x71, 0x49, - 0xe1, 0xd9, 0x91, 0xa9, 0xdc, 0xe4, 0xac, 0x94, 0x3c, 0x04, - 0x4c, 0x74, 0xf5, 0xcd, 0x85, 0xbd, 0x15, 0x2d, 0x65, 0x5d, - 0x28, 0x10, 0x58, 0x60, 0xc8, 0xf0, 0xb8, 0x80, 0x52, 0x6a, - 0x22, 0x1a, 0xb2, 0x8a, 0xc2, 0xfa, 0x8f, 0xb7, 0xff, 0xc7, - 0x6f, 0x57, 0x1f, 0x27, 0x51, 0x69, 0x21, 0x19, 0xb1, 0x89, - 0xc1, 0xf9, 0x8c, 0xb4, 0xfc, 0xc4, 0x6c, 0x54, 0x1c, 0x24, - 0xf6, 0xce, 0x86, 0xbe, 0x16, 0x2e, 0x66, 0x5e, 0x2b, 0x13, - 0x5b, 0x63, 0xcb, 0xf3, 0xbb, 0x83, 0x02, 0x3a, 0x72, 0x4a, - 0xe2, 0xda, 0x92, 0xaa, 0xdf, 0xe7, 0xaf, 0x97, 0x3f, 0x07, - 0x4f, 0x77, 0xa5, 0x9d, 0xd5, 0xed, 0x45, 0x7d, 0x35, 0x0d, - 0x78, 0x40, 0x08, 0x30, 0x98, 0xa0, 0xe8, 0xd0, 0xf7, 0xcf, - 0x87, 0xbf, 0x17, 0x2f, 0x67, 0x5f, 0x2a, 0x12, 0x5a, 0x62, - 0xca, 0xf2, 0xba, 0x82, 0x50, 0x68, 0x20, 0x18, 0xb0, 0x88, - 0xc0, 0xf8, 0x8d, 0xb5, 0xfd, 0xc5, 0x6d, 0x55, 0x1d, 0x25, - 0xa4, 0x9c, 0xd4, 0xec, 0x44, 0x7c, 0x34, 0x0c, 0x79, 0x41, - 0x09, 0x31, 0x99, 0xa1, 0xe9, 0xd1, 0x03, 0x3b, 0x73, 0x4b, - 0xe3, 0xdb, 0x93, 0xab, 0xde, 0xe6, 0xae, 0x96, 0x3e, 0x06, - 0x4e, 0x76, 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, - 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a, 0xb7, 0x8e, - 0xc5, 0xfc, 0x53, 0x6a, 0x21, 0x18, 0x62, 0x5b, 0x10, 0x29, - 0x86, 0xbf, 0xf4, 0xcd, 0x73, 0x4a, 0x01, 0x38, 0x97, 0xae, - 0xe5, 0xdc, 0xa6, 0x9f, 0xd4, 0xed, 0x42, 0x7b, 0x30, 0x09, - 0xc4, 0xfd, 0xb6, 0x8f, 0x20, 0x19, 0x52, 0x6b, 0x11, 0x28, - 0x63, 0x5a, 0xf5, 0xcc, 0x87, 0xbe, 0xe6, 0xdf, 0x94, 0xad, - 0x02, 0x3b, 0x70, 0x49, 0x33, 0x0a, 0x41, 0x78, 0xd7, 0xee, - 0xa5, 0x9c, 0x51, 0x68, 0x23, 0x1a, 0xb5, 0x8c, 0xc7, 0xfe, - 0x84, 0xbd, 0xf6, 0xcf, 0x60, 0x59, 0x12, 0x2b, 0x95, 0xac, - 0xe7, 0xde, 0x71, 0x48, 0x03, 0x3a, 0x40, 0x79, 0x32, 0x0b, - 0xa4, 0x9d, 0xd6, 0xef, 0x22, 0x1b, 0x50, 0x69, 0xc6, 0xff, - 0xb4, 0x8d, 0xf7, 0xce, 0x85, 0xbc, 0x13, 0x2a, 0x61, 0x58, - 0xd1, 0xe8, 0xa3, 0x9a, 0x35, 0x0c, 0x47, 0x7e, 0x04, 0x3d, - 0x76, 0x4f, 0xe0, 0xd9, 0x92, 0xab, 0x66, 0x5f, 0x14, 0x2d, - 0x82, 0xbb, 0xf0, 0xc9, 0xb3, 0x8a, 0xc1, 0xf8, 0x57, 0x6e, - 0x25, 0x1c, 0xa2, 0x9b, 0xd0, 0xe9, 0x46, 0x7f, 0x34, 0x0d, - 0x77, 0x4e, 0x05, 0x3c, 0x93, 0xaa, 0xe1, 0xd8, 0x15, 0x2c, - 0x67, 0x5e, 0xf1, 0xc8, 0x83, 0xba, 0xc0, 0xf9, 0xb2, 0x8b, - 0x24, 0x1d, 0x56, 0x6f, 0x37, 0x0e, 0x45, 0x7c, 0xd3, 0xea, - 0xa1, 0x98, 0xe2, 0xdb, 0x90, 0xa9, 0x06, 0x3f, 0x74, 0x4d, - 0x80, 0xb9, 0xf2, 0xcb, 0x64, 0x5d, 0x16, 0x2f, 0x55, 0x6c, - 0x27, 0x1e, 0xb1, 0x88, 0xc3, 0xfa, 0x44, 0x7d, 0x36, 0x0f, - 0xa0, 0x99, 0xd2, 0xeb, 0x91, 0xa8, 0xe3, 0xda, 0x75, 0x4c, - 0x07, 0x3e, 0xf3, 0xca, 0x81, 0xb8, 0x17, 0x2e, 0x65, 0x5c, - 0x26, 0x1f, 0x54, 0x6d, 0xc2, 0xfb, 0xb0, 0x89, 0x00, 0x3a, - 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, - 0x25, 0x1f, 0x51, 0x6b, 0x87, 0xbd, 0xf3, 0xc9, 0x6f, 0x55, - 0x1b, 0x21, 0x4a, 0x70, 0x3e, 0x04, 0xa2, 0x98, 0xd6, 0xec, - 0x13, 0x29, 0x67, 0x5d, 0xfb, 0xc1, 0x8f, 0xb5, 0xde, 0xe4, - 0xaa, 0x90, 0x36, 0x0c, 0x42, 0x78, 0x94, 0xae, 0xe0, 0xda, - 0x7c, 0x46, 0x08, 0x32, 0x59, 0x63, 0x2d, 0x17, 0xb1, 0x8b, - 0xc5, 0xff, 0x26, 0x1c, 0x52, 0x68, 0xce, 0xf4, 0xba, 0x80, - 0xeb, 0xd1, 0x9f, 0xa5, 0x03, 0x39, 0x77, 0x4d, 0xa1, 0x9b, - 0xd5, 0xef, 0x49, 0x73, 0x3d, 0x07, 0x6c, 0x56, 0x18, 0x22, - 0x84, 0xbe, 0xf0, 0xca, 0x35, 0x0f, 0x41, 0x7b, 0xdd, 0xe7, - 0xa9, 0x93, 0xf8, 0xc2, 0x8c, 0xb6, 0x10, 0x2a, 0x64, 0x5e, - 0xb2, 0x88, 0xc6, 0xfc, 0x5a, 0x60, 0x2e, 0x14, 0x7f, 0x45, - 0x0b, 0x31, 0x97, 0xad, 0xe3, 0xd9, 0x4c, 0x76, 0x38, 0x02, - 0xa4, 0x9e, 0xd0, 0xea, 0x81, 0xbb, 0xf5, 0xcf, 0x69, 0x53, - 0x1d, 0x27, 0xcb, 0xf1, 0xbf, 0x85, 0x23, 0x19, 0x57, 0x6d, - 0x06, 0x3c, 0x72, 0x48, 0xee, 0xd4, 0x9a, 0xa0, 0x5f, 0x65, - 0x2b, 0x11, 0xb7, 0x8d, 0xc3, 0xf9, 0x92, 0xa8, 0xe6, 0xdc, - 0x7a, 0x40, 0x0e, 0x34, 0xd8, 0xe2, 0xac, 0x96, 0x30, 0x0a, - 0x44, 0x7e, 0x15, 0x2f, 0x61, 0x5b, 0xfd, 0xc7, 0x89, 0xb3, - 0x6a, 0x50, 0x1e, 0x24, 0x82, 0xb8, 0xf6, 0xcc, 0xa7, 0x9d, - 0xd3, 0xe9, 0x4f, 0x75, 0x3b, 0x01, 0xed, 0xd7, 0x99, 0xa3, - 0x05, 0x3f, 0x71, 0x4b, 0x20, 0x1a, 0x54, 0x6e, 0xc8, 0xf2, - 0xbc, 0x86, 0x79, 0x43, 0x0d, 0x37, 0x91, 0xab, 0xe5, 0xdf, - 0xb4, 0x8e, 0xc0, 0xfa, 0x5c, 0x66, 0x28, 0x12, 0xfe, 0xc4, - 0x8a, 0xb0, 0x16, 0x2c, 0x62, 0x58, 0x33, 0x09, 0x47, 0x7d, - 0xdb, 0xe1, 0xaf, 0x95, 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, - 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64, - 0x97, 0xac, 0xe1, 0xda, 0x7b, 0x40, 0x0d, 0x36, 0x52, 0x69, - 0x24, 0x1f, 0xbe, 0x85, 0xc8, 0xf3, 0x33, 0x08, 0x45, 0x7e, - 0xdf, 0xe4, 0xa9, 0x92, 0xf6, 0xcd, 0x80, 0xbb, 0x1a, 0x21, - 0x6c, 0x57, 0xa4, 0x9f, 0xd2, 0xe9, 0x48, 0x73, 0x3e, 0x05, - 0x61, 0x5a, 0x17, 0x2c, 0x8d, 0xb6, 0xfb, 0xc0, 0x66, 0x5d, - 0x10, 0x2b, 0x8a, 0xb1, 0xfc, 0xc7, 0xa3, 0x98, 0xd5, 0xee, - 0x4f, 0x74, 0x39, 0x02, 0xf1, 0xca, 0x87, 0xbc, 0x1d, 0x26, - 0x6b, 0x50, 0x34, 0x0f, 0x42, 0x79, 0xd8, 0xe3, 0xae, 0x95, - 0x55, 0x6e, 0x23, 0x18, 0xb9, 0x82, 0xcf, 0xf4, 0x90, 0xab, - 0xe6, 0xdd, 0x7c, 0x47, 0x0a, 0x31, 0xc2, 0xf9, 0xb4, 0x8f, - 0x2e, 0x15, 0x58, 0x63, 0x07, 0x3c, 0x71, 0x4a, 0xeb, 0xd0, - 0x9d, 0xa6, 0xcc, 0xf7, 0xba, 0x81, 0x20, 0x1b, 0x56, 0x6d, - 0x09, 0x32, 0x7f, 0x44, 0xe5, 0xde, 0x93, 0xa8, 0x5b, 0x60, - 0x2d, 0x16, 0xb7, 0x8c, 0xc1, 0xfa, 0x9e, 0xa5, 0xe8, 0xd3, - 0x72, 0x49, 0x04, 0x3f, 0xff, 0xc4, 0x89, 0xb2, 0x13, 0x28, - 0x65, 0x5e, 0x3a, 0x01, 0x4c, 0x77, 0xd6, 0xed, 0xa0, 0x9b, - 0x68, 0x53, 0x1e, 0x25, 0x84, 0xbf, 0xf2, 0xc9, 0xad, 0x96, - 0xdb, 0xe0, 0x41, 0x7a, 0x37, 0x0c, 0xaa, 0x91, 0xdc, 0xe7, - 0x46, 0x7d, 0x30, 0x0b, 0x6f, 0x54, 0x19, 0x22, 0x83, 0xb8, - 0xf5, 0xce, 0x3d, 0x06, 0x4b, 0x70, 0xd1, 0xea, 0xa7, 0x9c, - 0xf8, 0xc3, 0x8e, 0xb5, 0x14, 0x2f, 0x62, 0x59, 0x99, 0xa2, - 0xef, 0xd4, 0x75, 0x4e, 0x03, 0x38, 0x5c, 0x67, 0x2a, 0x11, - 0xb0, 0x8b, 0xc6, 0xfd, 0x0e, 0x35, 0x78, 0x43, 0xe2, 0xd9, - 0x94, 0xaf, 0xcb, 0xf0, 0xbd, 0x86, 0x27, 0x1c, 0x51, 0x6a, - 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, - 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49, 0xe7, 0xdb, 0x9f, 0xa3, - 0x17, 0x2b, 0x6f, 0x53, 0x1a, 0x26, 0x62, 0x5e, 0xea, 0xd6, - 0x92, 0xae, 0xd3, 0xef, 0xab, 0x97, 0x23, 0x1f, 0x5b, 0x67, - 0x2e, 0x12, 0x56, 0x6a, 0xde, 0xe2, 0xa6, 0x9a, 0x34, 0x08, - 0x4c, 0x70, 0xc4, 0xf8, 0xbc, 0x80, 0xc9, 0xf5, 0xb1, 0x8d, - 0x39, 0x05, 0x41, 0x7d, 0xbb, 0x87, 0xc3, 0xff, 0x4b, 0x77, - 0x33, 0x0f, 0x46, 0x7a, 0x3e, 0x02, 0xb6, 0x8a, 0xce, 0xf2, - 0x5c, 0x60, 0x24, 0x18, 0xac, 0x90, 0xd4, 0xe8, 0xa1, 0x9d, - 0xd9, 0xe5, 0x51, 0x6d, 0x29, 0x15, 0x68, 0x54, 0x10, 0x2c, - 0x98, 0xa4, 0xe0, 0xdc, 0x95, 0xa9, 0xed, 0xd1, 0x65, 0x59, - 0x1d, 0x21, 0x8f, 0xb3, 0xf7, 0xcb, 0x7f, 0x43, 0x07, 0x3b, - 0x72, 0x4e, 0x0a, 0x36, 0x82, 0xbe, 0xfa, 0xc6, 0x6b, 0x57, - 0x13, 0x2f, 0x9b, 0xa7, 0xe3, 0xdf, 0x96, 0xaa, 0xee, 0xd2, - 0x66, 0x5a, 0x1e, 0x22, 0x8c, 0xb0, 0xf4, 0xc8, 0x7c, 0x40, - 0x04, 0x38, 0x71, 0x4d, 0x09, 0x35, 0x81, 0xbd, 0xf9, 0xc5, - 0xb8, 0x84, 0xc0, 0xfc, 0x48, 0x74, 0x30, 0x0c, 0x45, 0x79, - 0x3d, 0x01, 0xb5, 0x89, 0xcd, 0xf1, 0x5f, 0x63, 0x27, 0x1b, - 0xaf, 0x93, 0xd7, 0xeb, 0xa2, 0x9e, 0xda, 0xe6, 0x52, 0x6e, - 0x2a, 0x16, 0xd0, 0xec, 0xa8, 0x94, 0x20, 0x1c, 0x58, 0x64, - 0x2d, 0x11, 0x55, 0x69, 0xdd, 0xe1, 0xa5, 0x99, 0x37, 0x0b, - 0x4f, 0x73, 0xc7, 0xfb, 0xbf, 0x83, 0xca, 0xf6, 0xb2, 0x8e, - 0x3a, 0x06, 0x42, 0x7e, 0x03, 0x3f, 0x7b, 0x47, 0xf3, 0xcf, - 0x8b, 0xb7, 0xfe, 0xc2, 0x86, 0xba, 0x0e, 0x32, 0x76, 0x4a, - 0xe4, 0xd8, 0x9c, 0xa0, 0x14, 0x28, 0x6c, 0x50, 0x19, 0x25, - 0x61, 0x5d, 0xe9, 0xd5, 0x91, 0xad, 0x00, 0x3d, 0x7a, 0x47, - 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, - 0x7b, 0x46, 0xf7, 0xca, 0x8d, 0xb0, 0x03, 0x3e, 0x79, 0x44, - 0x02, 0x3f, 0x78, 0x45, 0xf6, 0xcb, 0x8c, 0xb1, 0xf3, 0xce, - 0x89, 0xb4, 0x07, 0x3a, 0x7d, 0x40, 0x06, 0x3b, 0x7c, 0x41, - 0xf2, 0xcf, 0x88, 0xb5, 0x04, 0x39, 0x7e, 0x43, 0xf0, 0xcd, - 0x8a, 0xb7, 0xf1, 0xcc, 0x8b, 0xb6, 0x05, 0x38, 0x7f, 0x42, - 0xfb, 0xc6, 0x81, 0xbc, 0x0f, 0x32, 0x75, 0x48, 0x0e, 0x33, - 0x74, 0x49, 0xfa, 0xc7, 0x80, 0xbd, 0x0c, 0x31, 0x76, 0x4b, - 0xf8, 0xc5, 0x82, 0xbf, 0xf9, 0xc4, 0x83, 0xbe, 0x0d, 0x30, - 0x77, 0x4a, 0x08, 0x35, 0x72, 0x4f, 0xfc, 0xc1, 0x86, 0xbb, - 0xfd, 0xc0, 0x87, 0xba, 0x09, 0x34, 0x73, 0x4e, 0xff, 0xc2, - 0x85, 0xb8, 0x0b, 0x36, 0x71, 0x4c, 0x0a, 0x37, 0x70, 0x4d, - 0xfe, 0xc3, 0x84, 0xb9, 0xeb, 0xd6, 0x91, 0xac, 0x1f, 0x22, - 0x65, 0x58, 0x1e, 0x23, 0x64, 0x59, 0xea, 0xd7, 0x90, 0xad, - 0x1c, 0x21, 0x66, 0x5b, 0xe8, 0xd5, 0x92, 0xaf, 0xe9, 0xd4, - 0x93, 0xae, 0x1d, 0x20, 0x67, 0x5a, 0x18, 0x25, 0x62, 0x5f, - 0xec, 0xd1, 0x96, 0xab, 0xed, 0xd0, 0x97, 0xaa, 0x19, 0x24, - 0x63, 0x5e, 0xef, 0xd2, 0x95, 0xa8, 0x1b, 0x26, 0x61, 0x5c, - 0x1a, 0x27, 0x60, 0x5d, 0xee, 0xd3, 0x94, 0xa9, 0x10, 0x2d, - 0x6a, 0x57, 0xe4, 0xd9, 0x9e, 0xa3, 0xe5, 0xd8, 0x9f, 0xa2, - 0x11, 0x2c, 0x6b, 0x56, 0xe7, 0xda, 0x9d, 0xa0, 0x13, 0x2e, - 0x69, 0x54, 0x12, 0x2f, 0x68, 0x55, 0xe6, 0xdb, 0x9c, 0xa1, - 0xe3, 0xde, 0x99, 0xa4, 0x17, 0x2a, 0x6d, 0x50, 0x16, 0x2b, - 0x6c, 0x51, 0xe2, 0xdf, 0x98, 0xa5, 0x14, 0x29, 0x6e, 0x53, - 0xe0, 0xdd, 0x9a, 0xa7, 0xe1, 0xdc, 0x9b, 0xa6, 0x15, 0x28, - 0x6f, 0x52, 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, - 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57, 0xc7, 0xf9, - 0xbb, 0x85, 0x3f, 0x01, 0x43, 0x7d, 0x2a, 0x14, 0x56, 0x68, - 0xd2, 0xec, 0xae, 0x90, 0x93, 0xad, 0xef, 0xd1, 0x6b, 0x55, - 0x17, 0x29, 0x7e, 0x40, 0x02, 0x3c, 0x86, 0xb8, 0xfa, 0xc4, - 0x54, 0x6a, 0x28, 0x16, 0xac, 0x92, 0xd0, 0xee, 0xb9, 0x87, - 0xc5, 0xfb, 0x41, 0x7f, 0x3d, 0x03, 0x3b, 0x05, 0x47, 0x79, - 0xc3, 0xfd, 0xbf, 0x81, 0xd6, 0xe8, 0xaa, 0x94, 0x2e, 0x10, - 0x52, 0x6c, 0xfc, 0xc2, 0x80, 0xbe, 0x04, 0x3a, 0x78, 0x46, - 0x11, 0x2f, 0x6d, 0x53, 0xe9, 0xd7, 0x95, 0xab, 0xa8, 0x96, - 0xd4, 0xea, 0x50, 0x6e, 0x2c, 0x12, 0x45, 0x7b, 0x39, 0x07, - 0xbd, 0x83, 0xc1, 0xff, 0x6f, 0x51, 0x13, 0x2d, 0x97, 0xa9, - 0xeb, 0xd5, 0x82, 0xbc, 0xfe, 0xc0, 0x7a, 0x44, 0x06, 0x38, - 0x76, 0x48, 0x0a, 0x34, 0x8e, 0xb0, 0xf2, 0xcc, 0x9b, 0xa5, - 0xe7, 0xd9, 0x63, 0x5d, 0x1f, 0x21, 0xb1, 0x8f, 0xcd, 0xf3, - 0x49, 0x77, 0x35, 0x0b, 0x5c, 0x62, 0x20, 0x1e, 0xa4, 0x9a, - 0xd8, 0xe6, 0xe5, 0xdb, 0x99, 0xa7, 0x1d, 0x23, 0x61, 0x5f, - 0x08, 0x36, 0x74, 0x4a, 0xf0, 0xce, 0x8c, 0xb2, 0x22, 0x1c, - 0x5e, 0x60, 0xda, 0xe4, 0xa6, 0x98, 0xcf, 0xf1, 0xb3, 0x8d, - 0x37, 0x09, 0x4b, 0x75, 0x4d, 0x73, 0x31, 0x0f, 0xb5, 0x8b, - 0xc9, 0xf7, 0xa0, 0x9e, 0xdc, 0xe2, 0x58, 0x66, 0x24, 0x1a, - 0x8a, 0xb4, 0xf6, 0xc8, 0x72, 0x4c, 0x0e, 0x30, 0x67, 0x59, - 0x1b, 0x25, 0x9f, 0xa1, 0xe3, 0xdd, 0xde, 0xe0, 0xa2, 0x9c, - 0x26, 0x18, 0x5a, 0x64, 0x33, 0x0d, 0x4f, 0x71, 0xcb, 0xf5, - 0xb7, 0x89, 0x19, 0x27, 0x65, 0x5b, 0xe1, 0xdf, 0x9d, 0xa3, - 0xf4, 0xca, 0x88, 0xb6, 0x0c, 0x32, 0x70, 0x4e, 0x00, 0x3f, - 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, - 0x19, 0x26, 0x67, 0x58, 0xd7, 0xe8, 0xa9, 0x96, 0x2b, 0x14, - 0x55, 0x6a, 0x32, 0x0d, 0x4c, 0x73, 0xce, 0xf1, 0xb0, 0x8f, - 0xb3, 0x8c, 0xcd, 0xf2, 0x4f, 0x70, 0x31, 0x0e, 0x56, 0x69, - 0x28, 0x17, 0xaa, 0x95, 0xd4, 0xeb, 0x64, 0x5b, 0x1a, 0x25, - 0x98, 0xa7, 0xe6, 0xd9, 0x81, 0xbe, 0xff, 0xc0, 0x7d, 0x42, - 0x03, 0x3c, 0x7b, 0x44, 0x05, 0x3a, 0x87, 0xb8, 0xf9, 0xc6, - 0x9e, 0xa1, 0xe0, 0xdf, 0x62, 0x5d, 0x1c, 0x23, 0xac, 0x93, - 0xd2, 0xed, 0x50, 0x6f, 0x2e, 0x11, 0x49, 0x76, 0x37, 0x08, - 0xb5, 0x8a, 0xcb, 0xf4, 0xc8, 0xf7, 0xb6, 0x89, 0x34, 0x0b, - 0x4a, 0x75, 0x2d, 0x12, 0x53, 0x6c, 0xd1, 0xee, 0xaf, 0x90, - 0x1f, 0x20, 0x61, 0x5e, 0xe3, 0xdc, 0x9d, 0xa2, 0xfa, 0xc5, - 0x84, 0xbb, 0x06, 0x39, 0x78, 0x47, 0xf6, 0xc9, 0x88, 0xb7, - 0x0a, 0x35, 0x74, 0x4b, 0x13, 0x2c, 0x6d, 0x52, 0xef, 0xd0, - 0x91, 0xae, 0x21, 0x1e, 0x5f, 0x60, 0xdd, 0xe2, 0xa3, 0x9c, - 0xc4, 0xfb, 0xba, 0x85, 0x38, 0x07, 0x46, 0x79, 0x45, 0x7a, - 0x3b, 0x04, 0xb9, 0x86, 0xc7, 0xf8, 0xa0, 0x9f, 0xde, 0xe1, - 0x5c, 0x63, 0x22, 0x1d, 0x92, 0xad, 0xec, 0xd3, 0x6e, 0x51, - 0x10, 0x2f, 0x77, 0x48, 0x09, 0x36, 0x8b, 0xb4, 0xf5, 0xca, - 0x8d, 0xb2, 0xf3, 0xcc, 0x71, 0x4e, 0x0f, 0x30, 0x68, 0x57, - 0x16, 0x29, 0x94, 0xab, 0xea, 0xd5, 0x5a, 0x65, 0x24, 0x1b, - 0xa6, 0x99, 0xd8, 0xe7, 0xbf, 0x80, 0xc1, 0xfe, 0x43, 0x7c, - 0x3d, 0x02, 0x3e, 0x01, 0x40, 0x7f, 0xc2, 0xfd, 0xbc, 0x83, - 0xdb, 0xe4, 0xa5, 0x9a, 0x27, 0x18, 0x59, 0x66, 0xe9, 0xd6, - 0x97, 0xa8, 0x15, 0x2a, 0x6b, 0x54, 0x0c, 0x33, 0x72, 0x4d, - 0xf0, 0xcf, 0x8e, 0xb1, 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, - 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7, - 0x74, 0x34, 0xf4, 0xb4, 0x69, 0x29, 0xe9, 0xa9, 0x4e, 0x0e, - 0xce, 0x8e, 0x53, 0x13, 0xd3, 0x93, 0xe8, 0xa8, 0x68, 0x28, - 0xf5, 0xb5, 0x75, 0x35, 0xd2, 0x92, 0x52, 0x12, 0xcf, 0x8f, - 0x4f, 0x0f, 0x9c, 0xdc, 0x1c, 0x5c, 0x81, 0xc1, 0x01, 0x41, - 0xa6, 0xe6, 0x26, 0x66, 0xbb, 0xfb, 0x3b, 0x7b, 0xcd, 0x8d, - 0x4d, 0x0d, 0xd0, 0x90, 0x50, 0x10, 0xf7, 0xb7, 0x77, 0x37, - 0xea, 0xaa, 0x6a, 0x2a, 0xb9, 0xf9, 0x39, 0x79, 0xa4, 0xe4, - 0x24, 0x64, 0x83, 0xc3, 0x03, 0x43, 0x9e, 0xde, 0x1e, 0x5e, - 0x25, 0x65, 0xa5, 0xe5, 0x38, 0x78, 0xb8, 0xf8, 0x1f, 0x5f, - 0x9f, 0xdf, 0x02, 0x42, 0x82, 0xc2, 0x51, 0x11, 0xd1, 0x91, - 0x4c, 0x0c, 0xcc, 0x8c, 0x6b, 0x2b, 0xeb, 0xab, 0x76, 0x36, - 0xf6, 0xb6, 0x87, 0xc7, 0x07, 0x47, 0x9a, 0xda, 0x1a, 0x5a, - 0xbd, 0xfd, 0x3d, 0x7d, 0xa0, 0xe0, 0x20, 0x60, 0xf3, 0xb3, - 0x73, 0x33, 0xee, 0xae, 0x6e, 0x2e, 0xc9, 0x89, 0x49, 0x09, - 0xd4, 0x94, 0x54, 0x14, 0x6f, 0x2f, 0xef, 0xaf, 0x72, 0x32, - 0xf2, 0xb2, 0x55, 0x15, 0xd5, 0x95, 0x48, 0x08, 0xc8, 0x88, - 0x1b, 0x5b, 0x9b, 0xdb, 0x06, 0x46, 0x86, 0xc6, 0x21, 0x61, - 0xa1, 0xe1, 0x3c, 0x7c, 0xbc, 0xfc, 0x4a, 0x0a, 0xca, 0x8a, - 0x57, 0x17, 0xd7, 0x97, 0x70, 0x30, 0xf0, 0xb0, 0x6d, 0x2d, - 0xed, 0xad, 0x3e, 0x7e, 0xbe, 0xfe, 0x23, 0x63, 0xa3, 0xe3, - 0x04, 0x44, 0x84, 0xc4, 0x19, 0x59, 0x99, 0xd9, 0xa2, 0xe2, - 0x22, 0x62, 0xbf, 0xff, 0x3f, 0x7f, 0x98, 0xd8, 0x18, 0x58, - 0x85, 0xc5, 0x05, 0x45, 0xd6, 0x96, 0x56, 0x16, 0xcb, 0x8b, - 0x4b, 0x0b, 0xec, 0xac, 0x6c, 0x2c, 0xf1, 0xb1, 0x71, 0x31, - 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, - 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8, 0x64, 0x25, 0xe6, 0xa7, - 0x7d, 0x3c, 0xff, 0xbe, 0x56, 0x17, 0xd4, 0x95, 0x4f, 0x0e, - 0xcd, 0x8c, 0xc8, 0x89, 0x4a, 0x0b, 0xd1, 0x90, 0x53, 0x12, - 0xfa, 0xbb, 0x78, 0x39, 0xe3, 0xa2, 0x61, 0x20, 0xac, 0xed, - 0x2e, 0x6f, 0xb5, 0xf4, 0x37, 0x76, 0x9e, 0xdf, 0x1c, 0x5d, - 0x87, 0xc6, 0x05, 0x44, 0x8d, 0xcc, 0x0f, 0x4e, 0x94, 0xd5, - 0x16, 0x57, 0xbf, 0xfe, 0x3d, 0x7c, 0xa6, 0xe7, 0x24, 0x65, - 0xe9, 0xa8, 0x6b, 0x2a, 0xf0, 0xb1, 0x72, 0x33, 0xdb, 0x9a, - 0x59, 0x18, 0xc2, 0x83, 0x40, 0x01, 0x45, 0x04, 0xc7, 0x86, - 0x5c, 0x1d, 0xde, 0x9f, 0x77, 0x36, 0xf5, 0xb4, 0x6e, 0x2f, - 0xec, 0xad, 0x21, 0x60, 0xa3, 0xe2, 0x38, 0x79, 0xba, 0xfb, - 0x13, 0x52, 0x91, 0xd0, 0x0a, 0x4b, 0x88, 0xc9, 0x07, 0x46, - 0x85, 0xc4, 0x1e, 0x5f, 0x9c, 0xdd, 0x35, 0x74, 0xb7, 0xf6, - 0x2c, 0x6d, 0xae, 0xef, 0x63, 0x22, 0xe1, 0xa0, 0x7a, 0x3b, - 0xf8, 0xb9, 0x51, 0x10, 0xd3, 0x92, 0x48, 0x09, 0xca, 0x8b, - 0xcf, 0x8e, 0x4d, 0x0c, 0xd6, 0x97, 0x54, 0x15, 0xfd, 0xbc, - 0x7f, 0x3e, 0xe4, 0xa5, 0x66, 0x27, 0xab, 0xea, 0x29, 0x68, - 0xb2, 0xf3, 0x30, 0x71, 0x99, 0xd8, 0x1b, 0x5a, 0x80, 0xc1, - 0x02, 0x43, 0x8a, 0xcb, 0x08, 0x49, 0x93, 0xd2, 0x11, 0x50, - 0xb8, 0xf9, 0x3a, 0x7b, 0xa1, 0xe0, 0x23, 0x62, 0xee, 0xaf, - 0x6c, 0x2d, 0xf7, 0xb6, 0x75, 0x34, 0xdc, 0x9d, 0x5e, 0x1f, - 0xc5, 0x84, 0x47, 0x06, 0x42, 0x03, 0xc0, 0x81, 0x5b, 0x1a, - 0xd9, 0x98, 0x70, 0x31, 0xf2, 0xb3, 0x69, 0x28, 0xeb, 0xaa, - 0x26, 0x67, 0xa4, 0xe5, 0x3f, 0x7e, 0xbd, 0xfc, 0x14, 0x55, - 0x96, 0xd7, 0x0d, 0x4c, 0x8f, 0xce, 0x00, 0x42, 0x84, 0xc6, - 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, - 0xbb, 0xf9, 0x54, 0x16, 0xd0, 0x92, 0x41, 0x03, 0xc5, 0x87, - 0x7e, 0x3c, 0xfa, 0xb8, 0x6b, 0x29, 0xef, 0xad, 0xa8, 0xea, - 0x2c, 0x6e, 0xbd, 0xff, 0x39, 0x7b, 0x82, 0xc0, 0x06, 0x44, - 0x97, 0xd5, 0x13, 0x51, 0xfc, 0xbe, 0x78, 0x3a, 0xe9, 0xab, - 0x6d, 0x2f, 0xd6, 0x94, 0x52, 0x10, 0xc3, 0x81, 0x47, 0x05, - 0x4d, 0x0f, 0xc9, 0x8b, 0x58, 0x1a, 0xdc, 0x9e, 0x67, 0x25, - 0xe3, 0xa1, 0x72, 0x30, 0xf6, 0xb4, 0x19, 0x5b, 0x9d, 0xdf, - 0x0c, 0x4e, 0x88, 0xca, 0x33, 0x71, 0xb7, 0xf5, 0x26, 0x64, - 0xa2, 0xe0, 0xe5, 0xa7, 0x61, 0x23, 0xf0, 0xb2, 0x74, 0x36, - 0xcf, 0x8d, 0x4b, 0x09, 0xda, 0x98, 0x5e, 0x1c, 0xb1, 0xf3, - 0x35, 0x77, 0xa4, 0xe6, 0x20, 0x62, 0x9b, 0xd9, 0x1f, 0x5d, - 0x8e, 0xcc, 0x0a, 0x48, 0x9a, 0xd8, 0x1e, 0x5c, 0x8f, 0xcd, - 0x0b, 0x49, 0xb0, 0xf2, 0x34, 0x76, 0xa5, 0xe7, 0x21, 0x63, - 0xce, 0x8c, 0x4a, 0x08, 0xdb, 0x99, 0x5f, 0x1d, 0xe4, 0xa6, - 0x60, 0x22, 0xf1, 0xb3, 0x75, 0x37, 0x32, 0x70, 0xb6, 0xf4, - 0x27, 0x65, 0xa3, 0xe1, 0x18, 0x5a, 0x9c, 0xde, 0x0d, 0x4f, - 0x89, 0xcb, 0x66, 0x24, 0xe2, 0xa0, 0x73, 0x31, 0xf7, 0xb5, - 0x4c, 0x0e, 0xc8, 0x8a, 0x59, 0x1b, 0xdd, 0x9f, 0xd7, 0x95, - 0x53, 0x11, 0xc2, 0x80, 0x46, 0x04, 0xfd, 0xbf, 0x79, 0x3b, - 0xe8, 0xaa, 0x6c, 0x2e, 0x83, 0xc1, 0x07, 0x45, 0x96, 0xd4, - 0x12, 0x50, 0xa9, 0xeb, 0x2d, 0x6f, 0xbc, 0xfe, 0x38, 0x7a, - 0x7f, 0x3d, 0xfb, 0xb9, 0x6a, 0x28, 0xee, 0xac, 0x55, 0x17, - 0xd1, 0x93, 0x40, 0x02, 0xc4, 0x86, 0x2b, 0x69, 0xaf, 0xed, - 0x3e, 0x7c, 0xba, 0xf8, 0x01, 0x43, 0x85, 0xc7, 0x14, 0x56, - 0x90, 0xd2, 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, - 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6, 0x44, 0x07, - 0xc2, 0x81, 0x55, 0x16, 0xd3, 0x90, 0x66, 0x25, 0xe0, 0xa3, - 0x77, 0x34, 0xf1, 0xb2, 0x88, 0xcb, 0x0e, 0x4d, 0x99, 0xda, - 0x1f, 0x5c, 0xaa, 0xe9, 0x2c, 0x6f, 0xbb, 0xf8, 0x3d, 0x7e, - 0xcc, 0x8f, 0x4a, 0x09, 0xdd, 0x9e, 0x5b, 0x18, 0xee, 0xad, - 0x68, 0x2b, 0xff, 0xbc, 0x79, 0x3a, 0x0d, 0x4e, 0x8b, 0xc8, - 0x1c, 0x5f, 0x9a, 0xd9, 0x2f, 0x6c, 0xa9, 0xea, 0x3e, 0x7d, - 0xb8, 0xfb, 0x49, 0x0a, 0xcf, 0x8c, 0x58, 0x1b, 0xde, 0x9d, - 0x6b, 0x28, 0xed, 0xae, 0x7a, 0x39, 0xfc, 0xbf, 0x85, 0xc6, - 0x03, 0x40, 0x94, 0xd7, 0x12, 0x51, 0xa7, 0xe4, 0x21, 0x62, - 0xb6, 0xf5, 0x30, 0x73, 0xc1, 0x82, 0x47, 0x04, 0xd0, 0x93, - 0x56, 0x15, 0xe3, 0xa0, 0x65, 0x26, 0xf2, 0xb1, 0x74, 0x37, - 0x1a, 0x59, 0x9c, 0xdf, 0x0b, 0x48, 0x8d, 0xce, 0x38, 0x7b, - 0xbe, 0xfd, 0x29, 0x6a, 0xaf, 0xec, 0x5e, 0x1d, 0xd8, 0x9b, - 0x4f, 0x0c, 0xc9, 0x8a, 0x7c, 0x3f, 0xfa, 0xb9, 0x6d, 0x2e, - 0xeb, 0xa8, 0x92, 0xd1, 0x14, 0x57, 0x83, 0xc0, 0x05, 0x46, - 0xb0, 0xf3, 0x36, 0x75, 0xa1, 0xe2, 0x27, 0x64, 0xd6, 0x95, - 0x50, 0x13, 0xc7, 0x84, 0x41, 0x02, 0xf4, 0xb7, 0x72, 0x31, - 0xe5, 0xa6, 0x63, 0x20, 0x17, 0x54, 0x91, 0xd2, 0x06, 0x45, - 0x80, 0xc3, 0x35, 0x76, 0xb3, 0xf0, 0x24, 0x67, 0xa2, 0xe1, - 0x53, 0x10, 0xd5, 0x96, 0x42, 0x01, 0xc4, 0x87, 0x71, 0x32, - 0xf7, 0xb4, 0x60, 0x23, 0xe6, 0xa5, 0x9f, 0xdc, 0x19, 0x5a, - 0x8e, 0xcd, 0x08, 0x4b, 0xbd, 0xfe, 0x3b, 0x78, 0xac, 0xef, - 0x2a, 0x69, 0xdb, 0x98, 0x5d, 0x1e, 0xca, 0x89, 0x4c, 0x0f, - 0xf9, 0xba, 0x7f, 0x3c, 0xe8, 0xab, 0x6e, 0x2d, 0x00, 0x44, - 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, - 0x17, 0x53, 0x9f, 0xdb, 0x34, 0x70, 0xbc, 0xf8, 0x39, 0x7d, - 0xb1, 0xf5, 0x2e, 0x6a, 0xa6, 0xe2, 0x23, 0x67, 0xab, 0xef, - 0x68, 0x2c, 0xe0, 0xa4, 0x65, 0x21, 0xed, 0xa9, 0x72, 0x36, - 0xfa, 0xbe, 0x7f, 0x3b, 0xf7, 0xb3, 0x5c, 0x18, 0xd4, 0x90, - 0x51, 0x15, 0xd9, 0x9d, 0x46, 0x02, 0xce, 0x8a, 0x4b, 0x0f, - 0xc3, 0x87, 0xd0, 0x94, 0x58, 0x1c, 0xdd, 0x99, 0x55, 0x11, - 0xca, 0x8e, 0x42, 0x06, 0xc7, 0x83, 0x4f, 0x0b, 0xe4, 0xa0, - 0x6c, 0x28, 0xe9, 0xad, 0x61, 0x25, 0xfe, 0xba, 0x76, 0x32, - 0xf3, 0xb7, 0x7b, 0x3f, 0xb8, 0xfc, 0x30, 0x74, 0xb5, 0xf1, - 0x3d, 0x79, 0xa2, 0xe6, 0x2a, 0x6e, 0xaf, 0xeb, 0x27, 0x63, - 0x8c, 0xc8, 0x04, 0x40, 0x81, 0xc5, 0x09, 0x4d, 0x96, 0xd2, - 0x1e, 0x5a, 0x9b, 0xdf, 0x13, 0x57, 0xbd, 0xf9, 0x35, 0x71, - 0xb0, 0xf4, 0x38, 0x7c, 0xa7, 0xe3, 0x2f, 0x6b, 0xaa, 0xee, - 0x22, 0x66, 0x89, 0xcd, 0x01, 0x45, 0x84, 0xc0, 0x0c, 0x48, - 0x93, 0xd7, 0x1b, 0x5f, 0x9e, 0xda, 0x16, 0x52, 0xd5, 0x91, - 0x5d, 0x19, 0xd8, 0x9c, 0x50, 0x14, 0xcf, 0x8b, 0x47, 0x03, - 0xc2, 0x86, 0x4a, 0x0e, 0xe1, 0xa5, 0x69, 0x2d, 0xec, 0xa8, - 0x64, 0x20, 0xfb, 0xbf, 0x73, 0x37, 0xf6, 0xb2, 0x7e, 0x3a, - 0x6d, 0x29, 0xe5, 0xa1, 0x60, 0x24, 0xe8, 0xac, 0x77, 0x33, - 0xff, 0xbb, 0x7a, 0x3e, 0xf2, 0xb6, 0x59, 0x1d, 0xd1, 0x95, - 0x54, 0x10, 0xdc, 0x98, 0x43, 0x07, 0xcb, 0x8f, 0x4e, 0x0a, - 0xc6, 0x82, 0x05, 0x41, 0x8d, 0xc9, 0x08, 0x4c, 0x80, 0xc4, - 0x1f, 0x5b, 0x97, 0xd3, 0x12, 0x56, 0x9a, 0xde, 0x31, 0x75, - 0xb9, 0xfd, 0x3c, 0x78, 0xb4, 0xf0, 0x2b, 0x6f, 0xa3, 0xe7, - 0x26, 0x62, 0xae, 0xea, 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, - 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4, - 0x24, 0x61, 0xae, 0xeb, 0x2d, 0x68, 0xa7, 0xe2, 0x36, 0x73, - 0xbc, 0xf9, 0x3f, 0x7a, 0xb5, 0xf0, 0x48, 0x0d, 0xc2, 0x87, - 0x41, 0x04, 0xcb, 0x8e, 0x5a, 0x1f, 0xd0, 0x95, 0x53, 0x16, - 0xd9, 0x9c, 0x6c, 0x29, 0xe6, 0xa3, 0x65, 0x20, 0xef, 0xaa, - 0x7e, 0x3b, 0xf4, 0xb1, 0x77, 0x32, 0xfd, 0xb8, 0x90, 0xd5, - 0x1a, 0x5f, 0x99, 0xdc, 0x13, 0x56, 0x82, 0xc7, 0x08, 0x4d, - 0x8b, 0xce, 0x01, 0x44, 0xb4, 0xf1, 0x3e, 0x7b, 0xbd, 0xf8, - 0x37, 0x72, 0xa6, 0xe3, 0x2c, 0x69, 0xaf, 0xea, 0x25, 0x60, - 0xd8, 0x9d, 0x52, 0x17, 0xd1, 0x94, 0x5b, 0x1e, 0xca, 0x8f, - 0x40, 0x05, 0xc3, 0x86, 0x49, 0x0c, 0xfc, 0xb9, 0x76, 0x33, - 0xf5, 0xb0, 0x7f, 0x3a, 0xee, 0xab, 0x64, 0x21, 0xe7, 0xa2, - 0x6d, 0x28, 0x3d, 0x78, 0xb7, 0xf2, 0x34, 0x71, 0xbe, 0xfb, - 0x2f, 0x6a, 0xa5, 0xe0, 0x26, 0x63, 0xac, 0xe9, 0x19, 0x5c, - 0x93, 0xd6, 0x10, 0x55, 0x9a, 0xdf, 0x0b, 0x4e, 0x81, 0xc4, - 0x02, 0x47, 0x88, 0xcd, 0x75, 0x30, 0xff, 0xba, 0x7c, 0x39, - 0xf6, 0xb3, 0x67, 0x22, 0xed, 0xa8, 0x6e, 0x2b, 0xe4, 0xa1, - 0x51, 0x14, 0xdb, 0x9e, 0x58, 0x1d, 0xd2, 0x97, 0x43, 0x06, - 0xc9, 0x8c, 0x4a, 0x0f, 0xc0, 0x85, 0xad, 0xe8, 0x27, 0x62, - 0xa4, 0xe1, 0x2e, 0x6b, 0xbf, 0xfa, 0x35, 0x70, 0xb6, 0xf3, - 0x3c, 0x79, 0x89, 0xcc, 0x03, 0x46, 0x80, 0xc5, 0x0a, 0x4f, - 0x9b, 0xde, 0x11, 0x54, 0x92, 0xd7, 0x18, 0x5d, 0xe5, 0xa0, - 0x6f, 0x2a, 0xec, 0xa9, 0x66, 0x23, 0xf7, 0xb2, 0x7d, 0x38, - 0xfe, 0xbb, 0x74, 0x31, 0xc1, 0x84, 0x4b, 0x0e, 0xc8, 0x8d, - 0x42, 0x07, 0xd3, 0x96, 0x59, 0x1c, 0xda, 0x9f, 0x50, 0x15, - 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, - 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5, 0x14, 0x52, 0x98, 0xde, - 0x11, 0x57, 0x9d, 0xdb, 0x1e, 0x58, 0x92, 0xd4, 0x1b, 0x5d, - 0x97, 0xd1, 0x28, 0x6e, 0xa4, 0xe2, 0x2d, 0x6b, 0xa1, 0xe7, - 0x22, 0x64, 0xae, 0xe8, 0x27, 0x61, 0xab, 0xed, 0x3c, 0x7a, - 0xb0, 0xf6, 0x39, 0x7f, 0xb5, 0xf3, 0x36, 0x70, 0xba, 0xfc, - 0x33, 0x75, 0xbf, 0xf9, 0x50, 0x16, 0xdc, 0x9a, 0x55, 0x13, - 0xd9, 0x9f, 0x5a, 0x1c, 0xd6, 0x90, 0x5f, 0x19, 0xd3, 0x95, - 0x44, 0x02, 0xc8, 0x8e, 0x41, 0x07, 0xcd, 0x8b, 0x4e, 0x08, - 0xc2, 0x84, 0x4b, 0x0d, 0xc7, 0x81, 0x78, 0x3e, 0xf4, 0xb2, - 0x7d, 0x3b, 0xf1, 0xb7, 0x72, 0x34, 0xfe, 0xb8, 0x77, 0x31, - 0xfb, 0xbd, 0x6c, 0x2a, 0xe0, 0xa6, 0x69, 0x2f, 0xe5, 0xa3, - 0x66, 0x20, 0xea, 0xac, 0x63, 0x25, 0xef, 0xa9, 0xa0, 0xe6, - 0x2c, 0x6a, 0xa5, 0xe3, 0x29, 0x6f, 0xaa, 0xec, 0x26, 0x60, - 0xaf, 0xe9, 0x23, 0x65, 0xb4, 0xf2, 0x38, 0x7e, 0xb1, 0xf7, - 0x3d, 0x7b, 0xbe, 0xf8, 0x32, 0x74, 0xbb, 0xfd, 0x37, 0x71, - 0x88, 0xce, 0x04, 0x42, 0x8d, 0xcb, 0x01, 0x47, 0x82, 0xc4, - 0x0e, 0x48, 0x87, 0xc1, 0x0b, 0x4d, 0x9c, 0xda, 0x10, 0x56, - 0x99, 0xdf, 0x15, 0x53, 0x96, 0xd0, 0x1a, 0x5c, 0x93, 0xd5, - 0x1f, 0x59, 0xf0, 0xb6, 0x7c, 0x3a, 0xf5, 0xb3, 0x79, 0x3f, - 0xfa, 0xbc, 0x76, 0x30, 0xff, 0xb9, 0x73, 0x35, 0xe4, 0xa2, - 0x68, 0x2e, 0xe1, 0xa7, 0x6d, 0x2b, 0xee, 0xa8, 0x62, 0x24, - 0xeb, 0xad, 0x67, 0x21, 0xd8, 0x9e, 0x54, 0x12, 0xdd, 0x9b, - 0x51, 0x17, 0xd2, 0x94, 0x5e, 0x18, 0xd7, 0x91, 0x5b, 0x1d, - 0xcc, 0x8a, 0x40, 0x06, 0xc9, 0x8f, 0x45, 0x03, 0xc6, 0x80, - 0x4a, 0x0c, 0xc3, 0x85, 0x4f, 0x09, 0x00, 0x47, 0x8e, 0xc9, - 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, - 0x8d, 0xca, 0x04, 0x43, 0x8a, 0xcd, 0x05, 0x42, 0x8b, 0xcc, - 0x06, 0x41, 0x88, 0xcf, 0x07, 0x40, 0x89, 0xce, 0x08, 0x4f, - 0x86, 0xc1, 0x09, 0x4e, 0x87, 0xc0, 0x0a, 0x4d, 0x84, 0xc3, - 0x0b, 0x4c, 0x85, 0xc2, 0x0c, 0x4b, 0x82, 0xc5, 0x0d, 0x4a, - 0x83, 0xc4, 0x0e, 0x49, 0x80, 0xc7, 0x0f, 0x48, 0x81, 0xc6, - 0x10, 0x57, 0x9e, 0xd9, 0x11, 0x56, 0x9f, 0xd8, 0x12, 0x55, - 0x9c, 0xdb, 0x13, 0x54, 0x9d, 0xda, 0x14, 0x53, 0x9a, 0xdd, - 0x15, 0x52, 0x9b, 0xdc, 0x16, 0x51, 0x98, 0xdf, 0x17, 0x50, - 0x99, 0xde, 0x18, 0x5f, 0x96, 0xd1, 0x19, 0x5e, 0x97, 0xd0, - 0x1a, 0x5d, 0x94, 0xd3, 0x1b, 0x5c, 0x95, 0xd2, 0x1c, 0x5b, - 0x92, 0xd5, 0x1d, 0x5a, 0x93, 0xd4, 0x1e, 0x59, 0x90, 0xd7, - 0x1f, 0x58, 0x91, 0xd6, 0x20, 0x67, 0xae, 0xe9, 0x21, 0x66, - 0xaf, 0xe8, 0x22, 0x65, 0xac, 0xeb, 0x23, 0x64, 0xad, 0xea, - 0x24, 0x63, 0xaa, 0xed, 0x25, 0x62, 0xab, 0xec, 0x26, 0x61, - 0xa8, 0xef, 0x27, 0x60, 0xa9, 0xee, 0x28, 0x6f, 0xa6, 0xe1, - 0x29, 0x6e, 0xa7, 0xe0, 0x2a, 0x6d, 0xa4, 0xe3, 0x2b, 0x6c, - 0xa5, 0xe2, 0x2c, 0x6b, 0xa2, 0xe5, 0x2d, 0x6a, 0xa3, 0xe4, - 0x2e, 0x69, 0xa0, 0xe7, 0x2f, 0x68, 0xa1, 0xe6, 0x30, 0x77, - 0xbe, 0xf9, 0x31, 0x76, 0xbf, 0xf8, 0x32, 0x75, 0xbc, 0xfb, - 0x33, 0x74, 0xbd, 0xfa, 0x34, 0x73, 0xba, 0xfd, 0x35, 0x72, - 0xbb, 0xfc, 0x36, 0x71, 0xb8, 0xff, 0x37, 0x70, 0xb9, 0xfe, - 0x38, 0x7f, 0xb6, 0xf1, 0x39, 0x7e, 0xb7, 0xf0, 0x3a, 0x7d, - 0xb4, 0xf3, 0x3b, 0x7c, 0xb5, 0xf2, 0x3c, 0x7b, 0xb2, 0xf5, - 0x3d, 0x7a, 0xb3, 0xf4, 0x3e, 0x79, 0xb0, 0xf7, 0x3f, 0x78, - 0xb1, 0xf6, 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, - 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f, 0xf4, 0xbc, - 0x64, 0x2c, 0xc9, 0x81, 0x59, 0x11, 0x8e, 0xc6, 0x1e, 0x56, - 0xb3, 0xfb, 0x23, 0x6b, 0xf5, 0xbd, 0x65, 0x2d, 0xc8, 0x80, - 0x58, 0x10, 0x8f, 0xc7, 0x1f, 0x57, 0xb2, 0xfa, 0x22, 0x6a, - 0x01, 0x49, 0x91, 0xd9, 0x3c, 0x74, 0xac, 0xe4, 0x7b, 0x33, - 0xeb, 0xa3, 0x46, 0x0e, 0xd6, 0x9e, 0xf7, 0xbf, 0x67, 0x2f, - 0xca, 0x82, 0x5a, 0x12, 0x8d, 0xc5, 0x1d, 0x55, 0xb0, 0xf8, - 0x20, 0x68, 0x03, 0x4b, 0x93, 0xdb, 0x3e, 0x76, 0xae, 0xe6, - 0x79, 0x31, 0xe9, 0xa1, 0x44, 0x0c, 0xd4, 0x9c, 0x02, 0x4a, - 0x92, 0xda, 0x3f, 0x77, 0xaf, 0xe7, 0x78, 0x30, 0xe8, 0xa0, - 0x45, 0x0d, 0xd5, 0x9d, 0xf6, 0xbe, 0x66, 0x2e, 0xcb, 0x83, - 0x5b, 0x13, 0x8c, 0xc4, 0x1c, 0x54, 0xb1, 0xf9, 0x21, 0x69, - 0xf3, 0xbb, 0x63, 0x2b, 0xce, 0x86, 0x5e, 0x16, 0x89, 0xc1, - 0x19, 0x51, 0xb4, 0xfc, 0x24, 0x6c, 0x07, 0x4f, 0x97, 0xdf, - 0x3a, 0x72, 0xaa, 0xe2, 0x7d, 0x35, 0xed, 0xa5, 0x40, 0x08, - 0xd0, 0x98, 0x06, 0x4e, 0x96, 0xde, 0x3b, 0x73, 0xab, 0xe3, - 0x7c, 0x34, 0xec, 0xa4, 0x41, 0x09, 0xd1, 0x99, 0xf2, 0xba, - 0x62, 0x2a, 0xcf, 0x87, 0x5f, 0x17, 0x88, 0xc0, 0x18, 0x50, - 0xb5, 0xfd, 0x25, 0x6d, 0x04, 0x4c, 0x94, 0xdc, 0x39, 0x71, - 0xa9, 0xe1, 0x7e, 0x36, 0xee, 0xa6, 0x43, 0x0b, 0xd3, 0x9b, - 0xf0, 0xb8, 0x60, 0x28, 0xcd, 0x85, 0x5d, 0x15, 0x8a, 0xc2, - 0x1a, 0x52, 0xb7, 0xff, 0x27, 0x6f, 0xf1, 0xb9, 0x61, 0x29, - 0xcc, 0x84, 0x5c, 0x14, 0x8b, 0xc3, 0x1b, 0x53, 0xb6, 0xfe, - 0x26, 0x6e, 0x05, 0x4d, 0x95, 0xdd, 0x38, 0x70, 0xa8, 0xe0, - 0x7f, 0x37, 0xef, 0xa7, 0x42, 0x0a, 0xd2, 0x9a, 0x00, 0x49, - 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, - 0x4b, 0x02, 0xd9, 0x90, 0xe4, 0xad, 0x76, 0x3f, 0xdd, 0x94, - 0x4f, 0x06, 0x96, 0xdf, 0x04, 0x4d, 0xaf, 0xe6, 0x3d, 0x74, - 0xd5, 0x9c, 0x47, 0x0e, 0xec, 0xa5, 0x7e, 0x37, 0xa7, 0xee, - 0x35, 0x7c, 0x9e, 0xd7, 0x0c, 0x45, 0x31, 0x78, 0xa3, 0xea, - 0x08, 0x41, 0x9a, 0xd3, 0x43, 0x0a, 0xd1, 0x98, 0x7a, 0x33, - 0xe8, 0xa1, 0xb7, 0xfe, 0x25, 0x6c, 0x8e, 0xc7, 0x1c, 0x55, - 0xc5, 0x8c, 0x57, 0x1e, 0xfc, 0xb5, 0x6e, 0x27, 0x53, 0x1a, - 0xc1, 0x88, 0x6a, 0x23, 0xf8, 0xb1, 0x21, 0x68, 0xb3, 0xfa, - 0x18, 0x51, 0x8a, 0xc3, 0x62, 0x2b, 0xf0, 0xb9, 0x5b, 0x12, - 0xc9, 0x80, 0x10, 0x59, 0x82, 0xcb, 0x29, 0x60, 0xbb, 0xf2, - 0x86, 0xcf, 0x14, 0x5d, 0xbf, 0xf6, 0x2d, 0x64, 0xf4, 0xbd, - 0x66, 0x2f, 0xcd, 0x84, 0x5f, 0x16, 0x73, 0x3a, 0xe1, 0xa8, - 0x4a, 0x03, 0xd8, 0x91, 0x01, 0x48, 0x93, 0xda, 0x38, 0x71, - 0xaa, 0xe3, 0x97, 0xde, 0x05, 0x4c, 0xae, 0xe7, 0x3c, 0x75, - 0xe5, 0xac, 0x77, 0x3e, 0xdc, 0x95, 0x4e, 0x07, 0xa6, 0xef, - 0x34, 0x7d, 0x9f, 0xd6, 0x0d, 0x44, 0xd4, 0x9d, 0x46, 0x0f, - 0xed, 0xa4, 0x7f, 0x36, 0x42, 0x0b, 0xd0, 0x99, 0x7b, 0x32, - 0xe9, 0xa0, 0x30, 0x79, 0xa2, 0xeb, 0x09, 0x40, 0x9b, 0xd2, - 0xc4, 0x8d, 0x56, 0x1f, 0xfd, 0xb4, 0x6f, 0x26, 0xb6, 0xff, - 0x24, 0x6d, 0x8f, 0xc6, 0x1d, 0x54, 0x20, 0x69, 0xb2, 0xfb, - 0x19, 0x50, 0x8b, 0xc2, 0x52, 0x1b, 0xc0, 0x89, 0x6b, 0x22, - 0xf9, 0xb0, 0x11, 0x58, 0x83, 0xca, 0x28, 0x61, 0xba, 0xf3, - 0x63, 0x2a, 0xf1, 0xb8, 0x5a, 0x13, 0xc8, 0x81, 0xf5, 0xbc, - 0x67, 0x2e, 0xcc, 0x85, 0x5e, 0x17, 0x87, 0xce, 0x15, 0x5c, - 0xbe, 0xf7, 0x2c, 0x65, 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, - 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81, - 0xd4, 0x9e, 0x40, 0x0a, 0xe1, 0xab, 0x75, 0x3f, 0xbe, 0xf4, - 0x2a, 0x60, 0x8b, 0xc1, 0x1f, 0x55, 0xb5, 0xff, 0x21, 0x6b, - 0x80, 0xca, 0x14, 0x5e, 0xdf, 0x95, 0x4b, 0x01, 0xea, 0xa0, - 0x7e, 0x34, 0x61, 0x2b, 0xf5, 0xbf, 0x54, 0x1e, 0xc0, 0x8a, - 0x0b, 0x41, 0x9f, 0xd5, 0x3e, 0x74, 0xaa, 0xe0, 0x77, 0x3d, - 0xe3, 0xa9, 0x42, 0x08, 0xd6, 0x9c, 0x1d, 0x57, 0x89, 0xc3, - 0x28, 0x62, 0xbc, 0xf6, 0xa3, 0xe9, 0x37, 0x7d, 0x96, 0xdc, - 0x02, 0x48, 0xc9, 0x83, 0x5d, 0x17, 0xfc, 0xb6, 0x68, 0x22, - 0xc2, 0x88, 0x56, 0x1c, 0xf7, 0xbd, 0x63, 0x29, 0xa8, 0xe2, - 0x3c, 0x76, 0x9d, 0xd7, 0x09, 0x43, 0x16, 0x5c, 0x82, 0xc8, - 0x23, 0x69, 0xb7, 0xfd, 0x7c, 0x36, 0xe8, 0xa2, 0x49, 0x03, - 0xdd, 0x97, 0xee, 0xa4, 0x7a, 0x30, 0xdb, 0x91, 0x4f, 0x05, - 0x84, 0xce, 0x10, 0x5a, 0xb1, 0xfb, 0x25, 0x6f, 0x3a, 0x70, - 0xae, 0xe4, 0x0f, 0x45, 0x9b, 0xd1, 0x50, 0x1a, 0xc4, 0x8e, - 0x65, 0x2f, 0xf1, 0xbb, 0x5b, 0x11, 0xcf, 0x85, 0x6e, 0x24, - 0xfa, 0xb0, 0x31, 0x7b, 0xa5, 0xef, 0x04, 0x4e, 0x90, 0xda, - 0x8f, 0xc5, 0x1b, 0x51, 0xba, 0xf0, 0x2e, 0x64, 0xe5, 0xaf, - 0x71, 0x3b, 0xd0, 0x9a, 0x44, 0x0e, 0x99, 0xd3, 0x0d, 0x47, - 0xac, 0xe6, 0x38, 0x72, 0xf3, 0xb9, 0x67, 0x2d, 0xc6, 0x8c, - 0x52, 0x18, 0x4d, 0x07, 0xd9, 0x93, 0x78, 0x32, 0xec, 0xa6, - 0x27, 0x6d, 0xb3, 0xf9, 0x12, 0x58, 0x86, 0xcc, 0x2c, 0x66, - 0xb8, 0xf2, 0x19, 0x53, 0x8d, 0xc7, 0x46, 0x0c, 0xd2, 0x98, - 0x73, 0x39, 0xe7, 0xad, 0xf8, 0xb2, 0x6c, 0x26, 0xcd, 0x87, - 0x59, 0x13, 0x92, 0xd8, 0x06, 0x4c, 0xa7, 0xed, 0x33, 0x79, - 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, - 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e, 0xc4, 0x8f, 0x52, 0x19, - 0xf5, 0xbe, 0x63, 0x28, 0xa6, 0xed, 0x30, 0x7b, 0x97, 0xdc, - 0x01, 0x4a, 0x95, 0xde, 0x03, 0x48, 0xa4, 0xef, 0x32, 0x79, - 0xf7, 0xbc, 0x61, 0x2a, 0xc6, 0x8d, 0x50, 0x1b, 0x51, 0x1a, - 0xc7, 0x8c, 0x60, 0x2b, 0xf6, 0xbd, 0x33, 0x78, 0xa5, 0xee, - 0x02, 0x49, 0x94, 0xdf, 0x37, 0x7c, 0xa1, 0xea, 0x06, 0x4d, - 0x90, 0xdb, 0x55, 0x1e, 0xc3, 0x88, 0x64, 0x2f, 0xf2, 0xb9, - 0xf3, 0xb8, 0x65, 0x2e, 0xc2, 0x89, 0x54, 0x1f, 0x91, 0xda, - 0x07, 0x4c, 0xa0, 0xeb, 0x36, 0x7d, 0xa2, 0xe9, 0x34, 0x7f, - 0x93, 0xd8, 0x05, 0x4e, 0xc0, 0x8b, 0x56, 0x1d, 0xf1, 0xba, - 0x67, 0x2c, 0x66, 0x2d, 0xf0, 0xbb, 0x57, 0x1c, 0xc1, 0x8a, - 0x04, 0x4f, 0x92, 0xd9, 0x35, 0x7e, 0xa3, 0xe8, 0x6e, 0x25, - 0xf8, 0xb3, 0x5f, 0x14, 0xc9, 0x82, 0x0c, 0x47, 0x9a, 0xd1, - 0x3d, 0x76, 0xab, 0xe0, 0xaa, 0xe1, 0x3c, 0x77, 0x9b, 0xd0, - 0x0d, 0x46, 0xc8, 0x83, 0x5e, 0x15, 0xf9, 0xb2, 0x6f, 0x24, - 0xfb, 0xb0, 0x6d, 0x26, 0xca, 0x81, 0x5c, 0x17, 0x99, 0xd2, - 0x0f, 0x44, 0xa8, 0xe3, 0x3e, 0x75, 0x3f, 0x74, 0xa9, 0xe2, - 0x0e, 0x45, 0x98, 0xd3, 0x5d, 0x16, 0xcb, 0x80, 0x6c, 0x27, - 0xfa, 0xb1, 0x59, 0x12, 0xcf, 0x84, 0x68, 0x23, 0xfe, 0xb5, - 0x3b, 0x70, 0xad, 0xe6, 0x0a, 0x41, 0x9c, 0xd7, 0x9d, 0xd6, - 0x0b, 0x40, 0xac, 0xe7, 0x3a, 0x71, 0xff, 0xb4, 0x69, 0x22, - 0xce, 0x85, 0x58, 0x13, 0xcc, 0x87, 0x5a, 0x11, 0xfd, 0xb6, - 0x6b, 0x20, 0xae, 0xe5, 0x38, 0x73, 0x9f, 0xd4, 0x09, 0x42, - 0x08, 0x43, 0x9e, 0xd5, 0x39, 0x72, 0xaf, 0xe4, 0x6a, 0x21, - 0xfc, 0xb7, 0x5b, 0x10, 0xcd, 0x86, 0x00, 0x4c, 0x98, 0xd4, - 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, - 0xef, 0xa3, 0xb4, 0xf8, 0x2c, 0x60, 0x99, 0xd5, 0x01, 0x4d, - 0xee, 0xa2, 0x76, 0x3a, 0xc3, 0x8f, 0x5b, 0x17, 0x75, 0x39, - 0xed, 0xa1, 0x58, 0x14, 0xc0, 0x8c, 0x2f, 0x63, 0xb7, 0xfb, - 0x02, 0x4e, 0x9a, 0xd6, 0xc1, 0x8d, 0x59, 0x15, 0xec, 0xa0, - 0x74, 0x38, 0x9b, 0xd7, 0x03, 0x4f, 0xb6, 0xfa, 0x2e, 0x62, - 0xea, 0xa6, 0x72, 0x3e, 0xc7, 0x8b, 0x5f, 0x13, 0xb0, 0xfc, - 0x28, 0x64, 0x9d, 0xd1, 0x05, 0x49, 0x5e, 0x12, 0xc6, 0x8a, - 0x73, 0x3f, 0xeb, 0xa7, 0x04, 0x48, 0x9c, 0xd0, 0x29, 0x65, - 0xb1, 0xfd, 0x9f, 0xd3, 0x07, 0x4b, 0xb2, 0xfe, 0x2a, 0x66, - 0xc5, 0x89, 0x5d, 0x11, 0xe8, 0xa4, 0x70, 0x3c, 0x2b, 0x67, - 0xb3, 0xff, 0x06, 0x4a, 0x9e, 0xd2, 0x71, 0x3d, 0xe9, 0xa5, - 0x5c, 0x10, 0xc4, 0x88, 0xc9, 0x85, 0x51, 0x1d, 0xe4, 0xa8, - 0x7c, 0x30, 0x93, 0xdf, 0x0b, 0x47, 0xbe, 0xf2, 0x26, 0x6a, - 0x7d, 0x31, 0xe5, 0xa9, 0x50, 0x1c, 0xc8, 0x84, 0x27, 0x6b, - 0xbf, 0xf3, 0x0a, 0x46, 0x92, 0xde, 0xbc, 0xf0, 0x24, 0x68, - 0x91, 0xdd, 0x09, 0x45, 0xe6, 0xaa, 0x7e, 0x32, 0xcb, 0x87, - 0x53, 0x1f, 0x08, 0x44, 0x90, 0xdc, 0x25, 0x69, 0xbd, 0xf1, - 0x52, 0x1e, 0xca, 0x86, 0x7f, 0x33, 0xe7, 0xab, 0x23, 0x6f, - 0xbb, 0xf7, 0x0e, 0x42, 0x96, 0xda, 0x79, 0x35, 0xe1, 0xad, - 0x54, 0x18, 0xcc, 0x80, 0x97, 0xdb, 0x0f, 0x43, 0xba, 0xf6, - 0x22, 0x6e, 0xcd, 0x81, 0x55, 0x19, 0xe0, 0xac, 0x78, 0x34, - 0x56, 0x1a, 0xce, 0x82, 0x7b, 0x37, 0xe3, 0xaf, 0x0c, 0x40, - 0x94, 0xd8, 0x21, 0x6d, 0xb9, 0xf5, 0xe2, 0xae, 0x7a, 0x36, - 0xcf, 0x83, 0x57, 0x1b, 0xb8, 0xf4, 0x20, 0x6c, 0x95, 0xd9, - 0x0d, 0x41, 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, - 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac, 0xa4, 0xe9, - 0x3e, 0x73, 0x8d, 0xc0, 0x17, 0x5a, 0xf6, 0xbb, 0x6c, 0x21, - 0xdf, 0x92, 0x45, 0x08, 0x55, 0x18, 0xcf, 0x82, 0x7c, 0x31, - 0xe6, 0xab, 0x07, 0x4a, 0x9d, 0xd0, 0x2e, 0x63, 0xb4, 0xf9, - 0xf1, 0xbc, 0x6b, 0x26, 0xd8, 0x95, 0x42, 0x0f, 0xa3, 0xee, - 0x39, 0x74, 0x8a, 0xc7, 0x10, 0x5d, 0xaa, 0xe7, 0x30, 0x7d, - 0x83, 0xce, 0x19, 0x54, 0xf8, 0xb5, 0x62, 0x2f, 0xd1, 0x9c, - 0x4b, 0x06, 0x0e, 0x43, 0x94, 0xd9, 0x27, 0x6a, 0xbd, 0xf0, - 0x5c, 0x11, 0xc6, 0x8b, 0x75, 0x38, 0xef, 0xa2, 0xff, 0xb2, - 0x65, 0x28, 0xd6, 0x9b, 0x4c, 0x01, 0xad, 0xe0, 0x37, 0x7a, - 0x84, 0xc9, 0x1e, 0x53, 0x5b, 0x16, 0xc1, 0x8c, 0x72, 0x3f, - 0xe8, 0xa5, 0x09, 0x44, 0x93, 0xde, 0x20, 0x6d, 0xba, 0xf7, - 0x49, 0x04, 0xd3, 0x9e, 0x60, 0x2d, 0xfa, 0xb7, 0x1b, 0x56, - 0x81, 0xcc, 0x32, 0x7f, 0xa8, 0xe5, 0xed, 0xa0, 0x77, 0x3a, - 0xc4, 0x89, 0x5e, 0x13, 0xbf, 0xf2, 0x25, 0x68, 0x96, 0xdb, - 0x0c, 0x41, 0x1c, 0x51, 0x86, 0xcb, 0x35, 0x78, 0xaf, 0xe2, - 0x4e, 0x03, 0xd4, 0x99, 0x67, 0x2a, 0xfd, 0xb0, 0xb8, 0xf5, - 0x22, 0x6f, 0x91, 0xdc, 0x0b, 0x46, 0xea, 0xa7, 0x70, 0x3d, - 0xc3, 0x8e, 0x59, 0x14, 0xe3, 0xae, 0x79, 0x34, 0xca, 0x87, - 0x50, 0x1d, 0xb1, 0xfc, 0x2b, 0x66, 0x98, 0xd5, 0x02, 0x4f, - 0x47, 0x0a, 0xdd, 0x90, 0x6e, 0x23, 0xf4, 0xb9, 0x15, 0x58, - 0x8f, 0xc2, 0x3c, 0x71, 0xa6, 0xeb, 0xb6, 0xfb, 0x2c, 0x61, - 0x9f, 0xd2, 0x05, 0x48, 0xe4, 0xa9, 0x7e, 0x33, 0xcd, 0x80, - 0x57, 0x1a, 0x12, 0x5f, 0x88, 0xc5, 0x3b, 0x76, 0xa1, 0xec, - 0x40, 0x0d, 0xda, 0x97, 0x69, 0x24, 0xf3, 0xbe, 0x00, 0x4e, - 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, - 0x6f, 0x21, 0xf3, 0xbd, 0x94, 0xda, 0x08, 0x46, 0xb1, 0xff, - 0x2d, 0x63, 0xde, 0x90, 0x42, 0x0c, 0xfb, 0xb5, 0x67, 0x29, - 0x35, 0x7b, 0xa9, 0xe7, 0x10, 0x5e, 0x8c, 0xc2, 0x7f, 0x31, - 0xe3, 0xad, 0x5a, 0x14, 0xc6, 0x88, 0xa1, 0xef, 0x3d, 0x73, - 0x84, 0xca, 0x18, 0x56, 0xeb, 0xa5, 0x77, 0x39, 0xce, 0x80, - 0x52, 0x1c, 0x6a, 0x24, 0xf6, 0xb8, 0x4f, 0x01, 0xd3, 0x9d, - 0x20, 0x6e, 0xbc, 0xf2, 0x05, 0x4b, 0x99, 0xd7, 0xfe, 0xb0, - 0x62, 0x2c, 0xdb, 0x95, 0x47, 0x09, 0xb4, 0xfa, 0x28, 0x66, - 0x91, 0xdf, 0x0d, 0x43, 0x5f, 0x11, 0xc3, 0x8d, 0x7a, 0x34, - 0xe6, 0xa8, 0x15, 0x5b, 0x89, 0xc7, 0x30, 0x7e, 0xac, 0xe2, - 0xcb, 0x85, 0x57, 0x19, 0xee, 0xa0, 0x72, 0x3c, 0x81, 0xcf, - 0x1d, 0x53, 0xa4, 0xea, 0x38, 0x76, 0xd4, 0x9a, 0x48, 0x06, - 0xf1, 0xbf, 0x6d, 0x23, 0x9e, 0xd0, 0x02, 0x4c, 0xbb, 0xf5, - 0x27, 0x69, 0x40, 0x0e, 0xdc, 0x92, 0x65, 0x2b, 0xf9, 0xb7, - 0x0a, 0x44, 0x96, 0xd8, 0x2f, 0x61, 0xb3, 0xfd, 0xe1, 0xaf, - 0x7d, 0x33, 0xc4, 0x8a, 0x58, 0x16, 0xab, 0xe5, 0x37, 0x79, - 0x8e, 0xc0, 0x12, 0x5c, 0x75, 0x3b, 0xe9, 0xa7, 0x50, 0x1e, - 0xcc, 0x82, 0x3f, 0x71, 0xa3, 0xed, 0x1a, 0x54, 0x86, 0xc8, - 0xbe, 0xf0, 0x22, 0x6c, 0x9b, 0xd5, 0x07, 0x49, 0xf4, 0xba, - 0x68, 0x26, 0xd1, 0x9f, 0x4d, 0x03, 0x2a, 0x64, 0xb6, 0xf8, - 0x0f, 0x41, 0x93, 0xdd, 0x60, 0x2e, 0xfc, 0xb2, 0x45, 0x0b, - 0xd9, 0x97, 0x8b, 0xc5, 0x17, 0x59, 0xae, 0xe0, 0x32, 0x7c, - 0xc1, 0x8f, 0x5d, 0x13, 0xe4, 0xaa, 0x78, 0x36, 0x1f, 0x51, - 0x83, 0xcd, 0x3a, 0x74, 0xa6, 0xe8, 0x55, 0x1b, 0xc9, 0x87, - 0x70, 0x3e, 0xec, 0xa2, 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, - 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2, - 0x84, 0xcb, 0x1a, 0x55, 0xa5, 0xea, 0x3b, 0x74, 0xc6, 0x89, - 0x58, 0x17, 0xe7, 0xa8, 0x79, 0x36, 0x15, 0x5a, 0x8b, 0xc4, - 0x34, 0x7b, 0xaa, 0xe5, 0x57, 0x18, 0xc9, 0x86, 0x76, 0x39, - 0xe8, 0xa7, 0x91, 0xde, 0x0f, 0x40, 0xb0, 0xff, 0x2e, 0x61, - 0xd3, 0x9c, 0x4d, 0x02, 0xf2, 0xbd, 0x6c, 0x23, 0x2a, 0x65, - 0xb4, 0xfb, 0x0b, 0x44, 0x95, 0xda, 0x68, 0x27, 0xf6, 0xb9, - 0x49, 0x06, 0xd7, 0x98, 0xae, 0xe1, 0x30, 0x7f, 0x8f, 0xc0, - 0x11, 0x5e, 0xec, 0xa3, 0x72, 0x3d, 0xcd, 0x82, 0x53, 0x1c, - 0x3f, 0x70, 0xa1, 0xee, 0x1e, 0x51, 0x80, 0xcf, 0x7d, 0x32, - 0xe3, 0xac, 0x5c, 0x13, 0xc2, 0x8d, 0xbb, 0xf4, 0x25, 0x6a, - 0x9a, 0xd5, 0x04, 0x4b, 0xf9, 0xb6, 0x67, 0x28, 0xd8, 0x97, - 0x46, 0x09, 0x54, 0x1b, 0xca, 0x85, 0x75, 0x3a, 0xeb, 0xa4, - 0x16, 0x59, 0x88, 0xc7, 0x37, 0x78, 0xa9, 0xe6, 0xd0, 0x9f, - 0x4e, 0x01, 0xf1, 0xbe, 0x6f, 0x20, 0x92, 0xdd, 0x0c, 0x43, - 0xb3, 0xfc, 0x2d, 0x62, 0x41, 0x0e, 0xdf, 0x90, 0x60, 0x2f, - 0xfe, 0xb1, 0x03, 0x4c, 0x9d, 0xd2, 0x22, 0x6d, 0xbc, 0xf3, - 0xc5, 0x8a, 0x5b, 0x14, 0xe4, 0xab, 0x7a, 0x35, 0x87, 0xc8, - 0x19, 0x56, 0xa6, 0xe9, 0x38, 0x77, 0x7e, 0x31, 0xe0, 0xaf, - 0x5f, 0x10, 0xc1, 0x8e, 0x3c, 0x73, 0xa2, 0xed, 0x1d, 0x52, - 0x83, 0xcc, 0xfa, 0xb5, 0x64, 0x2b, 0xdb, 0x94, 0x45, 0x0a, - 0xb8, 0xf7, 0x26, 0x69, 0x99, 0xd6, 0x07, 0x48, 0x6b, 0x24, - 0xf5, 0xba, 0x4a, 0x05, 0xd4, 0x9b, 0x29, 0x66, 0xb7, 0xf8, - 0x08, 0x47, 0x96, 0xd9, 0xef, 0xa0, 0x71, 0x3e, 0xce, 0x81, - 0x50, 0x1f, 0xad, 0xe2, 0x33, 0x7c, 0x8c, 0xc3, 0x12, 0x5d, - 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, - 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17, 0x69, 0x39, 0xc9, 0x99, - 0x34, 0x64, 0x94, 0xc4, 0xd3, 0x83, 0x73, 0x23, 0x8e, 0xde, - 0x2e, 0x7e, 0xd2, 0x82, 0x72, 0x22, 0x8f, 0xdf, 0x2f, 0x7f, - 0x68, 0x38, 0xc8, 0x98, 0x35, 0x65, 0x95, 0xc5, 0xbb, 0xeb, - 0x1b, 0x4b, 0xe6, 0xb6, 0x46, 0x16, 0x01, 0x51, 0xa1, 0xf1, - 0x5c, 0x0c, 0xfc, 0xac, 0xb9, 0xe9, 0x19, 0x49, 0xe4, 0xb4, - 0x44, 0x14, 0x03, 0x53, 0xa3, 0xf3, 0x5e, 0x0e, 0xfe, 0xae, - 0xd0, 0x80, 0x70, 0x20, 0x8d, 0xdd, 0x2d, 0x7d, 0x6a, 0x3a, - 0xca, 0x9a, 0x37, 0x67, 0x97, 0xc7, 0x6b, 0x3b, 0xcb, 0x9b, - 0x36, 0x66, 0x96, 0xc6, 0xd1, 0x81, 0x71, 0x21, 0x8c, 0xdc, - 0x2c, 0x7c, 0x02, 0x52, 0xa2, 0xf2, 0x5f, 0x0f, 0xff, 0xaf, - 0xb8, 0xe8, 0x18, 0x48, 0xe5, 0xb5, 0x45, 0x15, 0x6f, 0x3f, - 0xcf, 0x9f, 0x32, 0x62, 0x92, 0xc2, 0xd5, 0x85, 0x75, 0x25, - 0x88, 0xd8, 0x28, 0x78, 0x06, 0x56, 0xa6, 0xf6, 0x5b, 0x0b, - 0xfb, 0xab, 0xbc, 0xec, 0x1c, 0x4c, 0xe1, 0xb1, 0x41, 0x11, - 0xbd, 0xed, 0x1d, 0x4d, 0xe0, 0xb0, 0x40, 0x10, 0x07, 0x57, - 0xa7, 0xf7, 0x5a, 0x0a, 0xfa, 0xaa, 0xd4, 0x84, 0x74, 0x24, - 0x89, 0xd9, 0x29, 0x79, 0x6e, 0x3e, 0xce, 0x9e, 0x33, 0x63, - 0x93, 0xc3, 0xd6, 0x86, 0x76, 0x26, 0x8b, 0xdb, 0x2b, 0x7b, - 0x6c, 0x3c, 0xcc, 0x9c, 0x31, 0x61, 0x91, 0xc1, 0xbf, 0xef, - 0x1f, 0x4f, 0xe2, 0xb2, 0x42, 0x12, 0x05, 0x55, 0xa5, 0xf5, - 0x58, 0x08, 0xf8, 0xa8, 0x04, 0x54, 0xa4, 0xf4, 0x59, 0x09, - 0xf9, 0xa9, 0xbe, 0xee, 0x1e, 0x4e, 0xe3, 0xb3, 0x43, 0x13, - 0x6d, 0x3d, 0xcd, 0x9d, 0x30, 0x60, 0x90, 0xc0, 0xd7, 0x87, - 0x77, 0x27, 0x8a, 0xda, 0x2a, 0x7a, 0x00, 0x51, 0xa2, 0xf3, - 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, - 0x49, 0x18, 0x79, 0x28, 0xdb, 0x8a, 0x20, 0x71, 0x82, 0xd3, - 0xcb, 0x9a, 0x69, 0x38, 0x92, 0xc3, 0x30, 0x61, 0xf2, 0xa3, - 0x50, 0x01, 0xab, 0xfa, 0x09, 0x58, 0x40, 0x11, 0xe2, 0xb3, - 0x19, 0x48, 0xbb, 0xea, 0x8b, 0xda, 0x29, 0x78, 0xd2, 0x83, - 0x70, 0x21, 0x39, 0x68, 0x9b, 0xca, 0x60, 0x31, 0xc2, 0x93, - 0xf9, 0xa8, 0x5b, 0x0a, 0xa0, 0xf1, 0x02, 0x53, 0x4b, 0x1a, - 0xe9, 0xb8, 0x12, 0x43, 0xb0, 0xe1, 0x80, 0xd1, 0x22, 0x73, - 0xd9, 0x88, 0x7b, 0x2a, 0x32, 0x63, 0x90, 0xc1, 0x6b, 0x3a, - 0xc9, 0x98, 0x0b, 0x5a, 0xa9, 0xf8, 0x52, 0x03, 0xf0, 0xa1, - 0xb9, 0xe8, 0x1b, 0x4a, 0xe0, 0xb1, 0x42, 0x13, 0x72, 0x23, - 0xd0, 0x81, 0x2b, 0x7a, 0x89, 0xd8, 0xc0, 0x91, 0x62, 0x33, - 0x99, 0xc8, 0x3b, 0x6a, 0xef, 0xbe, 0x4d, 0x1c, 0xb6, 0xe7, - 0x14, 0x45, 0x5d, 0x0c, 0xff, 0xae, 0x04, 0x55, 0xa6, 0xf7, - 0x96, 0xc7, 0x34, 0x65, 0xcf, 0x9e, 0x6d, 0x3c, 0x24, 0x75, - 0x86, 0xd7, 0x7d, 0x2c, 0xdf, 0x8e, 0x1d, 0x4c, 0xbf, 0xee, - 0x44, 0x15, 0xe6, 0xb7, 0xaf, 0xfe, 0x0d, 0x5c, 0xf6, 0xa7, - 0x54, 0x05, 0x64, 0x35, 0xc6, 0x97, 0x3d, 0x6c, 0x9f, 0xce, - 0xd6, 0x87, 0x74, 0x25, 0x8f, 0xde, 0x2d, 0x7c, 0x16, 0x47, - 0xb4, 0xe5, 0x4f, 0x1e, 0xed, 0xbc, 0xa4, 0xf5, 0x06, 0x57, - 0xfd, 0xac, 0x5f, 0x0e, 0x6f, 0x3e, 0xcd, 0x9c, 0x36, 0x67, - 0x94, 0xc5, 0xdd, 0x8c, 0x7f, 0x2e, 0x84, 0xd5, 0x26, 0x77, - 0xe4, 0xb5, 0x46, 0x17, 0xbd, 0xec, 0x1f, 0x4e, 0x56, 0x07, - 0xf4, 0xa5, 0x0f, 0x5e, 0xad, 0xfc, 0x9d, 0xcc, 0x3f, 0x6e, - 0xc4, 0x95, 0x66, 0x37, 0x2f, 0x7e, 0x8d, 0xdc, 0x76, 0x27, - 0xd4, 0x85, 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, - 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09, 0x49, 0x1b, - 0xed, 0xbf, 0x1c, 0x4e, 0xb8, 0xea, 0xe3, 0xb1, 0x47, 0x15, - 0xb6, 0xe4, 0x12, 0x40, 0x92, 0xc0, 0x36, 0x64, 0xc7, 0x95, - 0x63, 0x31, 0x38, 0x6a, 0x9c, 0xce, 0x6d, 0x3f, 0xc9, 0x9b, - 0xdb, 0x89, 0x7f, 0x2d, 0x8e, 0xdc, 0x2a, 0x78, 0x71, 0x23, - 0xd5, 0x87, 0x24, 0x76, 0x80, 0xd2, 0x39, 0x6b, 0x9d, 0xcf, - 0x6c, 0x3e, 0xc8, 0x9a, 0x93, 0xc1, 0x37, 0x65, 0xc6, 0x94, - 0x62, 0x30, 0x70, 0x22, 0xd4, 0x86, 0x25, 0x77, 0x81, 0xd3, - 0xda, 0x88, 0x7e, 0x2c, 0x8f, 0xdd, 0x2b, 0x79, 0xab, 0xf9, - 0x0f, 0x5d, 0xfe, 0xac, 0x5a, 0x08, 0x01, 0x53, 0xa5, 0xf7, - 0x54, 0x06, 0xf0, 0xa2, 0xe2, 0xb0, 0x46, 0x14, 0xb7, 0xe5, - 0x13, 0x41, 0x48, 0x1a, 0xec, 0xbe, 0x1d, 0x4f, 0xb9, 0xeb, - 0x72, 0x20, 0xd6, 0x84, 0x27, 0x75, 0x83, 0xd1, 0xd8, 0x8a, - 0x7c, 0x2e, 0x8d, 0xdf, 0x29, 0x7b, 0x3b, 0x69, 0x9f, 0xcd, - 0x6e, 0x3c, 0xca, 0x98, 0x91, 0xc3, 0x35, 0x67, 0xc4, 0x96, - 0x60, 0x32, 0xe0, 0xb2, 0x44, 0x16, 0xb5, 0xe7, 0x11, 0x43, - 0x4a, 0x18, 0xee, 0xbc, 0x1f, 0x4d, 0xbb, 0xe9, 0xa9, 0xfb, - 0x0d, 0x5f, 0xfc, 0xae, 0x58, 0x0a, 0x03, 0x51, 0xa7, 0xf5, - 0x56, 0x04, 0xf2, 0xa0, 0x4b, 0x19, 0xef, 0xbd, 0x1e, 0x4c, - 0xba, 0xe8, 0xe1, 0xb3, 0x45, 0x17, 0xb4, 0xe6, 0x10, 0x42, - 0x02, 0x50, 0xa6, 0xf4, 0x57, 0x05, 0xf3, 0xa1, 0xa8, 0xfa, - 0x0c, 0x5e, 0xfd, 0xaf, 0x59, 0x0b, 0xd9, 0x8b, 0x7d, 0x2f, - 0x8c, 0xde, 0x28, 0x7a, 0x73, 0x21, 0xd7, 0x85, 0x26, 0x74, - 0x82, 0xd0, 0x90, 0xc2, 0x34, 0x66, 0xc5, 0x97, 0x61, 0x33, - 0x3a, 0x68, 0x9e, 0xcc, 0x6f, 0x3d, 0xcb, 0x99, 0x00, 0x53, - 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, - 0xf3, 0xa0, 0x55, 0x06, 0x59, 0x0a, 0xff, 0xac, 0x08, 0x5b, - 0xae, 0xfd, 0xfb, 0xa8, 0x5d, 0x0e, 0xaa, 0xf9, 0x0c, 0x5f, - 0xb2, 0xe1, 0x14, 0x47, 0xe3, 0xb0, 0x45, 0x16, 0x10, 0x43, - 0xb6, 0xe5, 0x41, 0x12, 0xe7, 0xb4, 0xeb, 0xb8, 0x4d, 0x1e, - 0xba, 0xe9, 0x1c, 0x4f, 0x49, 0x1a, 0xef, 0xbc, 0x18, 0x4b, - 0xbe, 0xed, 0x79, 0x2a, 0xdf, 0x8c, 0x28, 0x7b, 0x8e, 0xdd, - 0xdb, 0x88, 0x7d, 0x2e, 0x8a, 0xd9, 0x2c, 0x7f, 0x20, 0x73, - 0x86, 0xd5, 0x71, 0x22, 0xd7, 0x84, 0x82, 0xd1, 0x24, 0x77, - 0xd3, 0x80, 0x75, 0x26, 0xcb, 0x98, 0x6d, 0x3e, 0x9a, 0xc9, - 0x3c, 0x6f, 0x69, 0x3a, 0xcf, 0x9c, 0x38, 0x6b, 0x9e, 0xcd, - 0x92, 0xc1, 0x34, 0x67, 0xc3, 0x90, 0x65, 0x36, 0x30, 0x63, - 0x96, 0xc5, 0x61, 0x32, 0xc7, 0x94, 0xf2, 0xa1, 0x54, 0x07, - 0xa3, 0xf0, 0x05, 0x56, 0x50, 0x03, 0xf6, 0xa5, 0x01, 0x52, - 0xa7, 0xf4, 0xab, 0xf8, 0x0d, 0x5e, 0xfa, 0xa9, 0x5c, 0x0f, - 0x09, 0x5a, 0xaf, 0xfc, 0x58, 0x0b, 0xfe, 0xad, 0x40, 0x13, - 0xe6, 0xb5, 0x11, 0x42, 0xb7, 0xe4, 0xe2, 0xb1, 0x44, 0x17, - 0xb3, 0xe0, 0x15, 0x46, 0x19, 0x4a, 0xbf, 0xec, 0x48, 0x1b, - 0xee, 0xbd, 0xbb, 0xe8, 0x1d, 0x4e, 0xea, 0xb9, 0x4c, 0x1f, - 0x8b, 0xd8, 0x2d, 0x7e, 0xda, 0x89, 0x7c, 0x2f, 0x29, 0x7a, - 0x8f, 0xdc, 0x78, 0x2b, 0xde, 0x8d, 0xd2, 0x81, 0x74, 0x27, - 0x83, 0xd0, 0x25, 0x76, 0x70, 0x23, 0xd6, 0x85, 0x21, 0x72, - 0x87, 0xd4, 0x39, 0x6a, 0x9f, 0xcc, 0x68, 0x3b, 0xce, 0x9d, - 0x9b, 0xc8, 0x3d, 0x6e, 0xca, 0x99, 0x6c, 0x3f, 0x60, 0x33, - 0xc6, 0x95, 0x31, 0x62, 0x97, 0xc4, 0xc2, 0x91, 0x64, 0x37, - 0x93, 0xc0, 0x35, 0x66, 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, - 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b, - 0x29, 0x7d, 0x81, 0xd5, 0x64, 0x30, 0xcc, 0x98, 0xb3, 0xe7, - 0x1b, 0x4f, 0xfe, 0xaa, 0x56, 0x02, 0x52, 0x06, 0xfa, 0xae, - 0x1f, 0x4b, 0xb7, 0xe3, 0xc8, 0x9c, 0x60, 0x34, 0x85, 0xd1, - 0x2d, 0x79, 0x7b, 0x2f, 0xd3, 0x87, 0x36, 0x62, 0x9e, 0xca, - 0xe1, 0xb5, 0x49, 0x1d, 0xac, 0xf8, 0x04, 0x50, 0xa4, 0xf0, - 0x0c, 0x58, 0xe9, 0xbd, 0x41, 0x15, 0x3e, 0x6a, 0x96, 0xc2, - 0x73, 0x27, 0xdb, 0x8f, 0x8d, 0xd9, 0x25, 0x71, 0xc0, 0x94, - 0x68, 0x3c, 0x17, 0x43, 0xbf, 0xeb, 0x5a, 0x0e, 0xf2, 0xa6, - 0xf6, 0xa2, 0x5e, 0x0a, 0xbb, 0xef, 0x13, 0x47, 0x6c, 0x38, - 0xc4, 0x90, 0x21, 0x75, 0x89, 0xdd, 0xdf, 0x8b, 0x77, 0x23, - 0x92, 0xc6, 0x3a, 0x6e, 0x45, 0x11, 0xed, 0xb9, 0x08, 0x5c, - 0xa0, 0xf4, 0x55, 0x01, 0xfd, 0xa9, 0x18, 0x4c, 0xb0, 0xe4, - 0xcf, 0x9b, 0x67, 0x33, 0x82, 0xd6, 0x2a, 0x7e, 0x7c, 0x28, - 0xd4, 0x80, 0x31, 0x65, 0x99, 0xcd, 0xe6, 0xb2, 0x4e, 0x1a, - 0xab, 0xff, 0x03, 0x57, 0x07, 0x53, 0xaf, 0xfb, 0x4a, 0x1e, - 0xe2, 0xb6, 0x9d, 0xc9, 0x35, 0x61, 0xd0, 0x84, 0x78, 0x2c, - 0x2e, 0x7a, 0x86, 0xd2, 0x63, 0x37, 0xcb, 0x9f, 0xb4, 0xe0, - 0x1c, 0x48, 0xf9, 0xad, 0x51, 0x05, 0xf1, 0xa5, 0x59, 0x0d, - 0xbc, 0xe8, 0x14, 0x40, 0x6b, 0x3f, 0xc3, 0x97, 0x26, 0x72, - 0x8e, 0xda, 0xd8, 0x8c, 0x70, 0x24, 0x95, 0xc1, 0x3d, 0x69, - 0x42, 0x16, 0xea, 0xbe, 0x0f, 0x5b, 0xa7, 0xf3, 0xa3, 0xf7, - 0x0b, 0x5f, 0xee, 0xba, 0x46, 0x12, 0x39, 0x6d, 0x91, 0xc5, - 0x74, 0x20, 0xdc, 0x88, 0x8a, 0xde, 0x22, 0x76, 0xc7, 0x93, - 0x6f, 0x3b, 0x10, 0x44, 0xb8, 0xec, 0x5d, 0x09, 0xf5, 0xa1, - 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, - 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24, 0x39, 0x6c, 0x93, 0xc6, - 0x70, 0x25, 0xda, 0x8f, 0xab, 0xfe, 0x01, 0x54, 0xe2, 0xb7, - 0x48, 0x1d, 0x72, 0x27, 0xd8, 0x8d, 0x3b, 0x6e, 0x91, 0xc4, - 0xe0, 0xb5, 0x4a, 0x1f, 0xa9, 0xfc, 0x03, 0x56, 0x4b, 0x1e, - 0xe1, 0xb4, 0x02, 0x57, 0xa8, 0xfd, 0xd9, 0x8c, 0x73, 0x26, - 0x90, 0xc5, 0x3a, 0x6f, 0xe4, 0xb1, 0x4e, 0x1b, 0xad, 0xf8, - 0x07, 0x52, 0x76, 0x23, 0xdc, 0x89, 0x3f, 0x6a, 0x95, 0xc0, - 0xdd, 0x88, 0x77, 0x22, 0x94, 0xc1, 0x3e, 0x6b, 0x4f, 0x1a, - 0xe5, 0xb0, 0x06, 0x53, 0xac, 0xf9, 0x96, 0xc3, 0x3c, 0x69, - 0xdf, 0x8a, 0x75, 0x20, 0x04, 0x51, 0xae, 0xfb, 0x4d, 0x18, - 0xe7, 0xb2, 0xaf, 0xfa, 0x05, 0x50, 0xe6, 0xb3, 0x4c, 0x19, - 0x3d, 0x68, 0x97, 0xc2, 0x74, 0x21, 0xde, 0x8b, 0xd5, 0x80, - 0x7f, 0x2a, 0x9c, 0xc9, 0x36, 0x63, 0x47, 0x12, 0xed, 0xb8, - 0x0e, 0x5b, 0xa4, 0xf1, 0xec, 0xb9, 0x46, 0x13, 0xa5, 0xf0, - 0x0f, 0x5a, 0x7e, 0x2b, 0xd4, 0x81, 0x37, 0x62, 0x9d, 0xc8, - 0xa7, 0xf2, 0x0d, 0x58, 0xee, 0xbb, 0x44, 0x11, 0x35, 0x60, - 0x9f, 0xca, 0x7c, 0x29, 0xd6, 0x83, 0x9e, 0xcb, 0x34, 0x61, - 0xd7, 0x82, 0x7d, 0x28, 0x0c, 0x59, 0xa6, 0xf3, 0x45, 0x10, - 0xef, 0xba, 0x31, 0x64, 0x9b, 0xce, 0x78, 0x2d, 0xd2, 0x87, - 0xa3, 0xf6, 0x09, 0x5c, 0xea, 0xbf, 0x40, 0x15, 0x08, 0x5d, - 0xa2, 0xf7, 0x41, 0x14, 0xeb, 0xbe, 0x9a, 0xcf, 0x30, 0x65, - 0xd3, 0x86, 0x79, 0x2c, 0x43, 0x16, 0xe9, 0xbc, 0x0a, 0x5f, - 0xa0, 0xf5, 0xd1, 0x84, 0x7b, 0x2e, 0x98, 0xcd, 0x32, 0x67, - 0x7a, 0x2f, 0xd0, 0x85, 0x33, 0x66, 0x99, 0xcc, 0xe8, 0xbd, - 0x42, 0x17, 0xa1, 0xf4, 0x0b, 0x5e, 0x00, 0x56, 0xac, 0xfa, - 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, - 0x63, 0x35, 0x09, 0x5f, 0xa5, 0xf3, 0x4c, 0x1a, 0xe0, 0xb6, - 0x83, 0xd5, 0x2f, 0x79, 0xc6, 0x90, 0x6a, 0x3c, 0x12, 0x44, - 0xbe, 0xe8, 0x57, 0x01, 0xfb, 0xad, 0x98, 0xce, 0x34, 0x62, - 0xdd, 0x8b, 0x71, 0x27, 0x1b, 0x4d, 0xb7, 0xe1, 0x5e, 0x08, - 0xf2, 0xa4, 0x91, 0xc7, 0x3d, 0x6b, 0xd4, 0x82, 0x78, 0x2e, - 0x24, 0x72, 0x88, 0xde, 0x61, 0x37, 0xcd, 0x9b, 0xae, 0xf8, - 0x02, 0x54, 0xeb, 0xbd, 0x47, 0x11, 0x2d, 0x7b, 0x81, 0xd7, - 0x68, 0x3e, 0xc4, 0x92, 0xa7, 0xf1, 0x0b, 0x5d, 0xe2, 0xb4, - 0x4e, 0x18, 0x36, 0x60, 0x9a, 0xcc, 0x73, 0x25, 0xdf, 0x89, - 0xbc, 0xea, 0x10, 0x46, 0xf9, 0xaf, 0x55, 0x03, 0x3f, 0x69, - 0x93, 0xc5, 0x7a, 0x2c, 0xd6, 0x80, 0xb5, 0xe3, 0x19, 0x4f, - 0xf0, 0xa6, 0x5c, 0x0a, 0x48, 0x1e, 0xe4, 0xb2, 0x0d, 0x5b, - 0xa1, 0xf7, 0xc2, 0x94, 0x6e, 0x38, 0x87, 0xd1, 0x2b, 0x7d, - 0x41, 0x17, 0xed, 0xbb, 0x04, 0x52, 0xa8, 0xfe, 0xcb, 0x9d, - 0x67, 0x31, 0x8e, 0xd8, 0x22, 0x74, 0x5a, 0x0c, 0xf6, 0xa0, - 0x1f, 0x49, 0xb3, 0xe5, 0xd0, 0x86, 0x7c, 0x2a, 0x95, 0xc3, - 0x39, 0x6f, 0x53, 0x05, 0xff, 0xa9, 0x16, 0x40, 0xba, 0xec, - 0xd9, 0x8f, 0x75, 0x23, 0x9c, 0xca, 0x30, 0x66, 0x6c, 0x3a, - 0xc0, 0x96, 0x29, 0x7f, 0x85, 0xd3, 0xe6, 0xb0, 0x4a, 0x1c, - 0xa3, 0xf5, 0x0f, 0x59, 0x65, 0x33, 0xc9, 0x9f, 0x20, 0x76, - 0x8c, 0xda, 0xef, 0xb9, 0x43, 0x15, 0xaa, 0xfc, 0x06, 0x50, - 0x7e, 0x28, 0xd2, 0x84, 0x3b, 0x6d, 0x97, 0xc1, 0xf4, 0xa2, - 0x58, 0x0e, 0xb1, 0xe7, 0x1d, 0x4b, 0x77, 0x21, 0xdb, 0x8d, - 0x32, 0x64, 0x9e, 0xc8, 0xfd, 0xab, 0x51, 0x07, 0xb8, 0xee, - 0x14, 0x42, 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, - 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a, 0x19, 0x4e, - 0xb7, 0xe0, 0x58, 0x0f, 0xf6, 0xa1, 0x9b, 0xcc, 0x35, 0x62, - 0xda, 0x8d, 0x74, 0x23, 0x32, 0x65, 0x9c, 0xcb, 0x73, 0x24, - 0xdd, 0x8a, 0xb0, 0xe7, 0x1e, 0x49, 0xf1, 0xa6, 0x5f, 0x08, - 0x2b, 0x7c, 0x85, 0xd2, 0x6a, 0x3d, 0xc4, 0x93, 0xa9, 0xfe, - 0x07, 0x50, 0xe8, 0xbf, 0x46, 0x11, 0x64, 0x33, 0xca, 0x9d, - 0x25, 0x72, 0x8b, 0xdc, 0xe6, 0xb1, 0x48, 0x1f, 0xa7, 0xf0, - 0x09, 0x5e, 0x7d, 0x2a, 0xd3, 0x84, 0x3c, 0x6b, 0x92, 0xc5, - 0xff, 0xa8, 0x51, 0x06, 0xbe, 0xe9, 0x10, 0x47, 0x56, 0x01, - 0xf8, 0xaf, 0x17, 0x40, 0xb9, 0xee, 0xd4, 0x83, 0x7a, 0x2d, - 0x95, 0xc2, 0x3b, 0x6c, 0x4f, 0x18, 0xe1, 0xb6, 0x0e, 0x59, - 0xa0, 0xf7, 0xcd, 0x9a, 0x63, 0x34, 0x8c, 0xdb, 0x22, 0x75, - 0xc8, 0x9f, 0x66, 0x31, 0x89, 0xde, 0x27, 0x70, 0x4a, 0x1d, - 0xe4, 0xb3, 0x0b, 0x5c, 0xa5, 0xf2, 0xd1, 0x86, 0x7f, 0x28, - 0x90, 0xc7, 0x3e, 0x69, 0x53, 0x04, 0xfd, 0xaa, 0x12, 0x45, - 0xbc, 0xeb, 0xfa, 0xad, 0x54, 0x03, 0xbb, 0xec, 0x15, 0x42, - 0x78, 0x2f, 0xd6, 0x81, 0x39, 0x6e, 0x97, 0xc0, 0xe3, 0xb4, - 0x4d, 0x1a, 0xa2, 0xf5, 0x0c, 0x5b, 0x61, 0x36, 0xcf, 0x98, - 0x20, 0x77, 0x8e, 0xd9, 0xac, 0xfb, 0x02, 0x55, 0xed, 0xba, - 0x43, 0x14, 0x2e, 0x79, 0x80, 0xd7, 0x6f, 0x38, 0xc1, 0x96, - 0xb5, 0xe2, 0x1b, 0x4c, 0xf4, 0xa3, 0x5a, 0x0d, 0x37, 0x60, - 0x99, 0xce, 0x76, 0x21, 0xd8, 0x8f, 0x9e, 0xc9, 0x30, 0x67, - 0xdf, 0x88, 0x71, 0x26, 0x1c, 0x4b, 0xb2, 0xe5, 0x5d, 0x0a, - 0xf3, 0xa4, 0x87, 0xd0, 0x29, 0x7e, 0xc6, 0x91, 0x68, 0x3f, - 0x05, 0x52, 0xab, 0xfc, 0x44, 0x13, 0xea, 0xbd, 0x00, 0x58, - 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, - 0x87, 0xdf, 0x37, 0x6f, 0xe9, 0xb1, 0x59, 0x01, 0x94, 0xcc, - 0x24, 0x7c, 0x13, 0x4b, 0xa3, 0xfb, 0x6e, 0x36, 0xde, 0x86, - 0xcf, 0x97, 0x7f, 0x27, 0xb2, 0xea, 0x02, 0x5a, 0x35, 0x6d, - 0x85, 0xdd, 0x48, 0x10, 0xf8, 0xa0, 0x26, 0x7e, 0x96, 0xce, - 0x5b, 0x03, 0xeb, 0xb3, 0xdc, 0x84, 0x6c, 0x34, 0xa1, 0xf9, - 0x11, 0x49, 0x83, 0xdb, 0x33, 0x6b, 0xfe, 0xa6, 0x4e, 0x16, - 0x79, 0x21, 0xc9, 0x91, 0x04, 0x5c, 0xb4, 0xec, 0x6a, 0x32, - 0xda, 0x82, 0x17, 0x4f, 0xa7, 0xff, 0x90, 0xc8, 0x20, 0x78, - 0xed, 0xb5, 0x5d, 0x05, 0x4c, 0x14, 0xfc, 0xa4, 0x31, 0x69, - 0x81, 0xd9, 0xb6, 0xee, 0x06, 0x5e, 0xcb, 0x93, 0x7b, 0x23, - 0xa5, 0xfd, 0x15, 0x4d, 0xd8, 0x80, 0x68, 0x30, 0x5f, 0x07, - 0xef, 0xb7, 0x22, 0x7a, 0x92, 0xca, 0x1b, 0x43, 0xab, 0xf3, - 0x66, 0x3e, 0xd6, 0x8e, 0xe1, 0xb9, 0x51, 0x09, 0x9c, 0xc4, - 0x2c, 0x74, 0xf2, 0xaa, 0x42, 0x1a, 0x8f, 0xd7, 0x3f, 0x67, - 0x08, 0x50, 0xb8, 0xe0, 0x75, 0x2d, 0xc5, 0x9d, 0xd4, 0x8c, - 0x64, 0x3c, 0xa9, 0xf1, 0x19, 0x41, 0x2e, 0x76, 0x9e, 0xc6, - 0x53, 0x0b, 0xe3, 0xbb, 0x3d, 0x65, 0x8d, 0xd5, 0x40, 0x18, - 0xf0, 0xa8, 0xc7, 0x9f, 0x77, 0x2f, 0xba, 0xe2, 0x0a, 0x52, - 0x98, 0xc0, 0x28, 0x70, 0xe5, 0xbd, 0x55, 0x0d, 0x62, 0x3a, - 0xd2, 0x8a, 0x1f, 0x47, 0xaf, 0xf7, 0x71, 0x29, 0xc1, 0x99, - 0x0c, 0x54, 0xbc, 0xe4, 0x8b, 0xd3, 0x3b, 0x63, 0xf6, 0xae, - 0x46, 0x1e, 0x57, 0x0f, 0xe7, 0xbf, 0x2a, 0x72, 0x9a, 0xc2, - 0xad, 0xf5, 0x1d, 0x45, 0xd0, 0x88, 0x60, 0x38, 0xbe, 0xe6, - 0x0e, 0x56, 0xc3, 0x9b, 0x73, 0x2b, 0x44, 0x1c, 0xf4, 0xac, - 0x39, 0x61, 0x89, 0xd1, 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, - 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60, - 0xf9, 0xa0, 0x4b, 0x12, 0x80, 0xd9, 0x32, 0x6b, 0x0b, 0x52, - 0xb9, 0xe0, 0x72, 0x2b, 0xc0, 0x99, 0xef, 0xb6, 0x5d, 0x04, - 0x96, 0xcf, 0x24, 0x7d, 0x1d, 0x44, 0xaf, 0xf6, 0x64, 0x3d, - 0xd6, 0x8f, 0x16, 0x4f, 0xa4, 0xfd, 0x6f, 0x36, 0xdd, 0x84, - 0xe4, 0xbd, 0x56, 0x0f, 0x9d, 0xc4, 0x2f, 0x76, 0xc3, 0x9a, - 0x71, 0x28, 0xba, 0xe3, 0x08, 0x51, 0x31, 0x68, 0x83, 0xda, - 0x48, 0x11, 0xfa, 0xa3, 0x3a, 0x63, 0x88, 0xd1, 0x43, 0x1a, - 0xf1, 0xa8, 0xc8, 0x91, 0x7a, 0x23, 0xb1, 0xe8, 0x03, 0x5a, - 0x2c, 0x75, 0x9e, 0xc7, 0x55, 0x0c, 0xe7, 0xbe, 0xde, 0x87, - 0x6c, 0x35, 0xa7, 0xfe, 0x15, 0x4c, 0xd5, 0x8c, 0x67, 0x3e, - 0xac, 0xf5, 0x1e, 0x47, 0x27, 0x7e, 0x95, 0xcc, 0x5e, 0x07, - 0xec, 0xb5, 0x9b, 0xc2, 0x29, 0x70, 0xe2, 0xbb, 0x50, 0x09, - 0x69, 0x30, 0xdb, 0x82, 0x10, 0x49, 0xa2, 0xfb, 0x62, 0x3b, - 0xd0, 0x89, 0x1b, 0x42, 0xa9, 0xf0, 0x90, 0xc9, 0x22, 0x7b, - 0xe9, 0xb0, 0x5b, 0x02, 0x74, 0x2d, 0xc6, 0x9f, 0x0d, 0x54, - 0xbf, 0xe6, 0x86, 0xdf, 0x34, 0x6d, 0xff, 0xa6, 0x4d, 0x14, - 0x8d, 0xd4, 0x3f, 0x66, 0xf4, 0xad, 0x46, 0x1f, 0x7f, 0x26, - 0xcd, 0x94, 0x06, 0x5f, 0xb4, 0xed, 0x58, 0x01, 0xea, 0xb3, - 0x21, 0x78, 0x93, 0xca, 0xaa, 0xf3, 0x18, 0x41, 0xd3, 0x8a, - 0x61, 0x38, 0xa1, 0xf8, 0x13, 0x4a, 0xd8, 0x81, 0x6a, 0x33, - 0x53, 0x0a, 0xe1, 0xb8, 0x2a, 0x73, 0x98, 0xc1, 0xb7, 0xee, - 0x05, 0x5c, 0xce, 0x97, 0x7c, 0x25, 0x45, 0x1c, 0xf7, 0xae, - 0x3c, 0x65, 0x8e, 0xd7, 0x4e, 0x17, 0xfc, 0xa5, 0x37, 0x6e, - 0x85, 0xdc, 0xbc, 0xe5, 0x0e, 0x57, 0xc5, 0x9c, 0x77, 0x2e, - 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, - 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71, 0xc9, 0x93, 0x7d, 0x27, - 0xbc, 0xe6, 0x08, 0x52, 0x23, 0x79, 0x97, 0xcd, 0x56, 0x0c, - 0xe2, 0xb8, 0x8f, 0xd5, 0x3b, 0x61, 0xfa, 0xa0, 0x4e, 0x14, - 0x65, 0x3f, 0xd1, 0x8b, 0x10, 0x4a, 0xa4, 0xfe, 0x46, 0x1c, - 0xf2, 0xa8, 0x33, 0x69, 0x87, 0xdd, 0xac, 0xf6, 0x18, 0x42, - 0xd9, 0x83, 0x6d, 0x37, 0x03, 0x59, 0xb7, 0xed, 0x76, 0x2c, - 0xc2, 0x98, 0xe9, 0xb3, 0x5d, 0x07, 0x9c, 0xc6, 0x28, 0x72, - 0xca, 0x90, 0x7e, 0x24, 0xbf, 0xe5, 0x0b, 0x51, 0x20, 0x7a, - 0x94, 0xce, 0x55, 0x0f, 0xe1, 0xbb, 0x8c, 0xd6, 0x38, 0x62, - 0xf9, 0xa3, 0x4d, 0x17, 0x66, 0x3c, 0xd2, 0x88, 0x13, 0x49, - 0xa7, 0xfd, 0x45, 0x1f, 0xf1, 0xab, 0x30, 0x6a, 0x84, 0xde, - 0xaf, 0xf5, 0x1b, 0x41, 0xda, 0x80, 0x6e, 0x34, 0x06, 0x5c, - 0xb2, 0xe8, 0x73, 0x29, 0xc7, 0x9d, 0xec, 0xb6, 0x58, 0x02, - 0x99, 0xc3, 0x2d, 0x77, 0xcf, 0x95, 0x7b, 0x21, 0xba, 0xe0, - 0x0e, 0x54, 0x25, 0x7f, 0x91, 0xcb, 0x50, 0x0a, 0xe4, 0xbe, - 0x89, 0xd3, 0x3d, 0x67, 0xfc, 0xa6, 0x48, 0x12, 0x63, 0x39, - 0xd7, 0x8d, 0x16, 0x4c, 0xa2, 0xf8, 0x40, 0x1a, 0xf4, 0xae, - 0x35, 0x6f, 0x81, 0xdb, 0xaa, 0xf0, 0x1e, 0x44, 0xdf, 0x85, - 0x6b, 0x31, 0x05, 0x5f, 0xb1, 0xeb, 0x70, 0x2a, 0xc4, 0x9e, - 0xef, 0xb5, 0x5b, 0x01, 0x9a, 0xc0, 0x2e, 0x74, 0xcc, 0x96, - 0x78, 0x22, 0xb9, 0xe3, 0x0d, 0x57, 0x26, 0x7c, 0x92, 0xc8, - 0x53, 0x09, 0xe7, 0xbd, 0x8a, 0xd0, 0x3e, 0x64, 0xff, 0xa5, - 0x4b, 0x11, 0x60, 0x3a, 0xd4, 0x8e, 0x15, 0x4f, 0xa1, 0xfb, - 0x43, 0x19, 0xf7, 0xad, 0x36, 0x6c, 0x82, 0xd8, 0xa9, 0xf3, - 0x1d, 0x47, 0xdc, 0x86, 0x68, 0x32, 0x00, 0x5b, 0xb6, 0xed, - 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, - 0x25, 0x7e, 0xd9, 0x82, 0x6f, 0x34, 0xa8, 0xf3, 0x1e, 0x45, - 0x3b, 0x60, 0x8d, 0xd6, 0x4a, 0x11, 0xfc, 0xa7, 0xaf, 0xf4, - 0x19, 0x42, 0xde, 0x85, 0x68, 0x33, 0x4d, 0x16, 0xfb, 0xa0, - 0x3c, 0x67, 0x8a, 0xd1, 0x76, 0x2d, 0xc0, 0x9b, 0x07, 0x5c, - 0xb1, 0xea, 0x94, 0xcf, 0x22, 0x79, 0xe5, 0xbe, 0x53, 0x08, - 0x43, 0x18, 0xf5, 0xae, 0x32, 0x69, 0x84, 0xdf, 0xa1, 0xfa, - 0x17, 0x4c, 0xd0, 0x8b, 0x66, 0x3d, 0x9a, 0xc1, 0x2c, 0x77, - 0xeb, 0xb0, 0x5d, 0x06, 0x78, 0x23, 0xce, 0x95, 0x09, 0x52, - 0xbf, 0xe4, 0xec, 0xb7, 0x5a, 0x01, 0x9d, 0xc6, 0x2b, 0x70, - 0x0e, 0x55, 0xb8, 0xe3, 0x7f, 0x24, 0xc9, 0x92, 0x35, 0x6e, - 0x83, 0xd8, 0x44, 0x1f, 0xf2, 0xa9, 0xd7, 0x8c, 0x61, 0x3a, - 0xa6, 0xfd, 0x10, 0x4b, 0x86, 0xdd, 0x30, 0x6b, 0xf7, 0xac, - 0x41, 0x1a, 0x64, 0x3f, 0xd2, 0x89, 0x15, 0x4e, 0xa3, 0xf8, - 0x5f, 0x04, 0xe9, 0xb2, 0x2e, 0x75, 0x98, 0xc3, 0xbd, 0xe6, - 0x0b, 0x50, 0xcc, 0x97, 0x7a, 0x21, 0x29, 0x72, 0x9f, 0xc4, - 0x58, 0x03, 0xee, 0xb5, 0xcb, 0x90, 0x7d, 0x26, 0xba, 0xe1, - 0x0c, 0x57, 0xf0, 0xab, 0x46, 0x1d, 0x81, 0xda, 0x37, 0x6c, - 0x12, 0x49, 0xa4, 0xff, 0x63, 0x38, 0xd5, 0x8e, 0xc5, 0x9e, - 0x73, 0x28, 0xb4, 0xef, 0x02, 0x59, 0x27, 0x7c, 0x91, 0xca, - 0x56, 0x0d, 0xe0, 0xbb, 0x1c, 0x47, 0xaa, 0xf1, 0x6d, 0x36, - 0xdb, 0x80, 0xfe, 0xa5, 0x48, 0x13, 0x8f, 0xd4, 0x39, 0x62, - 0x6a, 0x31, 0xdc, 0x87, 0x1b, 0x40, 0xad, 0xf6, 0x88, 0xd3, - 0x3e, 0x65, 0xf9, 0xa2, 0x4f, 0x14, 0xb3, 0xe8, 0x05, 0x5e, - 0xc2, 0x99, 0x74, 0x2f, 0x51, 0x0a, 0xe7, 0xbc, 0x20, 0x7b, - 0x96, 0xcd, 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, - 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53, 0xa9, 0xf5, - 0x11, 0x4d, 0xc4, 0x98, 0x7c, 0x20, 0x73, 0x2f, 0xcb, 0x97, - 0x1e, 0x42, 0xa6, 0xfa, 0x4f, 0x13, 0xf7, 0xab, 0x22, 0x7e, - 0x9a, 0xc6, 0x95, 0xc9, 0x2d, 0x71, 0xf8, 0xa4, 0x40, 0x1c, - 0xe6, 0xba, 0x5e, 0x02, 0x8b, 0xd7, 0x33, 0x6f, 0x3c, 0x60, - 0x84, 0xd8, 0x51, 0x0d, 0xe9, 0xb5, 0x9e, 0xc2, 0x26, 0x7a, - 0xf3, 0xaf, 0x4b, 0x17, 0x44, 0x18, 0xfc, 0xa0, 0x29, 0x75, - 0x91, 0xcd, 0x37, 0x6b, 0x8f, 0xd3, 0x5a, 0x06, 0xe2, 0xbe, - 0xed, 0xb1, 0x55, 0x09, 0x80, 0xdc, 0x38, 0x64, 0xd1, 0x8d, - 0x69, 0x35, 0xbc, 0xe0, 0x04, 0x58, 0x0b, 0x57, 0xb3, 0xef, - 0x66, 0x3a, 0xde, 0x82, 0x78, 0x24, 0xc0, 0x9c, 0x15, 0x49, - 0xad, 0xf1, 0xa2, 0xfe, 0x1a, 0x46, 0xcf, 0x93, 0x77, 0x2b, - 0x21, 0x7d, 0x99, 0xc5, 0x4c, 0x10, 0xf4, 0xa8, 0xfb, 0xa7, - 0x43, 0x1f, 0x96, 0xca, 0x2e, 0x72, 0x88, 0xd4, 0x30, 0x6c, - 0xe5, 0xb9, 0x5d, 0x01, 0x52, 0x0e, 0xea, 0xb6, 0x3f, 0x63, - 0x87, 0xdb, 0x6e, 0x32, 0xd6, 0x8a, 0x03, 0x5f, 0xbb, 0xe7, - 0xb4, 0xe8, 0x0c, 0x50, 0xd9, 0x85, 0x61, 0x3d, 0xc7, 0x9b, - 0x7f, 0x23, 0xaa, 0xf6, 0x12, 0x4e, 0x1d, 0x41, 0xa5, 0xf9, - 0x70, 0x2c, 0xc8, 0x94, 0xbf, 0xe3, 0x07, 0x5b, 0xd2, 0x8e, - 0x6a, 0x36, 0x65, 0x39, 0xdd, 0x81, 0x08, 0x54, 0xb0, 0xec, - 0x16, 0x4a, 0xae, 0xf2, 0x7b, 0x27, 0xc3, 0x9f, 0xcc, 0x90, - 0x74, 0x28, 0xa1, 0xfd, 0x19, 0x45, 0xf0, 0xac, 0x48, 0x14, - 0x9d, 0xc1, 0x25, 0x79, 0x2a, 0x76, 0x92, 0xce, 0x47, 0x1b, - 0xff, 0xa3, 0x59, 0x05, 0xe1, 0xbd, 0x34, 0x68, 0x8c, 0xd0, - 0x83, 0xdf, 0x3b, 0x67, 0xee, 0xb2, 0x56, 0x0a, 0x00, 0x5d, - 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, - 0xbb, 0xe6, 0x01, 0x5c, 0xb9, 0xe4, 0x03, 0x5e, 0xd0, 0x8d, - 0x6a, 0x37, 0x6b, 0x36, 0xd1, 0x8c, 0x02, 0x5f, 0xb8, 0xe5, - 0x6f, 0x32, 0xd5, 0x88, 0x06, 0x5b, 0xbc, 0xe1, 0xbd, 0xe0, - 0x07, 0x5a, 0xd4, 0x89, 0x6e, 0x33, 0xd6, 0x8b, 0x6c, 0x31, - 0xbf, 0xe2, 0x05, 0x58, 0x04, 0x59, 0xbe, 0xe3, 0x6d, 0x30, - 0xd7, 0x8a, 0xde, 0x83, 0x64, 0x39, 0xb7, 0xea, 0x0d, 0x50, - 0x0c, 0x51, 0xb6, 0xeb, 0x65, 0x38, 0xdf, 0x82, 0x67, 0x3a, - 0xdd, 0x80, 0x0e, 0x53, 0xb4, 0xe9, 0xb5, 0xe8, 0x0f, 0x52, - 0xdc, 0x81, 0x66, 0x3b, 0xb1, 0xec, 0x0b, 0x56, 0xd8, 0x85, - 0x62, 0x3f, 0x63, 0x3e, 0xd9, 0x84, 0x0a, 0x57, 0xb0, 0xed, - 0x08, 0x55, 0xb2, 0xef, 0x61, 0x3c, 0xdb, 0x86, 0xda, 0x87, - 0x60, 0x3d, 0xb3, 0xee, 0x09, 0x54, 0xa1, 0xfc, 0x1b, 0x46, - 0xc8, 0x95, 0x72, 0x2f, 0x73, 0x2e, 0xc9, 0x94, 0x1a, 0x47, - 0xa0, 0xfd, 0x18, 0x45, 0xa2, 0xff, 0x71, 0x2c, 0xcb, 0x96, - 0xca, 0x97, 0x70, 0x2d, 0xa3, 0xfe, 0x19, 0x44, 0xce, 0x93, - 0x74, 0x29, 0xa7, 0xfa, 0x1d, 0x40, 0x1c, 0x41, 0xa6, 0xfb, - 0x75, 0x28, 0xcf, 0x92, 0x77, 0x2a, 0xcd, 0x90, 0x1e, 0x43, - 0xa4, 0xf9, 0xa5, 0xf8, 0x1f, 0x42, 0xcc, 0x91, 0x76, 0x2b, - 0x7f, 0x22, 0xc5, 0x98, 0x16, 0x4b, 0xac, 0xf1, 0xad, 0xf0, - 0x17, 0x4a, 0xc4, 0x99, 0x7e, 0x23, 0xc6, 0x9b, 0x7c, 0x21, - 0xaf, 0xf2, 0x15, 0x48, 0x14, 0x49, 0xae, 0xf3, 0x7d, 0x20, - 0xc7, 0x9a, 0x10, 0x4d, 0xaa, 0xf7, 0x79, 0x24, 0xc3, 0x9e, - 0xc2, 0x9f, 0x78, 0x25, 0xab, 0xf6, 0x11, 0x4c, 0xa9, 0xf4, - 0x13, 0x4e, 0xc0, 0x9d, 0x7a, 0x27, 0x7b, 0x26, 0xc1, 0x9c, - 0x12, 0x4f, 0xa8, 0xf5, 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, - 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d, - 0x89, 0xd7, 0x35, 0x6b, 0xec, 0xb2, 0x50, 0x0e, 0x43, 0x1d, - 0xff, 0xa1, 0x26, 0x78, 0x9a, 0xc4, 0x0f, 0x51, 0xb3, 0xed, - 0x6a, 0x34, 0xd6, 0x88, 0xc5, 0x9b, 0x79, 0x27, 0xa0, 0xfe, - 0x1c, 0x42, 0x86, 0xd8, 0x3a, 0x64, 0xe3, 0xbd, 0x5f, 0x01, - 0x4c, 0x12, 0xf0, 0xae, 0x29, 0x77, 0x95, 0xcb, 0x1e, 0x40, - 0xa2, 0xfc, 0x7b, 0x25, 0xc7, 0x99, 0xd4, 0x8a, 0x68, 0x36, - 0xb1, 0xef, 0x0d, 0x53, 0x97, 0xc9, 0x2b, 0x75, 0xf2, 0xac, - 0x4e, 0x10, 0x5d, 0x03, 0xe1, 0xbf, 0x38, 0x66, 0x84, 0xda, - 0x11, 0x4f, 0xad, 0xf3, 0x74, 0x2a, 0xc8, 0x96, 0xdb, 0x85, - 0x67, 0x39, 0xbe, 0xe0, 0x02, 0x5c, 0x98, 0xc6, 0x24, 0x7a, - 0xfd, 0xa3, 0x41, 0x1f, 0x52, 0x0c, 0xee, 0xb0, 0x37, 0x69, - 0x8b, 0xd5, 0x3c, 0x62, 0x80, 0xde, 0x59, 0x07, 0xe5, 0xbb, - 0xf6, 0xa8, 0x4a, 0x14, 0x93, 0xcd, 0x2f, 0x71, 0xb5, 0xeb, - 0x09, 0x57, 0xd0, 0x8e, 0x6c, 0x32, 0x7f, 0x21, 0xc3, 0x9d, - 0x1a, 0x44, 0xa6, 0xf8, 0x33, 0x6d, 0x8f, 0xd1, 0x56, 0x08, - 0xea, 0xb4, 0xf9, 0xa7, 0x45, 0x1b, 0x9c, 0xc2, 0x20, 0x7e, - 0xba, 0xe4, 0x06, 0x58, 0xdf, 0x81, 0x63, 0x3d, 0x70, 0x2e, - 0xcc, 0x92, 0x15, 0x4b, 0xa9, 0xf7, 0x22, 0x7c, 0x9e, 0xc0, - 0x47, 0x19, 0xfb, 0xa5, 0xe8, 0xb6, 0x54, 0x0a, 0x8d, 0xd3, - 0x31, 0x6f, 0xab, 0xf5, 0x17, 0x49, 0xce, 0x90, 0x72, 0x2c, - 0x61, 0x3f, 0xdd, 0x83, 0x04, 0x5a, 0xb8, 0xe6, 0x2d, 0x73, - 0x91, 0xcf, 0x48, 0x16, 0xf4, 0xaa, 0xe7, 0xb9, 0x5b, 0x05, - 0x82, 0xdc, 0x3e, 0x60, 0xa4, 0xfa, 0x18, 0x46, 0xc1, 0x9f, - 0x7d, 0x23, 0x6e, 0x30, 0xd2, 0x8c, 0x0b, 0x55, 0xb7, 0xe9, - 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, - 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42, 0x99, 0xc6, 0x27, 0x78, - 0xf8, 0xa7, 0x46, 0x19, 0x5b, 0x04, 0xe5, 0xba, 0x3a, 0x65, - 0x84, 0xdb, 0x2f, 0x70, 0x91, 0xce, 0x4e, 0x11, 0xf0, 0xaf, - 0xed, 0xb2, 0x53, 0x0c, 0x8c, 0xd3, 0x32, 0x6d, 0xb6, 0xe9, - 0x08, 0x57, 0xd7, 0x88, 0x69, 0x36, 0x74, 0x2b, 0xca, 0x95, - 0x15, 0x4a, 0xab, 0xf4, 0x5e, 0x01, 0xe0, 0xbf, 0x3f, 0x60, - 0x81, 0xde, 0x9c, 0xc3, 0x22, 0x7d, 0xfd, 0xa2, 0x43, 0x1c, - 0xc7, 0x98, 0x79, 0x26, 0xa6, 0xf9, 0x18, 0x47, 0x05, 0x5a, - 0xbb, 0xe4, 0x64, 0x3b, 0xda, 0x85, 0x71, 0x2e, 0xcf, 0x90, - 0x10, 0x4f, 0xae, 0xf1, 0xb3, 0xec, 0x0d, 0x52, 0xd2, 0x8d, - 0x6c, 0x33, 0xe8, 0xb7, 0x56, 0x09, 0x89, 0xd6, 0x37, 0x68, - 0x2a, 0x75, 0x94, 0xcb, 0x4b, 0x14, 0xf5, 0xaa, 0xbc, 0xe3, - 0x02, 0x5d, 0xdd, 0x82, 0x63, 0x3c, 0x7e, 0x21, 0xc0, 0x9f, - 0x1f, 0x40, 0xa1, 0xfe, 0x25, 0x7a, 0x9b, 0xc4, 0x44, 0x1b, - 0xfa, 0xa5, 0xe7, 0xb8, 0x59, 0x06, 0x86, 0xd9, 0x38, 0x67, - 0x93, 0xcc, 0x2d, 0x72, 0xf2, 0xad, 0x4c, 0x13, 0x51, 0x0e, - 0xef, 0xb0, 0x30, 0x6f, 0x8e, 0xd1, 0x0a, 0x55, 0xb4, 0xeb, - 0x6b, 0x34, 0xd5, 0x8a, 0xc8, 0x97, 0x76, 0x29, 0xa9, 0xf6, - 0x17, 0x48, 0xe2, 0xbd, 0x5c, 0x03, 0x83, 0xdc, 0x3d, 0x62, - 0x20, 0x7f, 0x9e, 0xc1, 0x41, 0x1e, 0xff, 0xa0, 0x7b, 0x24, - 0xc5, 0x9a, 0x1a, 0x45, 0xa4, 0xfb, 0xb9, 0xe6, 0x07, 0x58, - 0xd8, 0x87, 0x66, 0x39, 0xcd, 0x92, 0x73, 0x2c, 0xac, 0xf3, - 0x12, 0x4d, 0x0f, 0x50, 0xb1, 0xee, 0x6e, 0x31, 0xd0, 0x8f, - 0x54, 0x0b, 0xea, 0xb5, 0x35, 0x6a, 0x8b, 0xd4, 0x96, 0xc9, - 0x28, 0x77, 0xf7, 0xa8, 0x49, 0x16, 0x00, 0x60, 0xc0, 0xa0, - 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, - 0x7a, 0x1a, 0x4e, 0x2e, 0x8e, 0xee, 0xd3, 0xb3, 0x13, 0x73, - 0x69, 0x09, 0xa9, 0xc9, 0xf4, 0x94, 0x34, 0x54, 0x9c, 0xfc, - 0x5c, 0x3c, 0x01, 0x61, 0xc1, 0xa1, 0xbb, 0xdb, 0x7b, 0x1b, - 0x26, 0x46, 0xe6, 0x86, 0xd2, 0xb2, 0x12, 0x72, 0x4f, 0x2f, - 0x8f, 0xef, 0xf5, 0x95, 0x35, 0x55, 0x68, 0x08, 0xa8, 0xc8, - 0x25, 0x45, 0xe5, 0x85, 0xb8, 0xd8, 0x78, 0x18, 0x02, 0x62, - 0xc2, 0xa2, 0x9f, 0xff, 0x5f, 0x3f, 0x6b, 0x0b, 0xab, 0xcb, - 0xf6, 0x96, 0x36, 0x56, 0x4c, 0x2c, 0x8c, 0xec, 0xd1, 0xb1, - 0x11, 0x71, 0xb9, 0xd9, 0x79, 0x19, 0x24, 0x44, 0xe4, 0x84, - 0x9e, 0xfe, 0x5e, 0x3e, 0x03, 0x63, 0xc3, 0xa3, 0xf7, 0x97, - 0x37, 0x57, 0x6a, 0x0a, 0xaa, 0xca, 0xd0, 0xb0, 0x10, 0x70, - 0x4d, 0x2d, 0x8d, 0xed, 0x4a, 0x2a, 0x8a, 0xea, 0xd7, 0xb7, - 0x17, 0x77, 0x6d, 0x0d, 0xad, 0xcd, 0xf0, 0x90, 0x30, 0x50, - 0x04, 0x64, 0xc4, 0xa4, 0x99, 0xf9, 0x59, 0x39, 0x23, 0x43, - 0xe3, 0x83, 0xbe, 0xde, 0x7e, 0x1e, 0xd6, 0xb6, 0x16, 0x76, - 0x4b, 0x2b, 0x8b, 0xeb, 0xf1, 0x91, 0x31, 0x51, 0x6c, 0x0c, - 0xac, 0xcc, 0x98, 0xf8, 0x58, 0x38, 0x05, 0x65, 0xc5, 0xa5, - 0xbf, 0xdf, 0x7f, 0x1f, 0x22, 0x42, 0xe2, 0x82, 0x6f, 0x0f, - 0xaf, 0xcf, 0xf2, 0x92, 0x32, 0x52, 0x48, 0x28, 0x88, 0xe8, - 0xd5, 0xb5, 0x15, 0x75, 0x21, 0x41, 0xe1, 0x81, 0xbc, 0xdc, - 0x7c, 0x1c, 0x06, 0x66, 0xc6, 0xa6, 0x9b, 0xfb, 0x5b, 0x3b, - 0xf3, 0x93, 0x33, 0x53, 0x6e, 0x0e, 0xae, 0xce, 0xd4, 0xb4, - 0x14, 0x74, 0x49, 0x29, 0x89, 0xe9, 0xbd, 0xdd, 0x7d, 0x1d, - 0x20, 0x40, 0xe0, 0x80, 0x9a, 0xfa, 0x5a, 0x3a, 0x07, 0x67, - 0xc7, 0xa7, 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, - 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15, 0x5e, 0x3f, - 0x9c, 0xfd, 0xc7, 0xa6, 0x05, 0x64, 0x71, 0x10, 0xb3, 0xd2, - 0xe8, 0x89, 0x2a, 0x4b, 0xbc, 0xdd, 0x7e, 0x1f, 0x25, 0x44, - 0xe7, 0x86, 0x93, 0xf2, 0x51, 0x30, 0x0a, 0x6b, 0xc8, 0xa9, - 0xe2, 0x83, 0x20, 0x41, 0x7b, 0x1a, 0xb9, 0xd8, 0xcd, 0xac, - 0x0f, 0x6e, 0x54, 0x35, 0x96, 0xf7, 0x65, 0x04, 0xa7, 0xc6, - 0xfc, 0x9d, 0x3e, 0x5f, 0x4a, 0x2b, 0x88, 0xe9, 0xd3, 0xb2, - 0x11, 0x70, 0x3b, 0x5a, 0xf9, 0x98, 0xa2, 0xc3, 0x60, 0x01, - 0x14, 0x75, 0xd6, 0xb7, 0x8d, 0xec, 0x4f, 0x2e, 0xd9, 0xb8, - 0x1b, 0x7a, 0x40, 0x21, 0x82, 0xe3, 0xf6, 0x97, 0x34, 0x55, - 0x6f, 0x0e, 0xad, 0xcc, 0x87, 0xe6, 0x45, 0x24, 0x1e, 0x7f, - 0xdc, 0xbd, 0xa8, 0xc9, 0x6a, 0x0b, 0x31, 0x50, 0xf3, 0x92, - 0xca, 0xab, 0x08, 0x69, 0x53, 0x32, 0x91, 0xf0, 0xe5, 0x84, - 0x27, 0x46, 0x7c, 0x1d, 0xbe, 0xdf, 0x94, 0xf5, 0x56, 0x37, - 0x0d, 0x6c, 0xcf, 0xae, 0xbb, 0xda, 0x79, 0x18, 0x22, 0x43, - 0xe0, 0x81, 0x76, 0x17, 0xb4, 0xd5, 0xef, 0x8e, 0x2d, 0x4c, - 0x59, 0x38, 0x9b, 0xfa, 0xc0, 0xa1, 0x02, 0x63, 0x28, 0x49, - 0xea, 0x8b, 0xb1, 0xd0, 0x73, 0x12, 0x07, 0x66, 0xc5, 0xa4, - 0x9e, 0xff, 0x5c, 0x3d, 0xaf, 0xce, 0x6d, 0x0c, 0x36, 0x57, - 0xf4, 0x95, 0x80, 0xe1, 0x42, 0x23, 0x19, 0x78, 0xdb, 0xba, - 0xf1, 0x90, 0x33, 0x52, 0x68, 0x09, 0xaa, 0xcb, 0xde, 0xbf, - 0x1c, 0x7d, 0x47, 0x26, 0x85, 0xe4, 0x13, 0x72, 0xd1, 0xb0, - 0x8a, 0xeb, 0x48, 0x29, 0x3c, 0x5d, 0xfe, 0x9f, 0xa5, 0xc4, - 0x67, 0x06, 0x4d, 0x2c, 0x8f, 0xee, 0xd4, 0xb5, 0x16, 0x77, - 0x62, 0x03, 0xa0, 0xc1, 0xfb, 0x9a, 0x39, 0x58, 0x00, 0x62, - 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, - 0xa2, 0xc0, 0x66, 0x04, 0x6e, 0x0c, 0xaa, 0xc8, 0xfb, 0x99, - 0x3f, 0x5d, 0x59, 0x3b, 0x9d, 0xff, 0xcc, 0xae, 0x08, 0x6a, - 0xdc, 0xbe, 0x18, 0x7a, 0x49, 0x2b, 0x8d, 0xef, 0xeb, 0x89, - 0x2f, 0x4d, 0x7e, 0x1c, 0xba, 0xd8, 0xb2, 0xd0, 0x76, 0x14, - 0x27, 0x45, 0xe3, 0x81, 0x85, 0xe7, 0x41, 0x23, 0x10, 0x72, - 0xd4, 0xb6, 0xa5, 0xc7, 0x61, 0x03, 0x30, 0x52, 0xf4, 0x96, - 0x92, 0xf0, 0x56, 0x34, 0x07, 0x65, 0xc3, 0xa1, 0xcb, 0xa9, - 0x0f, 0x6d, 0x5e, 0x3c, 0x9a, 0xf8, 0xfc, 0x9e, 0x38, 0x5a, - 0x69, 0x0b, 0xad, 0xcf, 0x79, 0x1b, 0xbd, 0xdf, 0xec, 0x8e, - 0x28, 0x4a, 0x4e, 0x2c, 0x8a, 0xe8, 0xdb, 0xb9, 0x1f, 0x7d, - 0x17, 0x75, 0xd3, 0xb1, 0x82, 0xe0, 0x46, 0x24, 0x20, 0x42, - 0xe4, 0x86, 0xb5, 0xd7, 0x71, 0x13, 0x57, 0x35, 0x93, 0xf1, - 0xc2, 0xa0, 0x06, 0x64, 0x60, 0x02, 0xa4, 0xc6, 0xf5, 0x97, - 0x31, 0x53, 0x39, 0x5b, 0xfd, 0x9f, 0xac, 0xce, 0x68, 0x0a, - 0x0e, 0x6c, 0xca, 0xa8, 0x9b, 0xf9, 0x5f, 0x3d, 0x8b, 0xe9, - 0x4f, 0x2d, 0x1e, 0x7c, 0xda, 0xb8, 0xbc, 0xde, 0x78, 0x1a, - 0x29, 0x4b, 0xed, 0x8f, 0xe5, 0x87, 0x21, 0x43, 0x70, 0x12, - 0xb4, 0xd6, 0xd2, 0xb0, 0x16, 0x74, 0x47, 0x25, 0x83, 0xe1, - 0xf2, 0x90, 0x36, 0x54, 0x67, 0x05, 0xa3, 0xc1, 0xc5, 0xa7, - 0x01, 0x63, 0x50, 0x32, 0x94, 0xf6, 0x9c, 0xfe, 0x58, 0x3a, - 0x09, 0x6b, 0xcd, 0xaf, 0xab, 0xc9, 0x6f, 0x0d, 0x3e, 0x5c, - 0xfa, 0x98, 0x2e, 0x4c, 0xea, 0x88, 0xbb, 0xd9, 0x7f, 0x1d, - 0x19, 0x7b, 0xdd, 0xbf, 0x8c, 0xee, 0x48, 0x2a, 0x40, 0x22, - 0x84, 0xe6, 0xd5, 0xb7, 0x11, 0x73, 0x77, 0x15, 0xb3, 0xd1, - 0xe2, 0x80, 0x26, 0x44, 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, - 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b, - 0x7e, 0x1d, 0xb8, 0xdb, 0xef, 0x8c, 0x29, 0x4a, 0x41, 0x22, - 0x87, 0xe4, 0xd0, 0xb3, 0x16, 0x75, 0xfc, 0x9f, 0x3a, 0x59, - 0x6d, 0x0e, 0xab, 0xc8, 0xc3, 0xa0, 0x05, 0x66, 0x52, 0x31, - 0x94, 0xf7, 0x82, 0xe1, 0x44, 0x27, 0x13, 0x70, 0xd5, 0xb6, - 0xbd, 0xde, 0x7b, 0x18, 0x2c, 0x4f, 0xea, 0x89, 0xe5, 0x86, - 0x23, 0x40, 0x74, 0x17, 0xb2, 0xd1, 0xda, 0xb9, 0x1c, 0x7f, - 0x4b, 0x28, 0x8d, 0xee, 0x9b, 0xf8, 0x5d, 0x3e, 0x0a, 0x69, - 0xcc, 0xaf, 0xa4, 0xc7, 0x62, 0x01, 0x35, 0x56, 0xf3, 0x90, - 0x19, 0x7a, 0xdf, 0xbc, 0x88, 0xeb, 0x4e, 0x2d, 0x26, 0x45, - 0xe0, 0x83, 0xb7, 0xd4, 0x71, 0x12, 0x67, 0x04, 0xa1, 0xc2, - 0xf6, 0x95, 0x30, 0x53, 0x58, 0x3b, 0x9e, 0xfd, 0xc9, 0xaa, - 0x0f, 0x6c, 0xd7, 0xb4, 0x11, 0x72, 0x46, 0x25, 0x80, 0xe3, - 0xe8, 0x8b, 0x2e, 0x4d, 0x79, 0x1a, 0xbf, 0xdc, 0xa9, 0xca, - 0x6f, 0x0c, 0x38, 0x5b, 0xfe, 0x9d, 0x96, 0xf5, 0x50, 0x33, - 0x07, 0x64, 0xc1, 0xa2, 0x2b, 0x48, 0xed, 0x8e, 0xba, 0xd9, - 0x7c, 0x1f, 0x14, 0x77, 0xd2, 0xb1, 0x85, 0xe6, 0x43, 0x20, - 0x55, 0x36, 0x93, 0xf0, 0xc4, 0xa7, 0x02, 0x61, 0x6a, 0x09, - 0xac, 0xcf, 0xfb, 0x98, 0x3d, 0x5e, 0x32, 0x51, 0xf4, 0x97, - 0xa3, 0xc0, 0x65, 0x06, 0x0d, 0x6e, 0xcb, 0xa8, 0x9c, 0xff, - 0x5a, 0x39, 0x4c, 0x2f, 0x8a, 0xe9, 0xdd, 0xbe, 0x1b, 0x78, - 0x73, 0x10, 0xb5, 0xd6, 0xe2, 0x81, 0x24, 0x47, 0xce, 0xad, - 0x08, 0x6b, 0x5f, 0x3c, 0x99, 0xfa, 0xf1, 0x92, 0x37, 0x54, - 0x60, 0x03, 0xa6, 0xc5, 0xb0, 0xd3, 0x76, 0x15, 0x21, 0x42, - 0xe7, 0x84, 0x8f, 0xec, 0x49, 0x2a, 0x1e, 0x7d, 0xd8, 0xbb, - 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, - 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26, 0x0e, 0x6a, 0xc6, 0xa2, - 0x83, 0xe7, 0x4b, 0x2f, 0x09, 0x6d, 0xc1, 0xa5, 0x84, 0xe0, - 0x4c, 0x28, 0x1c, 0x78, 0xd4, 0xb0, 0x91, 0xf5, 0x59, 0x3d, - 0x1b, 0x7f, 0xd3, 0xb7, 0x96, 0xf2, 0x5e, 0x3a, 0x12, 0x76, - 0xda, 0xbe, 0x9f, 0xfb, 0x57, 0x33, 0x15, 0x71, 0xdd, 0xb9, - 0x98, 0xfc, 0x50, 0x34, 0x38, 0x5c, 0xf0, 0x94, 0xb5, 0xd1, - 0x7d, 0x19, 0x3f, 0x5b, 0xf7, 0x93, 0xb2, 0xd6, 0x7a, 0x1e, - 0x36, 0x52, 0xfe, 0x9a, 0xbb, 0xdf, 0x73, 0x17, 0x31, 0x55, - 0xf9, 0x9d, 0xbc, 0xd8, 0x74, 0x10, 0x24, 0x40, 0xec, 0x88, - 0xa9, 0xcd, 0x61, 0x05, 0x23, 0x47, 0xeb, 0x8f, 0xae, 0xca, - 0x66, 0x02, 0x2a, 0x4e, 0xe2, 0x86, 0xa7, 0xc3, 0x6f, 0x0b, - 0x2d, 0x49, 0xe5, 0x81, 0xa0, 0xc4, 0x68, 0x0c, 0x70, 0x14, - 0xb8, 0xdc, 0xfd, 0x99, 0x35, 0x51, 0x77, 0x13, 0xbf, 0xdb, - 0xfa, 0x9e, 0x32, 0x56, 0x7e, 0x1a, 0xb6, 0xd2, 0xf3, 0x97, - 0x3b, 0x5f, 0x79, 0x1d, 0xb1, 0xd5, 0xf4, 0x90, 0x3c, 0x58, - 0x6c, 0x08, 0xa4, 0xc0, 0xe1, 0x85, 0x29, 0x4d, 0x6b, 0x0f, - 0xa3, 0xc7, 0xe6, 0x82, 0x2e, 0x4a, 0x62, 0x06, 0xaa, 0xce, - 0xef, 0x8b, 0x27, 0x43, 0x65, 0x01, 0xad, 0xc9, 0xe8, 0x8c, - 0x20, 0x44, 0x48, 0x2c, 0x80, 0xe4, 0xc5, 0xa1, 0x0d, 0x69, - 0x4f, 0x2b, 0x87, 0xe3, 0xc2, 0xa6, 0x0a, 0x6e, 0x46, 0x22, - 0x8e, 0xea, 0xcb, 0xaf, 0x03, 0x67, 0x41, 0x25, 0x89, 0xed, - 0xcc, 0xa8, 0x04, 0x60, 0x54, 0x30, 0x9c, 0xf8, 0xd9, 0xbd, - 0x11, 0x75, 0x53, 0x37, 0x9b, 0xff, 0xde, 0xba, 0x16, 0x72, - 0x5a, 0x3e, 0x92, 0xf6, 0xd7, 0xb3, 0x1f, 0x7b, 0x5d, 0x39, - 0x95, 0xf1, 0xd0, 0xb4, 0x18, 0x7c, 0x00, 0x65, 0xca, 0xaf, - 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, - 0x4c, 0x29, 0x1e, 0x7b, 0xd4, 0xb1, 0x97, 0xf2, 0x5d, 0x38, - 0x11, 0x74, 0xdb, 0xbe, 0x98, 0xfd, 0x52, 0x37, 0x3c, 0x59, - 0xf6, 0x93, 0xb5, 0xd0, 0x7f, 0x1a, 0x33, 0x56, 0xf9, 0x9c, - 0xba, 0xdf, 0x70, 0x15, 0x22, 0x47, 0xe8, 0x8d, 0xab, 0xce, - 0x61, 0x04, 0x2d, 0x48, 0xe7, 0x82, 0xa4, 0xc1, 0x6e, 0x0b, - 0x78, 0x1d, 0xb2, 0xd7, 0xf1, 0x94, 0x3b, 0x5e, 0x77, 0x12, - 0xbd, 0xd8, 0xfe, 0x9b, 0x34, 0x51, 0x66, 0x03, 0xac, 0xc9, - 0xef, 0x8a, 0x25, 0x40, 0x69, 0x0c, 0xa3, 0xc6, 0xe0, 0x85, - 0x2a, 0x4f, 0x44, 0x21, 0x8e, 0xeb, 0xcd, 0xa8, 0x07, 0x62, - 0x4b, 0x2e, 0x81, 0xe4, 0xc2, 0xa7, 0x08, 0x6d, 0x5a, 0x3f, - 0x90, 0xf5, 0xd3, 0xb6, 0x19, 0x7c, 0x55, 0x30, 0x9f, 0xfa, - 0xdc, 0xb9, 0x16, 0x73, 0xf0, 0x95, 0x3a, 0x5f, 0x79, 0x1c, - 0xb3, 0xd6, 0xff, 0x9a, 0x35, 0x50, 0x76, 0x13, 0xbc, 0xd9, - 0xee, 0x8b, 0x24, 0x41, 0x67, 0x02, 0xad, 0xc8, 0xe1, 0x84, - 0x2b, 0x4e, 0x68, 0x0d, 0xa2, 0xc7, 0xcc, 0xa9, 0x06, 0x63, - 0x45, 0x20, 0x8f, 0xea, 0xc3, 0xa6, 0x09, 0x6c, 0x4a, 0x2f, - 0x80, 0xe5, 0xd2, 0xb7, 0x18, 0x7d, 0x5b, 0x3e, 0x91, 0xf4, - 0xdd, 0xb8, 0x17, 0x72, 0x54, 0x31, 0x9e, 0xfb, 0x88, 0xed, - 0x42, 0x27, 0x01, 0x64, 0xcb, 0xae, 0x87, 0xe2, 0x4d, 0x28, - 0x0e, 0x6b, 0xc4, 0xa1, 0x96, 0xf3, 0x5c, 0x39, 0x1f, 0x7a, - 0xd5, 0xb0, 0x99, 0xfc, 0x53, 0x36, 0x10, 0x75, 0xda, 0xbf, - 0xb4, 0xd1, 0x7e, 0x1b, 0x3d, 0x58, 0xf7, 0x92, 0xbb, 0xde, - 0x71, 0x14, 0x32, 0x57, 0xf8, 0x9d, 0xaa, 0xcf, 0x60, 0x05, - 0x23, 0x46, 0xe9, 0x8c, 0xa5, 0xc0, 0x6f, 0x0a, 0x2c, 0x49, - 0xe6, 0x83, 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, - 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38, 0x2e, 0x48, - 0xe2, 0x84, 0xab, 0xcd, 0x67, 0x01, 0x39, 0x5f, 0xf5, 0x93, - 0xbc, 0xda, 0x70, 0x16, 0x5c, 0x3a, 0x90, 0xf6, 0xd9, 0xbf, - 0x15, 0x73, 0x4b, 0x2d, 0x87, 0xe1, 0xce, 0xa8, 0x02, 0x64, - 0x72, 0x14, 0xbe, 0xd8, 0xf7, 0x91, 0x3b, 0x5d, 0x65, 0x03, - 0xa9, 0xcf, 0xe0, 0x86, 0x2c, 0x4a, 0xb8, 0xde, 0x74, 0x12, - 0x3d, 0x5b, 0xf1, 0x97, 0xaf, 0xc9, 0x63, 0x05, 0x2a, 0x4c, - 0xe6, 0x80, 0x96, 0xf0, 0x5a, 0x3c, 0x13, 0x75, 0xdf, 0xb9, - 0x81, 0xe7, 0x4d, 0x2b, 0x04, 0x62, 0xc8, 0xae, 0xe4, 0x82, - 0x28, 0x4e, 0x61, 0x07, 0xad, 0xcb, 0xf3, 0x95, 0x3f, 0x59, - 0x76, 0x10, 0xba, 0xdc, 0xca, 0xac, 0x06, 0x60, 0x4f, 0x29, - 0x83, 0xe5, 0xdd, 0xbb, 0x11, 0x77, 0x58, 0x3e, 0x94, 0xf2, - 0x6d, 0x0b, 0xa1, 0xc7, 0xe8, 0x8e, 0x24, 0x42, 0x7a, 0x1c, - 0xb6, 0xd0, 0xff, 0x99, 0x33, 0x55, 0x43, 0x25, 0x8f, 0xe9, - 0xc6, 0xa0, 0x0a, 0x6c, 0x54, 0x32, 0x98, 0xfe, 0xd1, 0xb7, - 0x1d, 0x7b, 0x31, 0x57, 0xfd, 0x9b, 0xb4, 0xd2, 0x78, 0x1e, - 0x26, 0x40, 0xea, 0x8c, 0xa3, 0xc5, 0x6f, 0x09, 0x1f, 0x79, - 0xd3, 0xb5, 0x9a, 0xfc, 0x56, 0x30, 0x08, 0x6e, 0xc4, 0xa2, - 0x8d, 0xeb, 0x41, 0x27, 0xd5, 0xb3, 0x19, 0x7f, 0x50, 0x36, - 0x9c, 0xfa, 0xc2, 0xa4, 0x0e, 0x68, 0x47, 0x21, 0x8b, 0xed, - 0xfb, 0x9d, 0x37, 0x51, 0x7e, 0x18, 0xb2, 0xd4, 0xec, 0x8a, - 0x20, 0x46, 0x69, 0x0f, 0xa5, 0xc3, 0x89, 0xef, 0x45, 0x23, - 0x0c, 0x6a, 0xc0, 0xa6, 0x9e, 0xf8, 0x52, 0x34, 0x1b, 0x7d, - 0xd7, 0xb1, 0xa7, 0xc1, 0x6b, 0x0d, 0x22, 0x44, 0xee, 0x88, - 0xb0, 0xd6, 0x7c, 0x1a, 0x35, 0x53, 0xf9, 0x9f, 0x00, 0x67, - 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, - 0x9e, 0xf9, 0x50, 0x37, 0x3e, 0x59, 0xf0, 0x97, 0xbf, 0xd8, - 0x71, 0x16, 0x21, 0x46, 0xef, 0x88, 0xa0, 0xc7, 0x6e, 0x09, - 0x7c, 0x1b, 0xb2, 0xd5, 0xfd, 0x9a, 0x33, 0x54, 0x63, 0x04, - 0xad, 0xca, 0xe2, 0x85, 0x2c, 0x4b, 0x42, 0x25, 0x8c, 0xeb, - 0xc3, 0xa4, 0x0d, 0x6a, 0x5d, 0x3a, 0x93, 0xf4, 0xdc, 0xbb, - 0x12, 0x75, 0xf8, 0x9f, 0x36, 0x51, 0x79, 0x1e, 0xb7, 0xd0, - 0xe7, 0x80, 0x29, 0x4e, 0x66, 0x01, 0xa8, 0xcf, 0xc6, 0xa1, - 0x08, 0x6f, 0x47, 0x20, 0x89, 0xee, 0xd9, 0xbe, 0x17, 0x70, - 0x58, 0x3f, 0x96, 0xf1, 0x84, 0xe3, 0x4a, 0x2d, 0x05, 0x62, - 0xcb, 0xac, 0x9b, 0xfc, 0x55, 0x32, 0x1a, 0x7d, 0xd4, 0xb3, - 0xba, 0xdd, 0x74, 0x13, 0x3b, 0x5c, 0xf5, 0x92, 0xa5, 0xc2, - 0x6b, 0x0c, 0x24, 0x43, 0xea, 0x8d, 0xed, 0x8a, 0x23, 0x44, - 0x6c, 0x0b, 0xa2, 0xc5, 0xf2, 0x95, 0x3c, 0x5b, 0x73, 0x14, - 0xbd, 0xda, 0xd3, 0xb4, 0x1d, 0x7a, 0x52, 0x35, 0x9c, 0xfb, - 0xcc, 0xab, 0x02, 0x65, 0x4d, 0x2a, 0x83, 0xe4, 0x91, 0xf6, - 0x5f, 0x38, 0x10, 0x77, 0xde, 0xb9, 0x8e, 0xe9, 0x40, 0x27, - 0x0f, 0x68, 0xc1, 0xa6, 0xaf, 0xc8, 0x61, 0x06, 0x2e, 0x49, - 0xe0, 0x87, 0xb0, 0xd7, 0x7e, 0x19, 0x31, 0x56, 0xff, 0x98, - 0x15, 0x72, 0xdb, 0xbc, 0x94, 0xf3, 0x5a, 0x3d, 0x0a, 0x6d, - 0xc4, 0xa3, 0x8b, 0xec, 0x45, 0x22, 0x2b, 0x4c, 0xe5, 0x82, - 0xaa, 0xcd, 0x64, 0x03, 0x34, 0x53, 0xfa, 0x9d, 0xb5, 0xd2, - 0x7b, 0x1c, 0x69, 0x0e, 0xa7, 0xc0, 0xe8, 0x8f, 0x26, 0x41, - 0x76, 0x11, 0xb8, 0xdf, 0xf7, 0x90, 0x39, 0x5e, 0x57, 0x30, - 0x99, 0xfe, 0xd6, 0xb1, 0x18, 0x7f, 0x48, 0x2f, 0x86, 0xe1, - 0xc9, 0xae, 0x07, 0x60, 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, - 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62, - 0xce, 0xa6, 0x1e, 0x76, 0x73, 0x1b, 0xa3, 0xcb, 0xa9, 0xc1, - 0x79, 0x11, 0x14, 0x7c, 0xc4, 0xac, 0x81, 0xe9, 0x51, 0x39, - 0x3c, 0x54, 0xec, 0x84, 0xe6, 0x8e, 0x36, 0x5e, 0x5b, 0x33, - 0x8b, 0xe3, 0x4f, 0x27, 0x9f, 0xf7, 0xf2, 0x9a, 0x22, 0x4a, - 0x28, 0x40, 0xf8, 0x90, 0x95, 0xfd, 0x45, 0x2d, 0x1f, 0x77, - 0xcf, 0xa7, 0xa2, 0xca, 0x72, 0x1a, 0x78, 0x10, 0xa8, 0xc0, - 0xc5, 0xad, 0x15, 0x7d, 0xd1, 0xb9, 0x01, 0x69, 0x6c, 0x04, - 0xbc, 0xd4, 0xb6, 0xde, 0x66, 0x0e, 0x0b, 0x63, 0xdb, 0xb3, - 0x9e, 0xf6, 0x4e, 0x26, 0x23, 0x4b, 0xf3, 0x9b, 0xf9, 0x91, - 0x29, 0x41, 0x44, 0x2c, 0x94, 0xfc, 0x50, 0x38, 0x80, 0xe8, - 0xed, 0x85, 0x3d, 0x55, 0x37, 0x5f, 0xe7, 0x8f, 0x8a, 0xe2, - 0x5a, 0x32, 0x3e, 0x56, 0xee, 0x86, 0x83, 0xeb, 0x53, 0x3b, - 0x59, 0x31, 0x89, 0xe1, 0xe4, 0x8c, 0x34, 0x5c, 0xf0, 0x98, - 0x20, 0x48, 0x4d, 0x25, 0x9d, 0xf5, 0x97, 0xff, 0x47, 0x2f, - 0x2a, 0x42, 0xfa, 0x92, 0xbf, 0xd7, 0x6f, 0x07, 0x02, 0x6a, - 0xd2, 0xba, 0xd8, 0xb0, 0x08, 0x60, 0x65, 0x0d, 0xb5, 0xdd, - 0x71, 0x19, 0xa1, 0xc9, 0xcc, 0xa4, 0x1c, 0x74, 0x16, 0x7e, - 0xc6, 0xae, 0xab, 0xc3, 0x7b, 0x13, 0x21, 0x49, 0xf1, 0x99, - 0x9c, 0xf4, 0x4c, 0x24, 0x46, 0x2e, 0x96, 0xfe, 0xfb, 0x93, - 0x2b, 0x43, 0xef, 0x87, 0x3f, 0x57, 0x52, 0x3a, 0x82, 0xea, - 0x88, 0xe0, 0x58, 0x30, 0x35, 0x5d, 0xe5, 0x8d, 0xa0, 0xc8, - 0x70, 0x18, 0x1d, 0x75, 0xcd, 0xa5, 0xc7, 0xaf, 0x17, 0x7f, - 0x7a, 0x12, 0xaa, 0xc2, 0x6e, 0x06, 0xbe, 0xd6, 0xd3, 0xbb, - 0x03, 0x6b, 0x09, 0x61, 0xd9, 0xb1, 0xb4, 0xdc, 0x64, 0x0c, - 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, - 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d, 0xde, 0xb7, 0x0c, 0x65, - 0x67, 0x0e, 0xb5, 0xdc, 0xb1, 0xd8, 0x63, 0x0a, 0x08, 0x61, - 0xda, 0xb3, 0xa1, 0xc8, 0x73, 0x1a, 0x18, 0x71, 0xca, 0xa3, - 0xce, 0xa7, 0x1c, 0x75, 0x77, 0x1e, 0xa5, 0xcc, 0x7f, 0x16, - 0xad, 0xc4, 0xc6, 0xaf, 0x14, 0x7d, 0x10, 0x79, 0xc2, 0xab, - 0xa9, 0xc0, 0x7b, 0x12, 0x5f, 0x36, 0x8d, 0xe4, 0xe6, 0x8f, - 0x34, 0x5d, 0x30, 0x59, 0xe2, 0x8b, 0x89, 0xe0, 0x5b, 0x32, - 0x81, 0xe8, 0x53, 0x3a, 0x38, 0x51, 0xea, 0x83, 0xee, 0x87, - 0x3c, 0x55, 0x57, 0x3e, 0x85, 0xec, 0xfe, 0x97, 0x2c, 0x45, - 0x47, 0x2e, 0x95, 0xfc, 0x91, 0xf8, 0x43, 0x2a, 0x28, 0x41, - 0xfa, 0x93, 0x20, 0x49, 0xf2, 0x9b, 0x99, 0xf0, 0x4b, 0x22, - 0x4f, 0x26, 0x9d, 0xf4, 0xf6, 0x9f, 0x24, 0x4d, 0xbe, 0xd7, - 0x6c, 0x05, 0x07, 0x6e, 0xd5, 0xbc, 0xd1, 0xb8, 0x03, 0x6a, - 0x68, 0x01, 0xba, 0xd3, 0x60, 0x09, 0xb2, 0xdb, 0xd9, 0xb0, - 0x0b, 0x62, 0x0f, 0x66, 0xdd, 0xb4, 0xb6, 0xdf, 0x64, 0x0d, - 0x1f, 0x76, 0xcd, 0xa4, 0xa6, 0xcf, 0x74, 0x1d, 0x70, 0x19, - 0xa2, 0xcb, 0xc9, 0xa0, 0x1b, 0x72, 0xc1, 0xa8, 0x13, 0x7a, - 0x78, 0x11, 0xaa, 0xc3, 0xae, 0xc7, 0x7c, 0x15, 0x17, 0x7e, - 0xc5, 0xac, 0xe1, 0x88, 0x33, 0x5a, 0x58, 0x31, 0x8a, 0xe3, - 0x8e, 0xe7, 0x5c, 0x35, 0x37, 0x5e, 0xe5, 0x8c, 0x3f, 0x56, - 0xed, 0x84, 0x86, 0xef, 0x54, 0x3d, 0x50, 0x39, 0x82, 0xeb, - 0xe9, 0x80, 0x3b, 0x52, 0x40, 0x29, 0x92, 0xfb, 0xf9, 0x90, - 0x2b, 0x42, 0x2f, 0x46, 0xfd, 0x94, 0x96, 0xff, 0x44, 0x2d, - 0x9e, 0xf7, 0x4c, 0x25, 0x27, 0x4e, 0xf5, 0x9c, 0xf1, 0x98, - 0x23, 0x4a, 0x48, 0x21, 0x9a, 0xf3, 0x00, 0x6a, 0xd4, 0xbe, - 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, - 0x16, 0x7c, 0xee, 0x84, 0x3a, 0x50, 0x5b, 0x31, 0x8f, 0xe5, - 0x99, 0xf3, 0x4d, 0x27, 0x2c, 0x46, 0xf8, 0x92, 0xc1, 0xab, - 0x15, 0x7f, 0x74, 0x1e, 0xa0, 0xca, 0xb6, 0xdc, 0x62, 0x08, - 0x03, 0x69, 0xd7, 0xbd, 0x2f, 0x45, 0xfb, 0x91, 0x9a, 0xf0, - 0x4e, 0x24, 0x58, 0x32, 0x8c, 0xe6, 0xed, 0x87, 0x39, 0x53, - 0x9f, 0xf5, 0x4b, 0x21, 0x2a, 0x40, 0xfe, 0x94, 0xe8, 0x82, - 0x3c, 0x56, 0x5d, 0x37, 0x89, 0xe3, 0x71, 0x1b, 0xa5, 0xcf, - 0xc4, 0xae, 0x10, 0x7a, 0x06, 0x6c, 0xd2, 0xb8, 0xb3, 0xd9, - 0x67, 0x0d, 0x5e, 0x34, 0x8a, 0xe0, 0xeb, 0x81, 0x3f, 0x55, - 0x29, 0x43, 0xfd, 0x97, 0x9c, 0xf6, 0x48, 0x22, 0xb0, 0xda, - 0x64, 0x0e, 0x05, 0x6f, 0xd1, 0xbb, 0xc7, 0xad, 0x13, 0x79, - 0x72, 0x18, 0xa6, 0xcc, 0x23, 0x49, 0xf7, 0x9d, 0x96, 0xfc, - 0x42, 0x28, 0x54, 0x3e, 0x80, 0xea, 0xe1, 0x8b, 0x35, 0x5f, - 0xcd, 0xa7, 0x19, 0x73, 0x78, 0x12, 0xac, 0xc6, 0xba, 0xd0, - 0x6e, 0x04, 0x0f, 0x65, 0xdb, 0xb1, 0xe2, 0x88, 0x36, 0x5c, - 0x57, 0x3d, 0x83, 0xe9, 0x95, 0xff, 0x41, 0x2b, 0x20, 0x4a, - 0xf4, 0x9e, 0x0c, 0x66, 0xd8, 0xb2, 0xb9, 0xd3, 0x6d, 0x07, - 0x7b, 0x11, 0xaf, 0xc5, 0xce, 0xa4, 0x1a, 0x70, 0xbc, 0xd6, - 0x68, 0x02, 0x09, 0x63, 0xdd, 0xb7, 0xcb, 0xa1, 0x1f, 0x75, - 0x7e, 0x14, 0xaa, 0xc0, 0x52, 0x38, 0x86, 0xec, 0xe7, 0x8d, - 0x33, 0x59, 0x25, 0x4f, 0xf1, 0x9b, 0x90, 0xfa, 0x44, 0x2e, - 0x7d, 0x17, 0xa9, 0xc3, 0xc8, 0xa2, 0x1c, 0x76, 0x0a, 0x60, - 0xde, 0xb4, 0xbf, 0xd5, 0x6b, 0x01, 0x93, 0xf9, 0x47, 0x2d, - 0x26, 0x4c, 0xf2, 0x98, 0xe4, 0x8e, 0x30, 0x5a, 0x51, 0x3b, - 0x85, 0xef, 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, - 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73, 0xfe, 0x95, - 0x28, 0x43, 0x4f, 0x24, 0x99, 0xf2, 0x81, 0xea, 0x57, 0x3c, - 0x30, 0x5b, 0xe6, 0x8d, 0xe1, 0x8a, 0x37, 0x5c, 0x50, 0x3b, - 0x86, 0xed, 0x9e, 0xf5, 0x48, 0x23, 0x2f, 0x44, 0xf9, 0x92, - 0x1f, 0x74, 0xc9, 0xa2, 0xae, 0xc5, 0x78, 0x13, 0x60, 0x0b, - 0xb6, 0xdd, 0xd1, 0xba, 0x07, 0x6c, 0xdf, 0xb4, 0x09, 0x62, - 0x6e, 0x05, 0xb8, 0xd3, 0xa0, 0xcb, 0x76, 0x1d, 0x11, 0x7a, - 0xc7, 0xac, 0x21, 0x4a, 0xf7, 0x9c, 0x90, 0xfb, 0x46, 0x2d, - 0x5e, 0x35, 0x88, 0xe3, 0xef, 0x84, 0x39, 0x52, 0x3e, 0x55, - 0xe8, 0x83, 0x8f, 0xe4, 0x59, 0x32, 0x41, 0x2a, 0x97, 0xfc, - 0xf0, 0x9b, 0x26, 0x4d, 0xc0, 0xab, 0x16, 0x7d, 0x71, 0x1a, - 0xa7, 0xcc, 0xbf, 0xd4, 0x69, 0x02, 0x0e, 0x65, 0xd8, 0xb3, - 0xa3, 0xc8, 0x75, 0x1e, 0x12, 0x79, 0xc4, 0xaf, 0xdc, 0xb7, - 0x0a, 0x61, 0x6d, 0x06, 0xbb, 0xd0, 0x5d, 0x36, 0x8b, 0xe0, - 0xec, 0x87, 0x3a, 0x51, 0x22, 0x49, 0xf4, 0x9f, 0x93, 0xf8, - 0x45, 0x2e, 0x42, 0x29, 0x94, 0xff, 0xf3, 0x98, 0x25, 0x4e, - 0x3d, 0x56, 0xeb, 0x80, 0x8c, 0xe7, 0x5a, 0x31, 0xbc, 0xd7, - 0x6a, 0x01, 0x0d, 0x66, 0xdb, 0xb0, 0xc3, 0xa8, 0x15, 0x7e, - 0x72, 0x19, 0xa4, 0xcf, 0x7c, 0x17, 0xaa, 0xc1, 0xcd, 0xa6, - 0x1b, 0x70, 0x03, 0x68, 0xd5, 0xbe, 0xb2, 0xd9, 0x64, 0x0f, - 0x82, 0xe9, 0x54, 0x3f, 0x33, 0x58, 0xe5, 0x8e, 0xfd, 0x96, - 0x2b, 0x40, 0x4c, 0x27, 0x9a, 0xf1, 0x9d, 0xf6, 0x4b, 0x20, - 0x2c, 0x47, 0xfa, 0x91, 0xe2, 0x89, 0x34, 0x5f, 0x53, 0x38, - 0x85, 0xee, 0x63, 0x08, 0xb5, 0xde, 0xd2, 0xb9, 0x04, 0x6f, - 0x1c, 0x77, 0xca, 0xa1, 0xad, 0xc6, 0x7b, 0x10, 0x00, 0x6c, - 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, - 0xea, 0x86, 0x32, 0x5e, 0x8e, 0xe2, 0x56, 0x3a, 0x23, 0x4f, - 0xfb, 0x97, 0xc9, 0xa5, 0x11, 0x7d, 0x64, 0x08, 0xbc, 0xd0, - 0x01, 0x6d, 0xd9, 0xb5, 0xac, 0xc0, 0x74, 0x18, 0x46, 0x2a, - 0x9e, 0xf2, 0xeb, 0x87, 0x33, 0x5f, 0x8f, 0xe3, 0x57, 0x3b, - 0x22, 0x4e, 0xfa, 0x96, 0xc8, 0xa4, 0x10, 0x7c, 0x65, 0x09, - 0xbd, 0xd1, 0x02, 0x6e, 0xda, 0xb6, 0xaf, 0xc3, 0x77, 0x1b, - 0x45, 0x29, 0x9d, 0xf1, 0xe8, 0x84, 0x30, 0x5c, 0x8c, 0xe0, - 0x54, 0x38, 0x21, 0x4d, 0xf9, 0x95, 0xcb, 0xa7, 0x13, 0x7f, - 0x66, 0x0a, 0xbe, 0xd2, 0x03, 0x6f, 0xdb, 0xb7, 0xae, 0xc2, - 0x76, 0x1a, 0x44, 0x28, 0x9c, 0xf0, 0xe9, 0x85, 0x31, 0x5d, - 0x8d, 0xe1, 0x55, 0x39, 0x20, 0x4c, 0xf8, 0x94, 0xca, 0xa6, - 0x12, 0x7e, 0x67, 0x0b, 0xbf, 0xd3, 0x04, 0x68, 0xdc, 0xb0, - 0xa9, 0xc5, 0x71, 0x1d, 0x43, 0x2f, 0x9b, 0xf7, 0xee, 0x82, - 0x36, 0x5a, 0x8a, 0xe6, 0x52, 0x3e, 0x27, 0x4b, 0xff, 0x93, - 0xcd, 0xa1, 0x15, 0x79, 0x60, 0x0c, 0xb8, 0xd4, 0x05, 0x69, - 0xdd, 0xb1, 0xa8, 0xc4, 0x70, 0x1c, 0x42, 0x2e, 0x9a, 0xf6, - 0xef, 0x83, 0x37, 0x5b, 0x8b, 0xe7, 0x53, 0x3f, 0x26, 0x4a, - 0xfe, 0x92, 0xcc, 0xa0, 0x14, 0x78, 0x61, 0x0d, 0xb9, 0xd5, - 0x06, 0x6a, 0xde, 0xb2, 0xab, 0xc7, 0x73, 0x1f, 0x41, 0x2d, - 0x99, 0xf5, 0xec, 0x80, 0x34, 0x58, 0x88, 0xe4, 0x50, 0x3c, - 0x25, 0x49, 0xfd, 0x91, 0xcf, 0xa3, 0x17, 0x7b, 0x62, 0x0e, - 0xba, 0xd6, 0x07, 0x6b, 0xdf, 0xb3, 0xaa, 0xc6, 0x72, 0x1e, - 0x40, 0x2c, 0x98, 0xf4, 0xed, 0x81, 0x35, 0x59, 0x89, 0xe5, - 0x51, 0x3d, 0x24, 0x48, 0xfc, 0x90, 0xce, 0xa2, 0x16, 0x7a, - 0x63, 0x0f, 0xbb, 0xd7, 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, - 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51, - 0x9e, 0xf3, 0x44, 0x29, 0x37, 0x5a, 0xed, 0x80, 0xd1, 0xbc, - 0x0b, 0x66, 0x78, 0x15, 0xa2, 0xcf, 0x21, 0x4c, 0xfb, 0x96, - 0x88, 0xe5, 0x52, 0x3f, 0x6e, 0x03, 0xb4, 0xd9, 0xc7, 0xaa, - 0x1d, 0x70, 0xbf, 0xd2, 0x65, 0x08, 0x16, 0x7b, 0xcc, 0xa1, - 0xf0, 0x9d, 0x2a, 0x47, 0x59, 0x34, 0x83, 0xee, 0x42, 0x2f, - 0x98, 0xf5, 0xeb, 0x86, 0x31, 0x5c, 0x0d, 0x60, 0xd7, 0xba, - 0xa4, 0xc9, 0x7e, 0x13, 0xdc, 0xb1, 0x06, 0x6b, 0x75, 0x18, - 0xaf, 0xc2, 0x93, 0xfe, 0x49, 0x24, 0x3a, 0x57, 0xe0, 0x8d, - 0x63, 0x0e, 0xb9, 0xd4, 0xca, 0xa7, 0x10, 0x7d, 0x2c, 0x41, - 0xf6, 0x9b, 0x85, 0xe8, 0x5f, 0x32, 0xfd, 0x90, 0x27, 0x4a, - 0x54, 0x39, 0x8e, 0xe3, 0xb2, 0xdf, 0x68, 0x05, 0x1b, 0x76, - 0xc1, 0xac, 0x84, 0xe9, 0x5e, 0x33, 0x2d, 0x40, 0xf7, 0x9a, - 0xcb, 0xa6, 0x11, 0x7c, 0x62, 0x0f, 0xb8, 0xd5, 0x1a, 0x77, - 0xc0, 0xad, 0xb3, 0xde, 0x69, 0x04, 0x55, 0x38, 0x8f, 0xe2, - 0xfc, 0x91, 0x26, 0x4b, 0xa5, 0xc8, 0x7f, 0x12, 0x0c, 0x61, - 0xd6, 0xbb, 0xea, 0x87, 0x30, 0x5d, 0x43, 0x2e, 0x99, 0xf4, - 0x3b, 0x56, 0xe1, 0x8c, 0x92, 0xff, 0x48, 0x25, 0x74, 0x19, - 0xae, 0xc3, 0xdd, 0xb0, 0x07, 0x6a, 0xc6, 0xab, 0x1c, 0x71, - 0x6f, 0x02, 0xb5, 0xd8, 0x89, 0xe4, 0x53, 0x3e, 0x20, 0x4d, - 0xfa, 0x97, 0x58, 0x35, 0x82, 0xef, 0xf1, 0x9c, 0x2b, 0x46, - 0x17, 0x7a, 0xcd, 0xa0, 0xbe, 0xd3, 0x64, 0x09, 0xe7, 0x8a, - 0x3d, 0x50, 0x4e, 0x23, 0x94, 0xf9, 0xa8, 0xc5, 0x72, 0x1f, - 0x01, 0x6c, 0xdb, 0xb6, 0x79, 0x14, 0xa3, 0xce, 0xd0, 0xbd, - 0x0a, 0x67, 0x36, 0x5b, 0xec, 0x81, 0x9f, 0xf2, 0x45, 0x28, - 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, - 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40, 0xae, 0xc0, 0x72, 0x1c, - 0x0b, 0x65, 0xd7, 0xb9, 0xf9, 0x97, 0x25, 0x4b, 0x5c, 0x32, - 0x80, 0xee, 0x41, 0x2f, 0x9d, 0xf3, 0xe4, 0x8a, 0x38, 0x56, - 0x16, 0x78, 0xca, 0xa4, 0xb3, 0xdd, 0x6f, 0x01, 0xef, 0x81, - 0x33, 0x5d, 0x4a, 0x24, 0x96, 0xf8, 0xb8, 0xd6, 0x64, 0x0a, - 0x1d, 0x73, 0xc1, 0xaf, 0x82, 0xec, 0x5e, 0x30, 0x27, 0x49, - 0xfb, 0x95, 0xd5, 0xbb, 0x09, 0x67, 0x70, 0x1e, 0xac, 0xc2, - 0x2c, 0x42, 0xf0, 0x9e, 0x89, 0xe7, 0x55, 0x3b, 0x7b, 0x15, - 0xa7, 0xc9, 0xde, 0xb0, 0x02, 0x6c, 0xc3, 0xad, 0x1f, 0x71, - 0x66, 0x08, 0xba, 0xd4, 0x94, 0xfa, 0x48, 0x26, 0x31, 0x5f, - 0xed, 0x83, 0x6d, 0x03, 0xb1, 0xdf, 0xc8, 0xa6, 0x14, 0x7a, - 0x3a, 0x54, 0xe6, 0x88, 0x9f, 0xf1, 0x43, 0x2d, 0x19, 0x77, - 0xc5, 0xab, 0xbc, 0xd2, 0x60, 0x0e, 0x4e, 0x20, 0x92, 0xfc, - 0xeb, 0x85, 0x37, 0x59, 0xb7, 0xd9, 0x6b, 0x05, 0x12, 0x7c, - 0xce, 0xa0, 0xe0, 0x8e, 0x3c, 0x52, 0x45, 0x2b, 0x99, 0xf7, - 0x58, 0x36, 0x84, 0xea, 0xfd, 0x93, 0x21, 0x4f, 0x0f, 0x61, - 0xd3, 0xbd, 0xaa, 0xc4, 0x76, 0x18, 0xf6, 0x98, 0x2a, 0x44, - 0x53, 0x3d, 0x8f, 0xe1, 0xa1, 0xcf, 0x7d, 0x13, 0x04, 0x6a, - 0xd8, 0xb6, 0x9b, 0xf5, 0x47, 0x29, 0x3e, 0x50, 0xe2, 0x8c, - 0xcc, 0xa2, 0x10, 0x7e, 0x69, 0x07, 0xb5, 0xdb, 0x35, 0x5b, - 0xe9, 0x87, 0x90, 0xfe, 0x4c, 0x22, 0x62, 0x0c, 0xbe, 0xd0, - 0xc7, 0xa9, 0x1b, 0x75, 0xda, 0xb4, 0x06, 0x68, 0x7f, 0x11, - 0xa3, 0xcd, 0x8d, 0xe3, 0x51, 0x3f, 0x28, 0x46, 0xf4, 0x9a, - 0x74, 0x1a, 0xa8, 0xc6, 0xd1, 0xbf, 0x0d, 0x63, 0x23, 0x4d, - 0xff, 0x91, 0x86, 0xe8, 0x5a, 0x34, 0x00, 0x6f, 0xde, 0xb1, - 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, - 0x20, 0x4f, 0xbe, 0xd1, 0x60, 0x0f, 0x1f, 0x70, 0xc1, 0xae, - 0xe1, 0x8e, 0x3f, 0x50, 0x40, 0x2f, 0x9e, 0xf1, 0x61, 0x0e, - 0xbf, 0xd0, 0xc0, 0xaf, 0x1e, 0x71, 0x3e, 0x51, 0xe0, 0x8f, - 0x9f, 0xf0, 0x41, 0x2e, 0xdf, 0xb0, 0x01, 0x6e, 0x7e, 0x11, - 0xa0, 0xcf, 0x80, 0xef, 0x5e, 0x31, 0x21, 0x4e, 0xff, 0x90, - 0xc2, 0xad, 0x1c, 0x73, 0x63, 0x0c, 0xbd, 0xd2, 0x9d, 0xf2, - 0x43, 0x2c, 0x3c, 0x53, 0xe2, 0x8d, 0x7c, 0x13, 0xa2, 0xcd, - 0xdd, 0xb2, 0x03, 0x6c, 0x23, 0x4c, 0xfd, 0x92, 0x82, 0xed, - 0x5c, 0x33, 0xa3, 0xcc, 0x7d, 0x12, 0x02, 0x6d, 0xdc, 0xb3, - 0xfc, 0x93, 0x22, 0x4d, 0x5d, 0x32, 0x83, 0xec, 0x1d, 0x72, - 0xc3, 0xac, 0xbc, 0xd3, 0x62, 0x0d, 0x42, 0x2d, 0x9c, 0xf3, - 0xe3, 0x8c, 0x3d, 0x52, 0x99, 0xf6, 0x47, 0x28, 0x38, 0x57, - 0xe6, 0x89, 0xc6, 0xa9, 0x18, 0x77, 0x67, 0x08, 0xb9, 0xd6, - 0x27, 0x48, 0xf9, 0x96, 0x86, 0xe9, 0x58, 0x37, 0x78, 0x17, - 0xa6, 0xc9, 0xd9, 0xb6, 0x07, 0x68, 0xf8, 0x97, 0x26, 0x49, - 0x59, 0x36, 0x87, 0xe8, 0xa7, 0xc8, 0x79, 0x16, 0x06, 0x69, - 0xd8, 0xb7, 0x46, 0x29, 0x98, 0xf7, 0xe7, 0x88, 0x39, 0x56, - 0x19, 0x76, 0xc7, 0xa8, 0xb8, 0xd7, 0x66, 0x09, 0x5b, 0x34, - 0x85, 0xea, 0xfa, 0x95, 0x24, 0x4b, 0x04, 0x6b, 0xda, 0xb5, - 0xa5, 0xca, 0x7b, 0x14, 0xe5, 0x8a, 0x3b, 0x54, 0x44, 0x2b, - 0x9a, 0xf5, 0xba, 0xd5, 0x64, 0x0b, 0x1b, 0x74, 0xc5, 0xaa, - 0x3a, 0x55, 0xe4, 0x8b, 0x9b, 0xf4, 0x45, 0x2a, 0x65, 0x0a, - 0xbb, 0xd4, 0xc4, 0xab, 0x1a, 0x75, 0x84, 0xeb, 0x5a, 0x35, - 0x25, 0x4a, 0xfb, 0x94, 0xdb, 0xb4, 0x05, 0x6a, 0x7a, 0x15, - 0xa4, 0xcb, 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, - 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea, 0x53, 0x23, - 0xb3, 0xc3, 0x8e, 0xfe, 0x6e, 0x1e, 0xf4, 0x84, 0x14, 0x64, - 0x29, 0x59, 0xc9, 0xb9, 0xa6, 0xd6, 0x46, 0x36, 0x7b, 0x0b, - 0x9b, 0xeb, 0x01, 0x71, 0xe1, 0x91, 0xdc, 0xac, 0x3c, 0x4c, - 0xf5, 0x85, 0x15, 0x65, 0x28, 0x58, 0xc8, 0xb8, 0x52, 0x22, - 0xb2, 0xc2, 0x8f, 0xff, 0x6f, 0x1f, 0x51, 0x21, 0xb1, 0xc1, - 0x8c, 0xfc, 0x6c, 0x1c, 0xf6, 0x86, 0x16, 0x66, 0x2b, 0x5b, - 0xcb, 0xbb, 0x02, 0x72, 0xe2, 0x92, 0xdf, 0xaf, 0x3f, 0x4f, - 0xa5, 0xd5, 0x45, 0x35, 0x78, 0x08, 0x98, 0xe8, 0xf7, 0x87, - 0x17, 0x67, 0x2a, 0x5a, 0xca, 0xba, 0x50, 0x20, 0xb0, 0xc0, - 0x8d, 0xfd, 0x6d, 0x1d, 0xa4, 0xd4, 0x44, 0x34, 0x79, 0x09, - 0x99, 0xe9, 0x03, 0x73, 0xe3, 0x93, 0xde, 0xae, 0x3e, 0x4e, - 0xa2, 0xd2, 0x42, 0x32, 0x7f, 0x0f, 0x9f, 0xef, 0x05, 0x75, - 0xe5, 0x95, 0xd8, 0xa8, 0x38, 0x48, 0xf1, 0x81, 0x11, 0x61, - 0x2c, 0x5c, 0xcc, 0xbc, 0x56, 0x26, 0xb6, 0xc6, 0x8b, 0xfb, - 0x6b, 0x1b, 0x04, 0x74, 0xe4, 0x94, 0xd9, 0xa9, 0x39, 0x49, - 0xa3, 0xd3, 0x43, 0x33, 0x7e, 0x0e, 0x9e, 0xee, 0x57, 0x27, - 0xb7, 0xc7, 0x8a, 0xfa, 0x6a, 0x1a, 0xf0, 0x80, 0x10, 0x60, - 0x2d, 0x5d, 0xcd, 0xbd, 0xf3, 0x83, 0x13, 0x63, 0x2e, 0x5e, - 0xce, 0xbe, 0x54, 0x24, 0xb4, 0xc4, 0x89, 0xf9, 0x69, 0x19, - 0xa0, 0xd0, 0x40, 0x30, 0x7d, 0x0d, 0x9d, 0xed, 0x07, 0x77, - 0xe7, 0x97, 0xda, 0xaa, 0x3a, 0x4a, 0x55, 0x25, 0xb5, 0xc5, - 0x88, 0xf8, 0x68, 0x18, 0xf2, 0x82, 0x12, 0x62, 0x2f, 0x5f, - 0xcf, 0xbf, 0x06, 0x76, 0xe6, 0x96, 0xdb, 0xab, 0x3b, 0x4b, - 0xa1, 0xd1, 0x41, 0x31, 0x7c, 0x0c, 0x9c, 0xec, 0x00, 0x71, - 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, - 0x76, 0x07, 0x94, 0xe5, 0x43, 0x32, 0xa1, 0xd0, 0x9a, 0xeb, - 0x78, 0x09, 0xec, 0x9d, 0x0e, 0x7f, 0x35, 0x44, 0xd7, 0xa6, - 0x86, 0xf7, 0x64, 0x15, 0x5f, 0x2e, 0xbd, 0xcc, 0x29, 0x58, - 0xcb, 0xba, 0xf0, 0x81, 0x12, 0x63, 0xc5, 0xb4, 0x27, 0x56, - 0x1c, 0x6d, 0xfe, 0x8f, 0x6a, 0x1b, 0x88, 0xf9, 0xb3, 0xc2, - 0x51, 0x20, 0x11, 0x60, 0xf3, 0x82, 0xc8, 0xb9, 0x2a, 0x5b, - 0xbe, 0xcf, 0x5c, 0x2d, 0x67, 0x16, 0x85, 0xf4, 0x52, 0x23, - 0xb0, 0xc1, 0x8b, 0xfa, 0x69, 0x18, 0xfd, 0x8c, 0x1f, 0x6e, - 0x24, 0x55, 0xc6, 0xb7, 0x97, 0xe6, 0x75, 0x04, 0x4e, 0x3f, - 0xac, 0xdd, 0x38, 0x49, 0xda, 0xab, 0xe1, 0x90, 0x03, 0x72, - 0xd4, 0xa5, 0x36, 0x47, 0x0d, 0x7c, 0xef, 0x9e, 0x7b, 0x0a, - 0x99, 0xe8, 0xa2, 0xd3, 0x40, 0x31, 0x22, 0x53, 0xc0, 0xb1, - 0xfb, 0x8a, 0x19, 0x68, 0x8d, 0xfc, 0x6f, 0x1e, 0x54, 0x25, - 0xb6, 0xc7, 0x61, 0x10, 0x83, 0xf2, 0xb8, 0xc9, 0x5a, 0x2b, - 0xce, 0xbf, 0x2c, 0x5d, 0x17, 0x66, 0xf5, 0x84, 0xa4, 0xd5, - 0x46, 0x37, 0x7d, 0x0c, 0x9f, 0xee, 0x0b, 0x7a, 0xe9, 0x98, - 0xd2, 0xa3, 0x30, 0x41, 0xe7, 0x96, 0x05, 0x74, 0x3e, 0x4f, - 0xdc, 0xad, 0x48, 0x39, 0xaa, 0xdb, 0x91, 0xe0, 0x73, 0x02, - 0x33, 0x42, 0xd1, 0xa0, 0xea, 0x9b, 0x08, 0x79, 0x9c, 0xed, - 0x7e, 0x0f, 0x45, 0x34, 0xa7, 0xd6, 0x70, 0x01, 0x92, 0xe3, - 0xa9, 0xd8, 0x4b, 0x3a, 0xdf, 0xae, 0x3d, 0x4c, 0x06, 0x77, - 0xe4, 0x95, 0xb5, 0xc4, 0x57, 0x26, 0x6c, 0x1d, 0x8e, 0xff, - 0x1a, 0x6b, 0xf8, 0x89, 0xc3, 0xb2, 0x21, 0x50, 0xf6, 0x87, - 0x14, 0x65, 0x2f, 0x5e, 0xcd, 0xbc, 0x59, 0x28, 0xbb, 0xca, - 0x80, 0xf1, 0x62, 0x13, 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, - 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4, - 0x73, 0x01, 0x97, 0xe5, 0xa6, 0xd4, 0x42, 0x30, 0xc4, 0xb6, - 0x20, 0x52, 0x11, 0x63, 0xf5, 0x87, 0xe6, 0x94, 0x02, 0x70, - 0x33, 0x41, 0xd7, 0xa5, 0x51, 0x23, 0xb5, 0xc7, 0x84, 0xf6, - 0x60, 0x12, 0x95, 0xe7, 0x71, 0x03, 0x40, 0x32, 0xa4, 0xd6, - 0x22, 0x50, 0xc6, 0xb4, 0xf7, 0x85, 0x13, 0x61, 0xd1, 0xa3, - 0x35, 0x47, 0x04, 0x76, 0xe0, 0x92, 0x66, 0x14, 0x82, 0xf0, - 0xb3, 0xc1, 0x57, 0x25, 0xa2, 0xd0, 0x46, 0x34, 0x77, 0x05, - 0x93, 0xe1, 0x15, 0x67, 0xf1, 0x83, 0xc0, 0xb2, 0x24, 0x56, - 0x37, 0x45, 0xd3, 0xa1, 0xe2, 0x90, 0x06, 0x74, 0x80, 0xf2, - 0x64, 0x16, 0x55, 0x27, 0xb1, 0xc3, 0x44, 0x36, 0xa0, 0xd2, - 0x91, 0xe3, 0x75, 0x07, 0xf3, 0x81, 0x17, 0x65, 0x26, 0x54, - 0xc2, 0xb0, 0xbf, 0xcd, 0x5b, 0x29, 0x6a, 0x18, 0x8e, 0xfc, - 0x08, 0x7a, 0xec, 0x9e, 0xdd, 0xaf, 0x39, 0x4b, 0xcc, 0xbe, - 0x28, 0x5a, 0x19, 0x6b, 0xfd, 0x8f, 0x7b, 0x09, 0x9f, 0xed, - 0xae, 0xdc, 0x4a, 0x38, 0x59, 0x2b, 0xbd, 0xcf, 0x8c, 0xfe, - 0x68, 0x1a, 0xee, 0x9c, 0x0a, 0x78, 0x3b, 0x49, 0xdf, 0xad, - 0x2a, 0x58, 0xce, 0xbc, 0xff, 0x8d, 0x1b, 0x69, 0x9d, 0xef, - 0x79, 0x0b, 0x48, 0x3a, 0xac, 0xde, 0x6e, 0x1c, 0x8a, 0xf8, - 0xbb, 0xc9, 0x5f, 0x2d, 0xd9, 0xab, 0x3d, 0x4f, 0x0c, 0x7e, - 0xe8, 0x9a, 0x1d, 0x6f, 0xf9, 0x8b, 0xc8, 0xba, 0x2c, 0x5e, - 0xaa, 0xd8, 0x4e, 0x3c, 0x7f, 0x0d, 0x9b, 0xe9, 0x88, 0xfa, - 0x6c, 0x1e, 0x5d, 0x2f, 0xb9, 0xcb, 0x3f, 0x4d, 0xdb, 0xa9, - 0xea, 0x98, 0x0e, 0x7c, 0xfb, 0x89, 0x1f, 0x6d, 0x2e, 0x5c, - 0xca, 0xb8, 0x4c, 0x3e, 0xa8, 0xda, 0x99, 0xeb, 0x7d, 0x0f, - 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, - 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb, 0x63, 0x10, 0x85, 0xf6, - 0xb2, 0xc1, 0x54, 0x27, 0xdc, 0xaf, 0x3a, 0x49, 0x0d, 0x7e, - 0xeb, 0x98, 0xc6, 0xb5, 0x20, 0x53, 0x17, 0x64, 0xf1, 0x82, - 0x79, 0x0a, 0x9f, 0xec, 0xa8, 0xdb, 0x4e, 0x3d, 0xa5, 0xd6, - 0x43, 0x30, 0x74, 0x07, 0x92, 0xe1, 0x1a, 0x69, 0xfc, 0x8f, - 0xcb, 0xb8, 0x2d, 0x5e, 0x91, 0xe2, 0x77, 0x04, 0x40, 0x33, - 0xa6, 0xd5, 0x2e, 0x5d, 0xc8, 0xbb, 0xff, 0x8c, 0x19, 0x6a, - 0xf2, 0x81, 0x14, 0x67, 0x23, 0x50, 0xc5, 0xb6, 0x4d, 0x3e, - 0xab, 0xd8, 0x9c, 0xef, 0x7a, 0x09, 0x57, 0x24, 0xb1, 0xc2, - 0x86, 0xf5, 0x60, 0x13, 0xe8, 0x9b, 0x0e, 0x7d, 0x39, 0x4a, - 0xdf, 0xac, 0x34, 0x47, 0xd2, 0xa1, 0xe5, 0x96, 0x03, 0x70, - 0x8b, 0xf8, 0x6d, 0x1e, 0x5a, 0x29, 0xbc, 0xcf, 0x3f, 0x4c, - 0xd9, 0xaa, 0xee, 0x9d, 0x08, 0x7b, 0x80, 0xf3, 0x66, 0x15, - 0x51, 0x22, 0xb7, 0xc4, 0x5c, 0x2f, 0xba, 0xc9, 0x8d, 0xfe, - 0x6b, 0x18, 0xe3, 0x90, 0x05, 0x76, 0x32, 0x41, 0xd4, 0xa7, - 0xf9, 0x8a, 0x1f, 0x6c, 0x28, 0x5b, 0xce, 0xbd, 0x46, 0x35, - 0xa0, 0xd3, 0x97, 0xe4, 0x71, 0x02, 0x9a, 0xe9, 0x7c, 0x0f, - 0x4b, 0x38, 0xad, 0xde, 0x25, 0x56, 0xc3, 0xb0, 0xf4, 0x87, - 0x12, 0x61, 0xae, 0xdd, 0x48, 0x3b, 0x7f, 0x0c, 0x99, 0xea, - 0x11, 0x62, 0xf7, 0x84, 0xc0, 0xb3, 0x26, 0x55, 0xcd, 0xbe, - 0x2b, 0x58, 0x1c, 0x6f, 0xfa, 0x89, 0x72, 0x01, 0x94, 0xe7, - 0xa3, 0xd0, 0x45, 0x36, 0x68, 0x1b, 0x8e, 0xfd, 0xb9, 0xca, - 0x5f, 0x2c, 0xd7, 0xa4, 0x31, 0x42, 0x06, 0x75, 0xe0, 0x93, - 0x0b, 0x78, 0xed, 0x9e, 0xda, 0xa9, 0x3c, 0x4f, 0xb4, 0xc7, - 0x52, 0x21, 0x65, 0x16, 0x83, 0xf0, 0x00, 0x74, 0xe8, 0x9c, - 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, - 0xa2, 0xd6, 0x13, 0x67, 0xfb, 0x8f, 0xde, 0xaa, 0x36, 0x42, - 0x94, 0xe0, 0x7c, 0x08, 0x59, 0x2d, 0xb1, 0xc5, 0x26, 0x52, - 0xce, 0xba, 0xeb, 0x9f, 0x03, 0x77, 0xa1, 0xd5, 0x49, 0x3d, - 0x6c, 0x18, 0x84, 0xf0, 0x35, 0x41, 0xdd, 0xa9, 0xf8, 0x8c, - 0x10, 0x64, 0xb2, 0xc6, 0x5a, 0x2e, 0x7f, 0x0b, 0x97, 0xe3, - 0x4c, 0x38, 0xa4, 0xd0, 0x81, 0xf5, 0x69, 0x1d, 0xcb, 0xbf, - 0x23, 0x57, 0x06, 0x72, 0xee, 0x9a, 0x5f, 0x2b, 0xb7, 0xc3, - 0x92, 0xe6, 0x7a, 0x0e, 0xd8, 0xac, 0x30, 0x44, 0x15, 0x61, - 0xfd, 0x89, 0x6a, 0x1e, 0x82, 0xf6, 0xa7, 0xd3, 0x4f, 0x3b, - 0xed, 0x99, 0x05, 0x71, 0x20, 0x54, 0xc8, 0xbc, 0x79, 0x0d, - 0x91, 0xe5, 0xb4, 0xc0, 0x5c, 0x28, 0xfe, 0x8a, 0x16, 0x62, - 0x33, 0x47, 0xdb, 0xaf, 0x98, 0xec, 0x70, 0x04, 0x55, 0x21, - 0xbd, 0xc9, 0x1f, 0x6b, 0xf7, 0x83, 0xd2, 0xa6, 0x3a, 0x4e, - 0x8b, 0xff, 0x63, 0x17, 0x46, 0x32, 0xae, 0xda, 0x0c, 0x78, - 0xe4, 0x90, 0xc1, 0xb5, 0x29, 0x5d, 0xbe, 0xca, 0x56, 0x22, - 0x73, 0x07, 0x9b, 0xef, 0x39, 0x4d, 0xd1, 0xa5, 0xf4, 0x80, - 0x1c, 0x68, 0xad, 0xd9, 0x45, 0x31, 0x60, 0x14, 0x88, 0xfc, - 0x2a, 0x5e, 0xc2, 0xb6, 0xe7, 0x93, 0x0f, 0x7b, 0xd4, 0xa0, - 0x3c, 0x48, 0x19, 0x6d, 0xf1, 0x85, 0x53, 0x27, 0xbb, 0xcf, - 0x9e, 0xea, 0x76, 0x02, 0xc7, 0xb3, 0x2f, 0x5b, 0x0a, 0x7e, - 0xe2, 0x96, 0x40, 0x34, 0xa8, 0xdc, 0x8d, 0xf9, 0x65, 0x11, - 0xf2, 0x86, 0x1a, 0x6e, 0x3f, 0x4b, 0xd7, 0xa3, 0x75, 0x01, - 0x9d, 0xe9, 0xb8, 0xcc, 0x50, 0x24, 0xe1, 0x95, 0x09, 0x7d, - 0x2c, 0x58, 0xc4, 0xb0, 0x66, 0x12, 0x8e, 0xfa, 0xab, 0xdf, - 0x43, 0x37, 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, - 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9, 0x03, 0x76, - 0xe9, 0x9c, 0xca, 0xbf, 0x20, 0x55, 0x8c, 0xf9, 0x66, 0x13, - 0x45, 0x30, 0xaf, 0xda, 0x06, 0x73, 0xec, 0x99, 0xcf, 0xba, - 0x25, 0x50, 0x89, 0xfc, 0x63, 0x16, 0x40, 0x35, 0xaa, 0xdf, - 0x05, 0x70, 0xef, 0x9a, 0xcc, 0xb9, 0x26, 0x53, 0x8a, 0xff, - 0x60, 0x15, 0x43, 0x36, 0xa9, 0xdc, 0x0c, 0x79, 0xe6, 0x93, - 0xc5, 0xb0, 0x2f, 0x5a, 0x83, 0xf6, 0x69, 0x1c, 0x4a, 0x3f, - 0xa0, 0xd5, 0x0f, 0x7a, 0xe5, 0x90, 0xc6, 0xb3, 0x2c, 0x59, - 0x80, 0xf5, 0x6a, 0x1f, 0x49, 0x3c, 0xa3, 0xd6, 0x0a, 0x7f, - 0xe0, 0x95, 0xc3, 0xb6, 0x29, 0x5c, 0x85, 0xf0, 0x6f, 0x1a, - 0x4c, 0x39, 0xa6, 0xd3, 0x09, 0x7c, 0xe3, 0x96, 0xc0, 0xb5, - 0x2a, 0x5f, 0x86, 0xf3, 0x6c, 0x19, 0x4f, 0x3a, 0xa5, 0xd0, - 0x18, 0x6d, 0xf2, 0x87, 0xd1, 0xa4, 0x3b, 0x4e, 0x97, 0xe2, - 0x7d, 0x08, 0x5e, 0x2b, 0xb4, 0xc1, 0x1b, 0x6e, 0xf1, 0x84, - 0xd2, 0xa7, 0x38, 0x4d, 0x94, 0xe1, 0x7e, 0x0b, 0x5d, 0x28, - 0xb7, 0xc2, 0x1e, 0x6b, 0xf4, 0x81, 0xd7, 0xa2, 0x3d, 0x48, - 0x91, 0xe4, 0x7b, 0x0e, 0x58, 0x2d, 0xb2, 0xc7, 0x1d, 0x68, - 0xf7, 0x82, 0xd4, 0xa1, 0x3e, 0x4b, 0x92, 0xe7, 0x78, 0x0d, - 0x5b, 0x2e, 0xb1, 0xc4, 0x14, 0x61, 0xfe, 0x8b, 0xdd, 0xa8, - 0x37, 0x42, 0x9b, 0xee, 0x71, 0x04, 0x52, 0x27, 0xb8, 0xcd, - 0x17, 0x62, 0xfd, 0x88, 0xde, 0xab, 0x34, 0x41, 0x98, 0xed, - 0x72, 0x07, 0x51, 0x24, 0xbb, 0xce, 0x12, 0x67, 0xf8, 0x8d, - 0xdb, 0xae, 0x31, 0x44, 0x9d, 0xe8, 0x77, 0x02, 0x54, 0x21, - 0xbe, 0xcb, 0x11, 0x64, 0xfb, 0x8e, 0xd8, 0xad, 0x32, 0x47, - 0x9e, 0xeb, 0x74, 0x01, 0x57, 0x22, 0xbd, 0xc8, 0x00, 0x76, - 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, - 0x52, 0x24, 0xbe, 0xc8, 0x33, 0x45, 0xdf, 0xa9, 0xf6, 0x80, - 0x1a, 0x6c, 0xa4, 0xd2, 0x48, 0x3e, 0x61, 0x17, 0x8d, 0xfb, - 0x66, 0x10, 0x8a, 0xfc, 0xa3, 0xd5, 0x4f, 0x39, 0xf1, 0x87, - 0x1d, 0x6b, 0x34, 0x42, 0xd8, 0xae, 0x55, 0x23, 0xb9, 0xcf, - 0x90, 0xe6, 0x7c, 0x0a, 0xc2, 0xb4, 0x2e, 0x58, 0x07, 0x71, - 0xeb, 0x9d, 0xcc, 0xba, 0x20, 0x56, 0x09, 0x7f, 0xe5, 0x93, - 0x5b, 0x2d, 0xb7, 0xc1, 0x9e, 0xe8, 0x72, 0x04, 0xff, 0x89, - 0x13, 0x65, 0x3a, 0x4c, 0xd6, 0xa0, 0x68, 0x1e, 0x84, 0xf2, - 0xad, 0xdb, 0x41, 0x37, 0xaa, 0xdc, 0x46, 0x30, 0x6f, 0x19, - 0x83, 0xf5, 0x3d, 0x4b, 0xd1, 0xa7, 0xf8, 0x8e, 0x14, 0x62, - 0x99, 0xef, 0x75, 0x03, 0x5c, 0x2a, 0xb0, 0xc6, 0x0e, 0x78, - 0xe2, 0x94, 0xcb, 0xbd, 0x27, 0x51, 0x85, 0xf3, 0x69, 0x1f, - 0x40, 0x36, 0xac, 0xda, 0x12, 0x64, 0xfe, 0x88, 0xd7, 0xa1, - 0x3b, 0x4d, 0xb6, 0xc0, 0x5a, 0x2c, 0x73, 0x05, 0x9f, 0xe9, - 0x21, 0x57, 0xcd, 0xbb, 0xe4, 0x92, 0x08, 0x7e, 0xe3, 0x95, - 0x0f, 0x79, 0x26, 0x50, 0xca, 0xbc, 0x74, 0x02, 0x98, 0xee, - 0xb1, 0xc7, 0x5d, 0x2b, 0xd0, 0xa6, 0x3c, 0x4a, 0x15, 0x63, - 0xf9, 0x8f, 0x47, 0x31, 0xab, 0xdd, 0x82, 0xf4, 0x6e, 0x18, - 0x49, 0x3f, 0xa5, 0xd3, 0x8c, 0xfa, 0x60, 0x16, 0xde, 0xa8, - 0x32, 0x44, 0x1b, 0x6d, 0xf7, 0x81, 0x7a, 0x0c, 0x96, 0xe0, - 0xbf, 0xc9, 0x53, 0x25, 0xed, 0x9b, 0x01, 0x77, 0x28, 0x5e, - 0xc4, 0xb2, 0x2f, 0x59, 0xc3, 0xb5, 0xea, 0x9c, 0x06, 0x70, - 0xb8, 0xce, 0x54, 0x22, 0x7d, 0x0b, 0x91, 0xe7, 0x1c, 0x6a, - 0xf0, 0x86, 0xd9, 0xaf, 0x35, 0x43, 0x8b, 0xfd, 0x67, 0x11, - 0x4e, 0x38, 0xa2, 0xd4, 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, - 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7, - 0x23, 0x54, 0xcd, 0xba, 0xe2, 0x95, 0x0c, 0x7b, 0xbc, 0xcb, - 0x52, 0x25, 0x7d, 0x0a, 0x93, 0xe4, 0x46, 0x31, 0xa8, 0xdf, - 0x87, 0xf0, 0x69, 0x1e, 0xd9, 0xae, 0x37, 0x40, 0x18, 0x6f, - 0xf6, 0x81, 0x65, 0x12, 0x8b, 0xfc, 0xa4, 0xd3, 0x4a, 0x3d, - 0xfa, 0x8d, 0x14, 0x63, 0x3b, 0x4c, 0xd5, 0xa2, 0x8c, 0xfb, - 0x62, 0x15, 0x4d, 0x3a, 0xa3, 0xd4, 0x13, 0x64, 0xfd, 0x8a, - 0xd2, 0xa5, 0x3c, 0x4b, 0xaf, 0xd8, 0x41, 0x36, 0x6e, 0x19, - 0x80, 0xf7, 0x30, 0x47, 0xde, 0xa9, 0xf1, 0x86, 0x1f, 0x68, - 0xca, 0xbd, 0x24, 0x53, 0x0b, 0x7c, 0xe5, 0x92, 0x55, 0x22, - 0xbb, 0xcc, 0x94, 0xe3, 0x7a, 0x0d, 0xe9, 0x9e, 0x07, 0x70, - 0x28, 0x5f, 0xc6, 0xb1, 0x76, 0x01, 0x98, 0xef, 0xb7, 0xc0, - 0x59, 0x2e, 0x05, 0x72, 0xeb, 0x9c, 0xc4, 0xb3, 0x2a, 0x5d, - 0x9a, 0xed, 0x74, 0x03, 0x5b, 0x2c, 0xb5, 0xc2, 0x26, 0x51, - 0xc8, 0xbf, 0xe7, 0x90, 0x09, 0x7e, 0xb9, 0xce, 0x57, 0x20, - 0x78, 0x0f, 0x96, 0xe1, 0x43, 0x34, 0xad, 0xda, 0x82, 0xf5, - 0x6c, 0x1b, 0xdc, 0xab, 0x32, 0x45, 0x1d, 0x6a, 0xf3, 0x84, - 0x60, 0x17, 0x8e, 0xf9, 0xa1, 0xd6, 0x4f, 0x38, 0xff, 0x88, - 0x11, 0x66, 0x3e, 0x49, 0xd0, 0xa7, 0x89, 0xfe, 0x67, 0x10, - 0x48, 0x3f, 0xa6, 0xd1, 0x16, 0x61, 0xf8, 0x8f, 0xd7, 0xa0, - 0x39, 0x4e, 0xaa, 0xdd, 0x44, 0x33, 0x6b, 0x1c, 0x85, 0xf2, - 0x35, 0x42, 0xdb, 0xac, 0xf4, 0x83, 0x1a, 0x6d, 0xcf, 0xb8, - 0x21, 0x56, 0x0e, 0x79, 0xe0, 0x97, 0x50, 0x27, 0xbe, 0xc9, - 0x91, 0xe6, 0x7f, 0x08, 0xec, 0x9b, 0x02, 0x75, 0x2d, 0x5a, - 0xc3, 0xb4, 0x73, 0x04, 0x9d, 0xea, 0xb2, 0xc5, 0x5c, 0x2b, - 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, - 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92, 0xd3, 0xab, 0x23, 0x5b, - 0x2e, 0x56, 0xde, 0xa6, 0x34, 0x4c, 0xc4, 0xbc, 0xc9, 0xb1, - 0x39, 0x41, 0xbb, 0xc3, 0x4b, 0x33, 0x46, 0x3e, 0xb6, 0xce, - 0x5c, 0x24, 0xac, 0xd4, 0xa1, 0xd9, 0x51, 0x29, 0x68, 0x10, - 0x98, 0xe0, 0x95, 0xed, 0x65, 0x1d, 0x8f, 0xf7, 0x7f, 0x07, - 0x72, 0x0a, 0x82, 0xfa, 0x6b, 0x13, 0x9b, 0xe3, 0x96, 0xee, - 0x66, 0x1e, 0x8c, 0xf4, 0x7c, 0x04, 0x71, 0x09, 0x81, 0xf9, - 0xb8, 0xc0, 0x48, 0x30, 0x45, 0x3d, 0xb5, 0xcd, 0x5f, 0x27, - 0xaf, 0xd7, 0xa2, 0xda, 0x52, 0x2a, 0xd0, 0xa8, 0x20, 0x58, - 0x2d, 0x55, 0xdd, 0xa5, 0x37, 0x4f, 0xc7, 0xbf, 0xca, 0xb2, - 0x3a, 0x42, 0x03, 0x7b, 0xf3, 0x8b, 0xfe, 0x86, 0x0e, 0x76, - 0xe4, 0x9c, 0x14, 0x6c, 0x19, 0x61, 0xe9, 0x91, 0xd6, 0xae, - 0x26, 0x5e, 0x2b, 0x53, 0xdb, 0xa3, 0x31, 0x49, 0xc1, 0xb9, - 0xcc, 0xb4, 0x3c, 0x44, 0x05, 0x7d, 0xf5, 0x8d, 0xf8, 0x80, - 0x08, 0x70, 0xe2, 0x9a, 0x12, 0x6a, 0x1f, 0x67, 0xef, 0x97, - 0x6d, 0x15, 0x9d, 0xe5, 0x90, 0xe8, 0x60, 0x18, 0x8a, 0xf2, - 0x7a, 0x02, 0x77, 0x0f, 0x87, 0xff, 0xbe, 0xc6, 0x4e, 0x36, - 0x43, 0x3b, 0xb3, 0xcb, 0x59, 0x21, 0xa9, 0xd1, 0xa4, 0xdc, - 0x54, 0x2c, 0xbd, 0xc5, 0x4d, 0x35, 0x40, 0x38, 0xb0, 0xc8, - 0x5a, 0x22, 0xaa, 0xd2, 0xa7, 0xdf, 0x57, 0x2f, 0x6e, 0x16, - 0x9e, 0xe6, 0x93, 0xeb, 0x63, 0x1b, 0x89, 0xf1, 0x79, 0x01, - 0x74, 0x0c, 0x84, 0xfc, 0x06, 0x7e, 0xf6, 0x8e, 0xfb, 0x83, - 0x0b, 0x73, 0xe1, 0x99, 0x11, 0x69, 0x1c, 0x64, 0xec, 0x94, - 0xd5, 0xad, 0x25, 0x5d, 0x28, 0x50, 0xd8, 0xa0, 0x32, 0x4a, - 0xc2, 0xba, 0xcf, 0xb7, 0x3f, 0x47, 0x00, 0x79, 0xf2, 0x8b, - 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, - 0xe4, 0x9d, 0xc3, 0xba, 0x31, 0x48, 0x3a, 0x43, 0xc8, 0xb1, - 0x2c, 0x55, 0xde, 0xa7, 0xd5, 0xac, 0x27, 0x5e, 0x9b, 0xe2, - 0x69, 0x10, 0x62, 0x1b, 0x90, 0xe9, 0x74, 0x0d, 0x86, 0xff, - 0x8d, 0xf4, 0x7f, 0x06, 0x58, 0x21, 0xaa, 0xd3, 0xa1, 0xd8, - 0x53, 0x2a, 0xb7, 0xce, 0x45, 0x3c, 0x4e, 0x37, 0xbc, 0xc5, - 0x2b, 0x52, 0xd9, 0xa0, 0xd2, 0xab, 0x20, 0x59, 0xc4, 0xbd, - 0x36, 0x4f, 0x3d, 0x44, 0xcf, 0xb6, 0xe8, 0x91, 0x1a, 0x63, - 0x11, 0x68, 0xe3, 0x9a, 0x07, 0x7e, 0xf5, 0x8c, 0xfe, 0x87, - 0x0c, 0x75, 0xb0, 0xc9, 0x42, 0x3b, 0x49, 0x30, 0xbb, 0xc2, - 0x5f, 0x26, 0xad, 0xd4, 0xa6, 0xdf, 0x54, 0x2d, 0x73, 0x0a, - 0x81, 0xf8, 0x8a, 0xf3, 0x78, 0x01, 0x9c, 0xe5, 0x6e, 0x17, - 0x65, 0x1c, 0x97, 0xee, 0x56, 0x2f, 0xa4, 0xdd, 0xaf, 0xd6, - 0x5d, 0x24, 0xb9, 0xc0, 0x4b, 0x32, 0x40, 0x39, 0xb2, 0xcb, - 0x95, 0xec, 0x67, 0x1e, 0x6c, 0x15, 0x9e, 0xe7, 0x7a, 0x03, - 0x88, 0xf1, 0x83, 0xfa, 0x71, 0x08, 0xcd, 0xb4, 0x3f, 0x46, - 0x34, 0x4d, 0xc6, 0xbf, 0x22, 0x5b, 0xd0, 0xa9, 0xdb, 0xa2, - 0x29, 0x50, 0x0e, 0x77, 0xfc, 0x85, 0xf7, 0x8e, 0x05, 0x7c, - 0xe1, 0x98, 0x13, 0x6a, 0x18, 0x61, 0xea, 0x93, 0x7d, 0x04, - 0x8f, 0xf6, 0x84, 0xfd, 0x76, 0x0f, 0x92, 0xeb, 0x60, 0x19, - 0x6b, 0x12, 0x99, 0xe0, 0xbe, 0xc7, 0x4c, 0x35, 0x47, 0x3e, - 0xb5, 0xcc, 0x51, 0x28, 0xa3, 0xda, 0xa8, 0xd1, 0x5a, 0x23, - 0xe6, 0x9f, 0x14, 0x6d, 0x1f, 0x66, 0xed, 0x94, 0x09, 0x70, - 0xfb, 0x82, 0xf0, 0x89, 0x02, 0x7b, 0x25, 0x5c, 0xd7, 0xae, - 0xdc, 0xa5, 0x2e, 0x57, 0xca, 0xb3, 0x38, 0x41, 0x33, 0x4a, - 0xc1, 0xb8, 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, - 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c, 0xf3, 0x89, - 0x07, 0x7d, 0x06, 0x7c, 0xf2, 0x88, 0x04, 0x7e, 0xf0, 0x8a, - 0xf1, 0x8b, 0x05, 0x7f, 0xfb, 0x81, 0x0f, 0x75, 0x0e, 0x74, - 0xfa, 0x80, 0x0c, 0x76, 0xf8, 0x82, 0xf9, 0x83, 0x0d, 0x77, - 0x08, 0x72, 0xfc, 0x86, 0xfd, 0x87, 0x09, 0x73, 0xff, 0x85, - 0x0b, 0x71, 0x0a, 0x70, 0xfe, 0x84, 0xeb, 0x91, 0x1f, 0x65, - 0x1e, 0x64, 0xea, 0x90, 0x1c, 0x66, 0xe8, 0x92, 0xe9, 0x93, - 0x1d, 0x67, 0x18, 0x62, 0xec, 0x96, 0xed, 0x97, 0x19, 0x63, - 0xef, 0x95, 0x1b, 0x61, 0x1a, 0x60, 0xee, 0x94, 0x10, 0x6a, - 0xe4, 0x9e, 0xe5, 0x9f, 0x11, 0x6b, 0xe7, 0x9d, 0x13, 0x69, - 0x12, 0x68, 0xe6, 0x9c, 0xe3, 0x99, 0x17, 0x6d, 0x16, 0x6c, - 0xe2, 0x98, 0x14, 0x6e, 0xe0, 0x9a, 0xe1, 0x9b, 0x15, 0x6f, - 0xcb, 0xb1, 0x3f, 0x45, 0x3e, 0x44, 0xca, 0xb0, 0x3c, 0x46, - 0xc8, 0xb2, 0xc9, 0xb3, 0x3d, 0x47, 0x38, 0x42, 0xcc, 0xb6, - 0xcd, 0xb7, 0x39, 0x43, 0xcf, 0xb5, 0x3b, 0x41, 0x3a, 0x40, - 0xce, 0xb4, 0x30, 0x4a, 0xc4, 0xbe, 0xc5, 0xbf, 0x31, 0x4b, - 0xc7, 0xbd, 0x33, 0x49, 0x32, 0x48, 0xc6, 0xbc, 0xc3, 0xb9, - 0x37, 0x4d, 0x36, 0x4c, 0xc2, 0xb8, 0x34, 0x4e, 0xc0, 0xba, - 0xc1, 0xbb, 0x35, 0x4f, 0x20, 0x5a, 0xd4, 0xae, 0xd5, 0xaf, - 0x21, 0x5b, 0xd7, 0xad, 0x23, 0x59, 0x22, 0x58, 0xd6, 0xac, - 0xd3, 0xa9, 0x27, 0x5d, 0x26, 0x5c, 0xd2, 0xa8, 0x24, 0x5e, - 0xd0, 0xaa, 0xd1, 0xab, 0x25, 0x5f, 0xdb, 0xa1, 0x2f, 0x55, - 0x2e, 0x54, 0xda, 0xa0, 0x2c, 0x56, 0xd8, 0xa2, 0xd9, 0xa3, - 0x2d, 0x57, 0x28, 0x52, 0xdc, 0xa6, 0xdd, 0xa7, 0x29, 0x53, - 0xdf, 0xa5, 0x2b, 0x51, 0x2a, 0x50, 0xde, 0xa4, 0x00, 0x7b, - 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, - 0x0e, 0x75, 0xf8, 0x83, 0xe3, 0x98, 0x15, 0x6e, 0x12, 0x69, - 0xe4, 0x9f, 0x1c, 0x67, 0xea, 0x91, 0xed, 0x96, 0x1b, 0x60, - 0xdb, 0xa0, 0x2d, 0x56, 0x2a, 0x51, 0xdc, 0xa7, 0x24, 0x5f, - 0xd2, 0xa9, 0xd5, 0xae, 0x23, 0x58, 0x38, 0x43, 0xce, 0xb5, - 0xc9, 0xb2, 0x3f, 0x44, 0xc7, 0xbc, 0x31, 0x4a, 0x36, 0x4d, - 0xc0, 0xbb, 0xab, 0xd0, 0x5d, 0x26, 0x5a, 0x21, 0xac, 0xd7, - 0x54, 0x2f, 0xa2, 0xd9, 0xa5, 0xde, 0x53, 0x28, 0x48, 0x33, - 0xbe, 0xc5, 0xb9, 0xc2, 0x4f, 0x34, 0xb7, 0xcc, 0x41, 0x3a, - 0x46, 0x3d, 0xb0, 0xcb, 0x70, 0x0b, 0x86, 0xfd, 0x81, 0xfa, - 0x77, 0x0c, 0x8f, 0xf4, 0x79, 0x02, 0x7e, 0x05, 0x88, 0xf3, - 0x93, 0xe8, 0x65, 0x1e, 0x62, 0x19, 0x94, 0xef, 0x6c, 0x17, - 0x9a, 0xe1, 0x9d, 0xe6, 0x6b, 0x10, 0x4b, 0x30, 0xbd, 0xc6, - 0xba, 0xc1, 0x4c, 0x37, 0xb4, 0xcf, 0x42, 0x39, 0x45, 0x3e, - 0xb3, 0xc8, 0xa8, 0xd3, 0x5e, 0x25, 0x59, 0x22, 0xaf, 0xd4, - 0x57, 0x2c, 0xa1, 0xda, 0xa6, 0xdd, 0x50, 0x2b, 0x90, 0xeb, - 0x66, 0x1d, 0x61, 0x1a, 0x97, 0xec, 0x6f, 0x14, 0x99, 0xe2, - 0x9e, 0xe5, 0x68, 0x13, 0x73, 0x08, 0x85, 0xfe, 0x82, 0xf9, - 0x74, 0x0f, 0x8c, 0xf7, 0x7a, 0x01, 0x7d, 0x06, 0x8b, 0xf0, - 0xe0, 0x9b, 0x16, 0x6d, 0x11, 0x6a, 0xe7, 0x9c, 0x1f, 0x64, - 0xe9, 0x92, 0xee, 0x95, 0x18, 0x63, 0x03, 0x78, 0xf5, 0x8e, - 0xf2, 0x89, 0x04, 0x7f, 0xfc, 0x87, 0x0a, 0x71, 0x0d, 0x76, - 0xfb, 0x80, 0x3b, 0x40, 0xcd, 0xb6, 0xca, 0xb1, 0x3c, 0x47, - 0xc4, 0xbf, 0x32, 0x49, 0x35, 0x4e, 0xc3, 0xb8, 0xd8, 0xa3, - 0x2e, 0x55, 0x29, 0x52, 0xdf, 0xa4, 0x27, 0x5c, 0xd1, 0xaa, - 0xd6, 0xad, 0x20, 0x5b, 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, - 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae, - 0x93, 0xef, 0x6b, 0x17, 0x7e, 0x02, 0x86, 0xfa, 0x54, 0x28, - 0xac, 0xd0, 0xb9, 0xc5, 0x41, 0x3d, 0x3b, 0x47, 0xc3, 0xbf, - 0xd6, 0xaa, 0x2e, 0x52, 0xfc, 0x80, 0x04, 0x78, 0x11, 0x6d, - 0xe9, 0x95, 0xa8, 0xd4, 0x50, 0x2c, 0x45, 0x39, 0xbd, 0xc1, - 0x6f, 0x13, 0x97, 0xeb, 0x82, 0xfe, 0x7a, 0x06, 0x76, 0x0a, - 0x8e, 0xf2, 0x9b, 0xe7, 0x63, 0x1f, 0xb1, 0xcd, 0x49, 0x35, - 0x5c, 0x20, 0xa4, 0xd8, 0xe5, 0x99, 0x1d, 0x61, 0x08, 0x74, - 0xf0, 0x8c, 0x22, 0x5e, 0xda, 0xa6, 0xcf, 0xb3, 0x37, 0x4b, - 0x4d, 0x31, 0xb5, 0xc9, 0xa0, 0xdc, 0x58, 0x24, 0x8a, 0xf6, - 0x72, 0x0e, 0x67, 0x1b, 0x9f, 0xe3, 0xde, 0xa2, 0x26, 0x5a, - 0x33, 0x4f, 0xcb, 0xb7, 0x19, 0x65, 0xe1, 0x9d, 0xf4, 0x88, - 0x0c, 0x70, 0xec, 0x90, 0x14, 0x68, 0x01, 0x7d, 0xf9, 0x85, - 0x2b, 0x57, 0xd3, 0xaf, 0xc6, 0xba, 0x3e, 0x42, 0x7f, 0x03, - 0x87, 0xfb, 0x92, 0xee, 0x6a, 0x16, 0xb8, 0xc4, 0x40, 0x3c, - 0x55, 0x29, 0xad, 0xd1, 0xd7, 0xab, 0x2f, 0x53, 0x3a, 0x46, - 0xc2, 0xbe, 0x10, 0x6c, 0xe8, 0x94, 0xfd, 0x81, 0x05, 0x79, - 0x44, 0x38, 0xbc, 0xc0, 0xa9, 0xd5, 0x51, 0x2d, 0x83, 0xff, - 0x7b, 0x07, 0x6e, 0x12, 0x96, 0xea, 0x9a, 0xe6, 0x62, 0x1e, - 0x77, 0x0b, 0x8f, 0xf3, 0x5d, 0x21, 0xa5, 0xd9, 0xb0, 0xcc, - 0x48, 0x34, 0x09, 0x75, 0xf1, 0x8d, 0xe4, 0x98, 0x1c, 0x60, - 0xce, 0xb2, 0x36, 0x4a, 0x23, 0x5f, 0xdb, 0xa7, 0xa1, 0xdd, - 0x59, 0x25, 0x4c, 0x30, 0xb4, 0xc8, 0x66, 0x1a, 0x9e, 0xe2, - 0x8b, 0xf7, 0x73, 0x0f, 0x32, 0x4e, 0xca, 0xb6, 0xdf, 0xa3, - 0x27, 0x5b, 0xf5, 0x89, 0x0d, 0x71, 0x18, 0x64, 0xe0, 0x9c, - 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, - 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1, 0x83, 0xfe, 0x79, 0x04, - 0x6a, 0x17, 0x90, 0xed, 0x4c, 0x31, 0xb6, 0xcb, 0xa5, 0xd8, - 0x5f, 0x22, 0x1b, 0x66, 0xe1, 0x9c, 0xf2, 0x8f, 0x08, 0x75, - 0xd4, 0xa9, 0x2e, 0x53, 0x3d, 0x40, 0xc7, 0xba, 0x98, 0xe5, - 0x62, 0x1f, 0x71, 0x0c, 0x8b, 0xf6, 0x57, 0x2a, 0xad, 0xd0, - 0xbe, 0xc3, 0x44, 0x39, 0x36, 0x4b, 0xcc, 0xb1, 0xdf, 0xa2, - 0x25, 0x58, 0xf9, 0x84, 0x03, 0x7e, 0x10, 0x6d, 0xea, 0x97, - 0xb5, 0xc8, 0x4f, 0x32, 0x5c, 0x21, 0xa6, 0xdb, 0x7a, 0x07, - 0x80, 0xfd, 0x93, 0xee, 0x69, 0x14, 0x2d, 0x50, 0xd7, 0xaa, - 0xc4, 0xb9, 0x3e, 0x43, 0xe2, 0x9f, 0x18, 0x65, 0x0b, 0x76, - 0xf1, 0x8c, 0xae, 0xd3, 0x54, 0x29, 0x47, 0x3a, 0xbd, 0xc0, - 0x61, 0x1c, 0x9b, 0xe6, 0x88, 0xf5, 0x72, 0x0f, 0x6c, 0x11, - 0x96, 0xeb, 0x85, 0xf8, 0x7f, 0x02, 0xa3, 0xde, 0x59, 0x24, - 0x4a, 0x37, 0xb0, 0xcd, 0xef, 0x92, 0x15, 0x68, 0x06, 0x7b, - 0xfc, 0x81, 0x20, 0x5d, 0xda, 0xa7, 0xc9, 0xb4, 0x33, 0x4e, - 0x77, 0x0a, 0x8d, 0xf0, 0x9e, 0xe3, 0x64, 0x19, 0xb8, 0xc5, - 0x42, 0x3f, 0x51, 0x2c, 0xab, 0xd6, 0xf4, 0x89, 0x0e, 0x73, - 0x1d, 0x60, 0xe7, 0x9a, 0x3b, 0x46, 0xc1, 0xbc, 0xd2, 0xaf, - 0x28, 0x55, 0x5a, 0x27, 0xa0, 0xdd, 0xb3, 0xce, 0x49, 0x34, - 0x95, 0xe8, 0x6f, 0x12, 0x7c, 0x01, 0x86, 0xfb, 0xd9, 0xa4, - 0x23, 0x5e, 0x30, 0x4d, 0xca, 0xb7, 0x16, 0x6b, 0xec, 0x91, - 0xff, 0x82, 0x05, 0x78, 0x41, 0x3c, 0xbb, 0xc6, 0xa8, 0xd5, - 0x52, 0x2f, 0x8e, 0xf3, 0x74, 0x09, 0x67, 0x1a, 0x9d, 0xe0, - 0xc2, 0xbf, 0x38, 0x45, 0x2b, 0x56, 0xd1, 0xac, 0x0d, 0x70, - 0xf7, 0x8a, 0xe4, 0x99, 0x1e, 0x63, 0x00, 0x7e, 0xfc, 0x82, - 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, - 0xce, 0xb0, 0xb3, 0xcd, 0x4f, 0x31, 0x56, 0x28, 0xaa, 0xd4, - 0x64, 0x1a, 0x98, 0xe6, 0x81, 0xff, 0x7d, 0x03, 0x7b, 0x05, - 0x87, 0xf9, 0x9e, 0xe0, 0x62, 0x1c, 0xac, 0xd2, 0x50, 0x2e, - 0x49, 0x37, 0xb5, 0xcb, 0xc8, 0xb6, 0x34, 0x4a, 0x2d, 0x53, - 0xd1, 0xaf, 0x1f, 0x61, 0xe3, 0x9d, 0xfa, 0x84, 0x06, 0x78, - 0xf6, 0x88, 0x0a, 0x74, 0x13, 0x6d, 0xef, 0x91, 0x21, 0x5f, - 0xdd, 0xa3, 0xc4, 0xba, 0x38, 0x46, 0x45, 0x3b, 0xb9, 0xc7, - 0xa0, 0xde, 0x5c, 0x22, 0x92, 0xec, 0x6e, 0x10, 0x77, 0x09, - 0x8b, 0xf5, 0x8d, 0xf3, 0x71, 0x0f, 0x68, 0x16, 0x94, 0xea, - 0x5a, 0x24, 0xa6, 0xd8, 0xbf, 0xc1, 0x43, 0x3d, 0x3e, 0x40, - 0xc2, 0xbc, 0xdb, 0xa5, 0x27, 0x59, 0xe9, 0x97, 0x15, 0x6b, - 0x0c, 0x72, 0xf0, 0x8e, 0xf1, 0x8f, 0x0d, 0x73, 0x14, 0x6a, - 0xe8, 0x96, 0x26, 0x58, 0xda, 0xa4, 0xc3, 0xbd, 0x3f, 0x41, - 0x42, 0x3c, 0xbe, 0xc0, 0xa7, 0xd9, 0x5b, 0x25, 0x95, 0xeb, - 0x69, 0x17, 0x70, 0x0e, 0x8c, 0xf2, 0x8a, 0xf4, 0x76, 0x08, - 0x6f, 0x11, 0x93, 0xed, 0x5d, 0x23, 0xa1, 0xdf, 0xb8, 0xc6, - 0x44, 0x3a, 0x39, 0x47, 0xc5, 0xbb, 0xdc, 0xa2, 0x20, 0x5e, - 0xee, 0x90, 0x12, 0x6c, 0x0b, 0x75, 0xf7, 0x89, 0x07, 0x79, - 0xfb, 0x85, 0xe2, 0x9c, 0x1e, 0x60, 0xd0, 0xae, 0x2c, 0x52, - 0x35, 0x4b, 0xc9, 0xb7, 0xb4, 0xca, 0x48, 0x36, 0x51, 0x2f, - 0xad, 0xd3, 0x63, 0x1d, 0x9f, 0xe1, 0x86, 0xf8, 0x7a, 0x04, - 0x7c, 0x02, 0x80, 0xfe, 0x99, 0xe7, 0x65, 0x1b, 0xab, 0xd5, - 0x57, 0x29, 0x4e, 0x30, 0xb2, 0xcc, 0xcf, 0xb1, 0x33, 0x4d, - 0x2a, 0x54, 0xd6, 0xa8, 0x18, 0x66, 0xe4, 0x9a, 0xfd, 0x83, - 0x01, 0x7f, 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, - 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf, 0xa3, 0xdc, - 0x5d, 0x22, 0x42, 0x3d, 0xbc, 0xc3, 0x7c, 0x03, 0x82, 0xfd, - 0x9d, 0xe2, 0x63, 0x1c, 0x5b, 0x24, 0xa5, 0xda, 0xba, 0xc5, - 0x44, 0x3b, 0x84, 0xfb, 0x7a, 0x05, 0x65, 0x1a, 0x9b, 0xe4, - 0xf8, 0x87, 0x06, 0x79, 0x19, 0x66, 0xe7, 0x98, 0x27, 0x58, - 0xd9, 0xa6, 0xc6, 0xb9, 0x38, 0x47, 0xb6, 0xc9, 0x48, 0x37, - 0x57, 0x28, 0xa9, 0xd6, 0x69, 0x16, 0x97, 0xe8, 0x88, 0xf7, - 0x76, 0x09, 0x15, 0x6a, 0xeb, 0x94, 0xf4, 0x8b, 0x0a, 0x75, - 0xca, 0xb5, 0x34, 0x4b, 0x2b, 0x54, 0xd5, 0xaa, 0xed, 0x92, - 0x13, 0x6c, 0x0c, 0x73, 0xf2, 0x8d, 0x32, 0x4d, 0xcc, 0xb3, - 0xd3, 0xac, 0x2d, 0x52, 0x4e, 0x31, 0xb0, 0xcf, 0xaf, 0xd0, - 0x51, 0x2e, 0x91, 0xee, 0x6f, 0x10, 0x70, 0x0f, 0x8e, 0xf1, - 0x71, 0x0e, 0x8f, 0xf0, 0x90, 0xef, 0x6e, 0x11, 0xae, 0xd1, - 0x50, 0x2f, 0x4f, 0x30, 0xb1, 0xce, 0xd2, 0xad, 0x2c, 0x53, - 0x33, 0x4c, 0xcd, 0xb2, 0x0d, 0x72, 0xf3, 0x8c, 0xec, 0x93, - 0x12, 0x6d, 0x2a, 0x55, 0xd4, 0xab, 0xcb, 0xb4, 0x35, 0x4a, - 0xf5, 0x8a, 0x0b, 0x74, 0x14, 0x6b, 0xea, 0x95, 0x89, 0xf6, - 0x77, 0x08, 0x68, 0x17, 0x96, 0xe9, 0x56, 0x29, 0xa8, 0xd7, - 0xb7, 0xc8, 0x49, 0x36, 0xc7, 0xb8, 0x39, 0x46, 0x26, 0x59, - 0xd8, 0xa7, 0x18, 0x67, 0xe6, 0x99, 0xf9, 0x86, 0x07, 0x78, - 0x64, 0x1b, 0x9a, 0xe5, 0x85, 0xfa, 0x7b, 0x04, 0xbb, 0xc4, - 0x45, 0x3a, 0x5a, 0x25, 0xa4, 0xdb, 0x9c, 0xe3, 0x62, 0x1d, - 0x7d, 0x02, 0x83, 0xfc, 0x43, 0x3c, 0xbd, 0xc2, 0xa2, 0xdd, - 0x5c, 0x23, 0x3f, 0x40, 0xc1, 0xbe, 0xde, 0xa1, 0x20, 0x5f, - 0xe0, 0x9f, 0x1e, 0x61, 0x01, 0x7e, 0xff, 0x80, 0x00, 0x80, - 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, - 0x4e, 0xce, 0x53, 0xd3, 0xe8, 0x68, 0xf5, 0x75, 0xd2, 0x52, - 0xcf, 0x4f, 0x9c, 0x1c, 0x81, 0x01, 0xa6, 0x26, 0xbb, 0x3b, - 0xcd, 0x4d, 0xd0, 0x50, 0xf7, 0x77, 0xea, 0x6a, 0xb9, 0x39, - 0xa4, 0x24, 0x83, 0x03, 0x9e, 0x1e, 0x25, 0xa5, 0x38, 0xb8, - 0x1f, 0x9f, 0x02, 0x82, 0x51, 0xd1, 0x4c, 0xcc, 0x6b, 0xeb, - 0x76, 0xf6, 0x87, 0x07, 0x9a, 0x1a, 0xbd, 0x3d, 0xa0, 0x20, - 0xf3, 0x73, 0xee, 0x6e, 0xc9, 0x49, 0xd4, 0x54, 0x6f, 0xef, - 0x72, 0xf2, 0x55, 0xd5, 0x48, 0xc8, 0x1b, 0x9b, 0x06, 0x86, - 0x21, 0xa1, 0x3c, 0xbc, 0x4a, 0xca, 0x57, 0xd7, 0x70, 0xf0, - 0x6d, 0xed, 0x3e, 0xbe, 0x23, 0xa3, 0x04, 0x84, 0x19, 0x99, - 0xa2, 0x22, 0xbf, 0x3f, 0x98, 0x18, 0x85, 0x05, 0xd6, 0x56, - 0xcb, 0x4b, 0xec, 0x6c, 0xf1, 0x71, 0x13, 0x93, 0x0e, 0x8e, - 0x29, 0xa9, 0x34, 0xb4, 0x67, 0xe7, 0x7a, 0xfa, 0x5d, 0xdd, - 0x40, 0xc0, 0xfb, 0x7b, 0xe6, 0x66, 0xc1, 0x41, 0xdc, 0x5c, - 0x8f, 0x0f, 0x92, 0x12, 0xb5, 0x35, 0xa8, 0x28, 0xde, 0x5e, - 0xc3, 0x43, 0xe4, 0x64, 0xf9, 0x79, 0xaa, 0x2a, 0xb7, 0x37, - 0x90, 0x10, 0x8d, 0x0d, 0x36, 0xb6, 0x2b, 0xab, 0x0c, 0x8c, - 0x11, 0x91, 0x42, 0xc2, 0x5f, 0xdf, 0x78, 0xf8, 0x65, 0xe5, - 0x94, 0x14, 0x89, 0x09, 0xae, 0x2e, 0xb3, 0x33, 0xe0, 0x60, - 0xfd, 0x7d, 0xda, 0x5a, 0xc7, 0x47, 0x7c, 0xfc, 0x61, 0xe1, - 0x46, 0xc6, 0x5b, 0xdb, 0x08, 0x88, 0x15, 0x95, 0x32, 0xb2, - 0x2f, 0xaf, 0x59, 0xd9, 0x44, 0xc4, 0x63, 0xe3, 0x7e, 0xfe, - 0x2d, 0xad, 0x30, 0xb0, 0x17, 0x97, 0x0a, 0x8a, 0xb1, 0x31, - 0xac, 0x2c, 0x8b, 0x0b, 0x96, 0x16, 0xc5, 0x45, 0xd8, 0x58, - 0xff, 0x7f, 0xe2, 0x62, 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, - 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc, - 0xf8, 0x79, 0xe7, 0x66, 0xc6, 0x47, 0xd9, 0x58, 0x84, 0x05, - 0x9b, 0x1a, 0xba, 0x3b, 0xa5, 0x24, 0xed, 0x6c, 0xf2, 0x73, - 0xd3, 0x52, 0xcc, 0x4d, 0x91, 0x10, 0x8e, 0x0f, 0xaf, 0x2e, - 0xb0, 0x31, 0x15, 0x94, 0x0a, 0x8b, 0x2b, 0xaa, 0x34, 0xb5, - 0x69, 0xe8, 0x76, 0xf7, 0x57, 0xd6, 0x48, 0xc9, 0xc7, 0x46, - 0xd8, 0x59, 0xf9, 0x78, 0xe6, 0x67, 0xbb, 0x3a, 0xa4, 0x25, - 0x85, 0x04, 0x9a, 0x1b, 0x3f, 0xbe, 0x20, 0xa1, 0x01, 0x80, - 0x1e, 0x9f, 0x43, 0xc2, 0x5c, 0xdd, 0x7d, 0xfc, 0x62, 0xe3, - 0x2a, 0xab, 0x35, 0xb4, 0x14, 0x95, 0x0b, 0x8a, 0x56, 0xd7, - 0x49, 0xc8, 0x68, 0xe9, 0x77, 0xf6, 0xd2, 0x53, 0xcd, 0x4c, - 0xec, 0x6d, 0xf3, 0x72, 0xae, 0x2f, 0xb1, 0x30, 0x90, 0x11, - 0x8f, 0x0e, 0x93, 0x12, 0x8c, 0x0d, 0xad, 0x2c, 0xb2, 0x33, - 0xef, 0x6e, 0xf0, 0x71, 0xd1, 0x50, 0xce, 0x4f, 0x6b, 0xea, - 0x74, 0xf5, 0x55, 0xd4, 0x4a, 0xcb, 0x17, 0x96, 0x08, 0x89, - 0x29, 0xa8, 0x36, 0xb7, 0x7e, 0xff, 0x61, 0xe0, 0x40, 0xc1, - 0x5f, 0xde, 0x02, 0x83, 0x1d, 0x9c, 0x3c, 0xbd, 0x23, 0xa2, - 0x86, 0x07, 0x99, 0x18, 0xb8, 0x39, 0xa7, 0x26, 0xfa, 0x7b, - 0xe5, 0x64, 0xc4, 0x45, 0xdb, 0x5a, 0x54, 0xd5, 0x4b, 0xca, - 0x6a, 0xeb, 0x75, 0xf4, 0x28, 0xa9, 0x37, 0xb6, 0x16, 0x97, - 0x09, 0x88, 0xac, 0x2d, 0xb3, 0x32, 0x92, 0x13, 0x8d, 0x0c, - 0xd0, 0x51, 0xcf, 0x4e, 0xee, 0x6f, 0xf1, 0x70, 0xb9, 0x38, - 0xa6, 0x27, 0x87, 0x06, 0x98, 0x19, 0xc5, 0x44, 0xda, 0x5b, - 0xfb, 0x7a, 0xe4, 0x65, 0x41, 0xc0, 0x5e, 0xdf, 0x7f, 0xfe, - 0x60, 0xe1, 0x3d, 0xbc, 0x22, 0xa3, 0x03, 0x82, 0x1c, 0x9d, - 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, - 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd, 0xc8, 0x4a, 0xd1, 0x53, - 0xfa, 0x78, 0xe3, 0x61, 0xac, 0x2e, 0xb5, 0x37, 0x9e, 0x1c, - 0x87, 0x05, 0x8d, 0x0f, 0x94, 0x16, 0xbf, 0x3d, 0xa6, 0x24, - 0xe9, 0x6b, 0xf0, 0x72, 0xdb, 0x59, 0xc2, 0x40, 0x45, 0xc7, - 0x5c, 0xde, 0x77, 0xf5, 0x6e, 0xec, 0x21, 0xa3, 0x38, 0xba, - 0x13, 0x91, 0x0a, 0x88, 0x07, 0x85, 0x1e, 0x9c, 0x35, 0xb7, - 0x2c, 0xae, 0x63, 0xe1, 0x7a, 0xf8, 0x51, 0xd3, 0x48, 0xca, - 0xcf, 0x4d, 0xd6, 0x54, 0xfd, 0x7f, 0xe4, 0x66, 0xab, 0x29, - 0xb2, 0x30, 0x99, 0x1b, 0x80, 0x02, 0x8a, 0x08, 0x93, 0x11, - 0xb8, 0x3a, 0xa1, 0x23, 0xee, 0x6c, 0xf7, 0x75, 0xdc, 0x5e, - 0xc5, 0x47, 0x42, 0xc0, 0x5b, 0xd9, 0x70, 0xf2, 0x69, 0xeb, - 0x26, 0xa4, 0x3f, 0xbd, 0x14, 0x96, 0x0d, 0x8f, 0x0e, 0x8c, - 0x17, 0x95, 0x3c, 0xbe, 0x25, 0xa7, 0x6a, 0xe8, 0x73, 0xf1, - 0x58, 0xda, 0x41, 0xc3, 0xc6, 0x44, 0xdf, 0x5d, 0xf4, 0x76, - 0xed, 0x6f, 0xa2, 0x20, 0xbb, 0x39, 0x90, 0x12, 0x89, 0x0b, - 0x83, 0x01, 0x9a, 0x18, 0xb1, 0x33, 0xa8, 0x2a, 0xe7, 0x65, - 0xfe, 0x7c, 0xd5, 0x57, 0xcc, 0x4e, 0x4b, 0xc9, 0x52, 0xd0, - 0x79, 0xfb, 0x60, 0xe2, 0x2f, 0xad, 0x36, 0xb4, 0x1d, 0x9f, - 0x04, 0x86, 0x09, 0x8b, 0x10, 0x92, 0x3b, 0xb9, 0x22, 0xa0, - 0x6d, 0xef, 0x74, 0xf6, 0x5f, 0xdd, 0x46, 0xc4, 0xc1, 0x43, - 0xd8, 0x5a, 0xf3, 0x71, 0xea, 0x68, 0xa5, 0x27, 0xbc, 0x3e, - 0x97, 0x15, 0x8e, 0x0c, 0x84, 0x06, 0x9d, 0x1f, 0xb6, 0x34, - 0xaf, 0x2d, 0xe0, 0x62, 0xf9, 0x7b, 0xd2, 0x50, 0xcb, 0x49, - 0x4c, 0xce, 0x55, 0xd7, 0x7e, 0xfc, 0x67, 0xe5, 0x28, 0xaa, - 0x31, 0xb3, 0x1a, 0x98, 0x03, 0x81, 0x00, 0x83, 0x1b, 0x98, - 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, - 0x41, 0xc2, 0xd8, 0x5b, 0xc3, 0x40, 0xee, 0x6d, 0xf5, 0x76, - 0xb4, 0x37, 0xaf, 0x2c, 0x82, 0x01, 0x99, 0x1a, 0xad, 0x2e, - 0xb6, 0x35, 0x9b, 0x18, 0x80, 0x03, 0xc1, 0x42, 0xda, 0x59, - 0xf7, 0x74, 0xec, 0x6f, 0x75, 0xf6, 0x6e, 0xed, 0x43, 0xc0, - 0x58, 0xdb, 0x19, 0x9a, 0x02, 0x81, 0x2f, 0xac, 0x34, 0xb7, - 0x47, 0xc4, 0x5c, 0xdf, 0x71, 0xf2, 0x6a, 0xe9, 0x2b, 0xa8, - 0x30, 0xb3, 0x1d, 0x9e, 0x06, 0x85, 0x9f, 0x1c, 0x84, 0x07, - 0xa9, 0x2a, 0xb2, 0x31, 0xf3, 0x70, 0xe8, 0x6b, 0xc5, 0x46, - 0xde, 0x5d, 0xea, 0x69, 0xf1, 0x72, 0xdc, 0x5f, 0xc7, 0x44, - 0x86, 0x05, 0x9d, 0x1e, 0xb0, 0x33, 0xab, 0x28, 0x32, 0xb1, - 0x29, 0xaa, 0x04, 0x87, 0x1f, 0x9c, 0x5e, 0xdd, 0x45, 0xc6, - 0x68, 0xeb, 0x73, 0xf0, 0x8e, 0x0d, 0x95, 0x16, 0xb8, 0x3b, - 0xa3, 0x20, 0xe2, 0x61, 0xf9, 0x7a, 0xd4, 0x57, 0xcf, 0x4c, - 0x56, 0xd5, 0x4d, 0xce, 0x60, 0xe3, 0x7b, 0xf8, 0x3a, 0xb9, - 0x21, 0xa2, 0x0c, 0x8f, 0x17, 0x94, 0x23, 0xa0, 0x38, 0xbb, - 0x15, 0x96, 0x0e, 0x8d, 0x4f, 0xcc, 0x54, 0xd7, 0x79, 0xfa, - 0x62, 0xe1, 0xfb, 0x78, 0xe0, 0x63, 0xcd, 0x4e, 0xd6, 0x55, - 0x97, 0x14, 0x8c, 0x0f, 0xa1, 0x22, 0xba, 0x39, 0xc9, 0x4a, - 0xd2, 0x51, 0xff, 0x7c, 0xe4, 0x67, 0xa5, 0x26, 0xbe, 0x3d, - 0x93, 0x10, 0x88, 0x0b, 0x11, 0x92, 0x0a, 0x89, 0x27, 0xa4, - 0x3c, 0xbf, 0x7d, 0xfe, 0x66, 0xe5, 0x4b, 0xc8, 0x50, 0xd3, - 0x64, 0xe7, 0x7f, 0xfc, 0x52, 0xd1, 0x49, 0xca, 0x08, 0x8b, - 0x13, 0x90, 0x3e, 0xbd, 0x25, 0xa6, 0xbc, 0x3f, 0xa7, 0x24, - 0x8a, 0x09, 0x91, 0x12, 0xd0, 0x53, 0xcb, 0x48, 0xe6, 0x65, - 0xfd, 0x7e, 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, - 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef, 0xa8, 0x2c, - 0xbd, 0x39, 0x82, 0x06, 0x97, 0x13, 0xfc, 0x78, 0xe9, 0x6d, - 0xd6, 0x52, 0xc3, 0x47, 0x4d, 0xc9, 0x58, 0xdc, 0x67, 0xe3, - 0x72, 0xf6, 0x19, 0x9d, 0x0c, 0x88, 0x33, 0xb7, 0x26, 0xa2, - 0xe5, 0x61, 0xf0, 0x74, 0xcf, 0x4b, 0xda, 0x5e, 0xb1, 0x35, - 0xa4, 0x20, 0x9b, 0x1f, 0x8e, 0x0a, 0x9a, 0x1e, 0x8f, 0x0b, - 0xb0, 0x34, 0xa5, 0x21, 0xce, 0x4a, 0xdb, 0x5f, 0xe4, 0x60, - 0xf1, 0x75, 0x32, 0xb6, 0x27, 0xa3, 0x18, 0x9c, 0x0d, 0x89, - 0x66, 0xe2, 0x73, 0xf7, 0x4c, 0xc8, 0x59, 0xdd, 0xd7, 0x53, - 0xc2, 0x46, 0xfd, 0x79, 0xe8, 0x6c, 0x83, 0x07, 0x96, 0x12, - 0xa9, 0x2d, 0xbc, 0x38, 0x7f, 0xfb, 0x6a, 0xee, 0x55, 0xd1, - 0x40, 0xc4, 0x2b, 0xaf, 0x3e, 0xba, 0x01, 0x85, 0x14, 0x90, - 0x29, 0xad, 0x3c, 0xb8, 0x03, 0x87, 0x16, 0x92, 0x7d, 0xf9, - 0x68, 0xec, 0x57, 0xd3, 0x42, 0xc6, 0x81, 0x05, 0x94, 0x10, - 0xab, 0x2f, 0xbe, 0x3a, 0xd5, 0x51, 0xc0, 0x44, 0xff, 0x7b, - 0xea, 0x6e, 0x64, 0xe0, 0x71, 0xf5, 0x4e, 0xca, 0x5b, 0xdf, - 0x30, 0xb4, 0x25, 0xa1, 0x1a, 0x9e, 0x0f, 0x8b, 0xcc, 0x48, - 0xd9, 0x5d, 0xe6, 0x62, 0xf3, 0x77, 0x98, 0x1c, 0x8d, 0x09, - 0xb2, 0x36, 0xa7, 0x23, 0xb3, 0x37, 0xa6, 0x22, 0x99, 0x1d, - 0x8c, 0x08, 0xe7, 0x63, 0xf2, 0x76, 0xcd, 0x49, 0xd8, 0x5c, - 0x1b, 0x9f, 0x0e, 0x8a, 0x31, 0xb5, 0x24, 0xa0, 0x4f, 0xcb, - 0x5a, 0xde, 0x65, 0xe1, 0x70, 0xf4, 0xfe, 0x7a, 0xeb, 0x6f, - 0xd4, 0x50, 0xc1, 0x45, 0xaa, 0x2e, 0xbf, 0x3b, 0x80, 0x04, - 0x95, 0x11, 0x56, 0xd2, 0x43, 0xc7, 0x7c, 0xf8, 0x69, 0xed, - 0x02, 0x86, 0x17, 0x93, 0x28, 0xac, 0x3d, 0xb9, 0x00, 0x85, - 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, - 0x72, 0xf7, 0x65, 0xe0, 0xb8, 0x3d, 0xaf, 0x2a, 0x96, 0x13, - 0x81, 0x04, 0xe4, 0x61, 0xf3, 0x76, 0xca, 0x4f, 0xdd, 0x58, - 0x6d, 0xe8, 0x7a, 0xff, 0x43, 0xc6, 0x54, 0xd1, 0x31, 0xb4, - 0x26, 0xa3, 0x1f, 0x9a, 0x08, 0x8d, 0xd5, 0x50, 0xc2, 0x47, - 0xfb, 0x7e, 0xec, 0x69, 0x89, 0x0c, 0x9e, 0x1b, 0xa7, 0x22, - 0xb0, 0x35, 0xda, 0x5f, 0xcd, 0x48, 0xf4, 0x71, 0xe3, 0x66, - 0x86, 0x03, 0x91, 0x14, 0xa8, 0x2d, 0xbf, 0x3a, 0x62, 0xe7, - 0x75, 0xf0, 0x4c, 0xc9, 0x5b, 0xde, 0x3e, 0xbb, 0x29, 0xac, - 0x10, 0x95, 0x07, 0x82, 0xb7, 0x32, 0xa0, 0x25, 0x99, 0x1c, - 0x8e, 0x0b, 0xeb, 0x6e, 0xfc, 0x79, 0xc5, 0x40, 0xd2, 0x57, - 0x0f, 0x8a, 0x18, 0x9d, 0x21, 0xa4, 0x36, 0xb3, 0x53, 0xd6, - 0x44, 0xc1, 0x7d, 0xf8, 0x6a, 0xef, 0xa9, 0x2c, 0xbe, 0x3b, - 0x87, 0x02, 0x90, 0x15, 0xf5, 0x70, 0xe2, 0x67, 0xdb, 0x5e, - 0xcc, 0x49, 0x11, 0x94, 0x06, 0x83, 0x3f, 0xba, 0x28, 0xad, - 0x4d, 0xc8, 0x5a, 0xdf, 0x63, 0xe6, 0x74, 0xf1, 0xc4, 0x41, - 0xd3, 0x56, 0xea, 0x6f, 0xfd, 0x78, 0x98, 0x1d, 0x8f, 0x0a, - 0xb6, 0x33, 0xa1, 0x24, 0x7c, 0xf9, 0x6b, 0xee, 0x52, 0xd7, - 0x45, 0xc0, 0x20, 0xa5, 0x37, 0xb2, 0x0e, 0x8b, 0x19, 0x9c, - 0x73, 0xf6, 0x64, 0xe1, 0x5d, 0xd8, 0x4a, 0xcf, 0x2f, 0xaa, - 0x38, 0xbd, 0x01, 0x84, 0x16, 0x93, 0xcb, 0x4e, 0xdc, 0x59, - 0xe5, 0x60, 0xf2, 0x77, 0x97, 0x12, 0x80, 0x05, 0xb9, 0x3c, - 0xae, 0x2b, 0x1e, 0x9b, 0x09, 0x8c, 0x30, 0xb5, 0x27, 0xa2, - 0x42, 0xc7, 0x55, 0xd0, 0x6c, 0xe9, 0x7b, 0xfe, 0xa6, 0x23, - 0xb1, 0x34, 0x88, 0x0d, 0x9f, 0x1a, 0xfa, 0x7f, 0xed, 0x68, - 0xd4, 0x51, 0xc3, 0x46, 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, - 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1, - 0x88, 0x0e, 0x99, 0x1f, 0xaa, 0x2c, 0xbb, 0x3d, 0xcc, 0x4a, - 0xdd, 0x5b, 0xee, 0x68, 0xff, 0x79, 0x0d, 0x8b, 0x1c, 0x9a, - 0x2f, 0xa9, 0x3e, 0xb8, 0x49, 0xcf, 0x58, 0xde, 0x6b, 0xed, - 0x7a, 0xfc, 0x85, 0x03, 0x94, 0x12, 0xa7, 0x21, 0xb6, 0x30, - 0xc1, 0x47, 0xd0, 0x56, 0xe3, 0x65, 0xf2, 0x74, 0x1a, 0x9c, - 0x0b, 0x8d, 0x38, 0xbe, 0x29, 0xaf, 0x5e, 0xd8, 0x4f, 0xc9, - 0x7c, 0xfa, 0x6d, 0xeb, 0x92, 0x14, 0x83, 0x05, 0xb0, 0x36, - 0xa1, 0x27, 0xd6, 0x50, 0xc7, 0x41, 0xf4, 0x72, 0xe5, 0x63, - 0x17, 0x91, 0x06, 0x80, 0x35, 0xb3, 0x24, 0xa2, 0x53, 0xd5, - 0x42, 0xc4, 0x71, 0xf7, 0x60, 0xe6, 0x9f, 0x19, 0x8e, 0x08, - 0xbd, 0x3b, 0xac, 0x2a, 0xdb, 0x5d, 0xca, 0x4c, 0xf9, 0x7f, - 0xe8, 0x6e, 0x34, 0xb2, 0x25, 0xa3, 0x16, 0x90, 0x07, 0x81, - 0x70, 0xf6, 0x61, 0xe7, 0x52, 0xd4, 0x43, 0xc5, 0xbc, 0x3a, - 0xad, 0x2b, 0x9e, 0x18, 0x8f, 0x09, 0xf8, 0x7e, 0xe9, 0x6f, - 0xda, 0x5c, 0xcb, 0x4d, 0x39, 0xbf, 0x28, 0xae, 0x1b, 0x9d, - 0x0a, 0x8c, 0x7d, 0xfb, 0x6c, 0xea, 0x5f, 0xd9, 0x4e, 0xc8, - 0xb1, 0x37, 0xa0, 0x26, 0x93, 0x15, 0x82, 0x04, 0xf5, 0x73, - 0xe4, 0x62, 0xd7, 0x51, 0xc6, 0x40, 0x2e, 0xa8, 0x3f, 0xb9, - 0x0c, 0x8a, 0x1d, 0x9b, 0x6a, 0xec, 0x7b, 0xfd, 0x48, 0xce, - 0x59, 0xdf, 0xa6, 0x20, 0xb7, 0x31, 0x84, 0x02, 0x95, 0x13, - 0xe2, 0x64, 0xf3, 0x75, 0xc0, 0x46, 0xd1, 0x57, 0x23, 0xa5, - 0x32, 0xb4, 0x01, 0x87, 0x10, 0x96, 0x67, 0xe1, 0x76, 0xf0, - 0x45, 0xc3, 0x54, 0xd2, 0xab, 0x2d, 0xba, 0x3c, 0x89, 0x0f, - 0x98, 0x1e, 0xef, 0x69, 0xfe, 0x78, 0xcd, 0x4b, 0xdc, 0x5a, - 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, - 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe, 0x98, 0x1f, 0x8b, 0x0c, - 0xbe, 0x39, 0xad, 0x2a, 0xd4, 0x53, 0xc7, 0x40, 0xf2, 0x75, - 0xe1, 0x66, 0x2d, 0xaa, 0x3e, 0xb9, 0x0b, 0x8c, 0x18, 0x9f, - 0x61, 0xe6, 0x72, 0xf5, 0x47, 0xc0, 0x54, 0xd3, 0xb5, 0x32, - 0xa6, 0x21, 0x93, 0x14, 0x80, 0x07, 0xf9, 0x7e, 0xea, 0x6d, - 0xdf, 0x58, 0xcc, 0x4b, 0x5a, 0xdd, 0x49, 0xce, 0x7c, 0xfb, - 0x6f, 0xe8, 0x16, 0x91, 0x05, 0x82, 0x30, 0xb7, 0x23, 0xa4, - 0xc2, 0x45, 0xd1, 0x56, 0xe4, 0x63, 0xf7, 0x70, 0x8e, 0x09, - 0x9d, 0x1a, 0xa8, 0x2f, 0xbb, 0x3c, 0x77, 0xf0, 0x64, 0xe3, - 0x51, 0xd6, 0x42, 0xc5, 0x3b, 0xbc, 0x28, 0xaf, 0x1d, 0x9a, - 0x0e, 0x89, 0xef, 0x68, 0xfc, 0x7b, 0xc9, 0x4e, 0xda, 0x5d, - 0xa3, 0x24, 0xb0, 0x37, 0x85, 0x02, 0x96, 0x11, 0xb4, 0x33, - 0xa7, 0x20, 0x92, 0x15, 0x81, 0x06, 0xf8, 0x7f, 0xeb, 0x6c, - 0xde, 0x59, 0xcd, 0x4a, 0x2c, 0xab, 0x3f, 0xb8, 0x0a, 0x8d, - 0x19, 0x9e, 0x60, 0xe7, 0x73, 0xf4, 0x46, 0xc1, 0x55, 0xd2, - 0x99, 0x1e, 0x8a, 0x0d, 0xbf, 0x38, 0xac, 0x2b, 0xd5, 0x52, - 0xc6, 0x41, 0xf3, 0x74, 0xe0, 0x67, 0x01, 0x86, 0x12, 0x95, - 0x27, 0xa0, 0x34, 0xb3, 0x4d, 0xca, 0x5e, 0xd9, 0x6b, 0xec, - 0x78, 0xff, 0xee, 0x69, 0xfd, 0x7a, 0xc8, 0x4f, 0xdb, 0x5c, - 0xa2, 0x25, 0xb1, 0x36, 0x84, 0x03, 0x97, 0x10, 0x76, 0xf1, - 0x65, 0xe2, 0x50, 0xd7, 0x43, 0xc4, 0x3a, 0xbd, 0x29, 0xae, - 0x1c, 0x9b, 0x0f, 0x88, 0xc3, 0x44, 0xd0, 0x57, 0xe5, 0x62, - 0xf6, 0x71, 0x8f, 0x08, 0x9c, 0x1b, 0xa9, 0x2e, 0xba, 0x3d, - 0x5b, 0xdc, 0x48, 0xcf, 0x7d, 0xfa, 0x6e, 0xe9, 0x17, 0x90, - 0x04, 0x83, 0x31, 0xb6, 0x22, 0xa5, 0x00, 0x88, 0x0d, 0x85, - 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, - 0x23, 0xab, 0x68, 0xe0, 0x65, 0xed, 0x72, 0xfa, 0x7f, 0xf7, - 0x5c, 0xd4, 0x51, 0xd9, 0x46, 0xce, 0x4b, 0xc3, 0xd0, 0x58, - 0xdd, 0x55, 0xca, 0x42, 0xc7, 0x4f, 0xe4, 0x6c, 0xe9, 0x61, - 0xfe, 0x76, 0xf3, 0x7b, 0xb8, 0x30, 0xb5, 0x3d, 0xa2, 0x2a, - 0xaf, 0x27, 0x8c, 0x04, 0x81, 0x09, 0x96, 0x1e, 0x9b, 0x13, - 0xbd, 0x35, 0xb0, 0x38, 0xa7, 0x2f, 0xaa, 0x22, 0x89, 0x01, - 0x84, 0x0c, 0x93, 0x1b, 0x9e, 0x16, 0xd5, 0x5d, 0xd8, 0x50, - 0xcf, 0x47, 0xc2, 0x4a, 0xe1, 0x69, 0xec, 0x64, 0xfb, 0x73, - 0xf6, 0x7e, 0x6d, 0xe5, 0x60, 0xe8, 0x77, 0xff, 0x7a, 0xf2, - 0x59, 0xd1, 0x54, 0xdc, 0x43, 0xcb, 0x4e, 0xc6, 0x05, 0x8d, - 0x08, 0x80, 0x1f, 0x97, 0x12, 0x9a, 0x31, 0xb9, 0x3c, 0xb4, - 0x2b, 0xa3, 0x26, 0xae, 0x67, 0xef, 0x6a, 0xe2, 0x7d, 0xf5, - 0x70, 0xf8, 0x53, 0xdb, 0x5e, 0xd6, 0x49, 0xc1, 0x44, 0xcc, - 0x0f, 0x87, 0x02, 0x8a, 0x15, 0x9d, 0x18, 0x90, 0x3b, 0xb3, - 0x36, 0xbe, 0x21, 0xa9, 0x2c, 0xa4, 0xb7, 0x3f, 0xba, 0x32, - 0xad, 0x25, 0xa0, 0x28, 0x83, 0x0b, 0x8e, 0x06, 0x99, 0x11, - 0x94, 0x1c, 0xdf, 0x57, 0xd2, 0x5a, 0xc5, 0x4d, 0xc8, 0x40, - 0xeb, 0x63, 0xe6, 0x6e, 0xf1, 0x79, 0xfc, 0x74, 0xda, 0x52, - 0xd7, 0x5f, 0xc0, 0x48, 0xcd, 0x45, 0xee, 0x66, 0xe3, 0x6b, - 0xf4, 0x7c, 0xf9, 0x71, 0xb2, 0x3a, 0xbf, 0x37, 0xa8, 0x20, - 0xa5, 0x2d, 0x86, 0x0e, 0x8b, 0x03, 0x9c, 0x14, 0x91, 0x19, - 0x0a, 0x82, 0x07, 0x8f, 0x10, 0x98, 0x1d, 0x95, 0x3e, 0xb6, - 0x33, 0xbb, 0x24, 0xac, 0x29, 0xa1, 0x62, 0xea, 0x6f, 0xe7, - 0x78, 0xf0, 0x75, 0xfd, 0x56, 0xde, 0x5b, 0xd3, 0x4c, 0xc4, - 0x41, 0xc9, 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, - 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4, 0x78, 0xf1, - 0x77, 0xfe, 0x66, 0xef, 0x69, 0xe0, 0x44, 0xcd, 0x4b, 0xc2, - 0x5a, 0xd3, 0x55, 0xdc, 0xf0, 0x79, 0xff, 0x76, 0xee, 0x67, - 0xe1, 0x68, 0xcc, 0x45, 0xc3, 0x4a, 0xd2, 0x5b, 0xdd, 0x54, - 0x88, 0x01, 0x87, 0x0e, 0x96, 0x1f, 0x99, 0x10, 0xb4, 0x3d, - 0xbb, 0x32, 0xaa, 0x23, 0xa5, 0x2c, 0xfd, 0x74, 0xf2, 0x7b, - 0xe3, 0x6a, 0xec, 0x65, 0xc1, 0x48, 0xce, 0x47, 0xdf, 0x56, - 0xd0, 0x59, 0x85, 0x0c, 0x8a, 0x03, 0x9b, 0x12, 0x94, 0x1d, - 0xb9, 0x30, 0xb6, 0x3f, 0xa7, 0x2e, 0xa8, 0x21, 0x0d, 0x84, - 0x02, 0x8b, 0x13, 0x9a, 0x1c, 0x95, 0x31, 0xb8, 0x3e, 0xb7, - 0x2f, 0xa6, 0x20, 0xa9, 0x75, 0xfc, 0x7a, 0xf3, 0x6b, 0xe2, - 0x64, 0xed, 0x49, 0xc0, 0x46, 0xcf, 0x57, 0xde, 0x58, 0xd1, - 0xe7, 0x6e, 0xe8, 0x61, 0xf9, 0x70, 0xf6, 0x7f, 0xdb, 0x52, - 0xd4, 0x5d, 0xc5, 0x4c, 0xca, 0x43, 0x9f, 0x16, 0x90, 0x19, - 0x81, 0x08, 0x8e, 0x07, 0xa3, 0x2a, 0xac, 0x25, 0xbd, 0x34, - 0xb2, 0x3b, 0x17, 0x9e, 0x18, 0x91, 0x09, 0x80, 0x06, 0x8f, - 0x2b, 0xa2, 0x24, 0xad, 0x35, 0xbc, 0x3a, 0xb3, 0x6f, 0xe6, - 0x60, 0xe9, 0x71, 0xf8, 0x7e, 0xf7, 0x53, 0xda, 0x5c, 0xd5, - 0x4d, 0xc4, 0x42, 0xcb, 0x1a, 0x93, 0x15, 0x9c, 0x04, 0x8d, - 0x0b, 0x82, 0x26, 0xaf, 0x29, 0xa0, 0x38, 0xb1, 0x37, 0xbe, - 0x62, 0xeb, 0x6d, 0xe4, 0x7c, 0xf5, 0x73, 0xfa, 0x5e, 0xd7, - 0x51, 0xd8, 0x40, 0xc9, 0x4f, 0xc6, 0xea, 0x63, 0xe5, 0x6c, - 0xf4, 0x7d, 0xfb, 0x72, 0xd6, 0x5f, 0xd9, 0x50, 0xc8, 0x41, - 0xc7, 0x4e, 0x92, 0x1b, 0x9d, 0x14, 0x8c, 0x05, 0x83, 0x0a, - 0xae, 0x27, 0xa1, 0x28, 0xb0, 0x39, 0xbf, 0x36, 0x00, 0x8a, - 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, - 0x36, 0xbc, 0x3f, 0xb5, 0x48, 0xc2, 0x41, 0xcb, 0x5a, 0xd0, - 0x53, 0xd9, 0x6c, 0xe6, 0x65, 0xef, 0x7e, 0xf4, 0x77, 0xfd, - 0x90, 0x1a, 0x99, 0x13, 0x82, 0x08, 0x8b, 0x01, 0xb4, 0x3e, - 0xbd, 0x37, 0xa6, 0x2c, 0xaf, 0x25, 0xd8, 0x52, 0xd1, 0x5b, - 0xca, 0x40, 0xc3, 0x49, 0xfc, 0x76, 0xf5, 0x7f, 0xee, 0x64, - 0xe7, 0x6d, 0x3d, 0xb7, 0x34, 0xbe, 0x2f, 0xa5, 0x26, 0xac, - 0x19, 0x93, 0x10, 0x9a, 0x0b, 0x81, 0x02, 0x88, 0x75, 0xff, - 0x7c, 0xf6, 0x67, 0xed, 0x6e, 0xe4, 0x51, 0xdb, 0x58, 0xd2, - 0x43, 0xc9, 0x4a, 0xc0, 0xad, 0x27, 0xa4, 0x2e, 0xbf, 0x35, - 0xb6, 0x3c, 0x89, 0x03, 0x80, 0x0a, 0x9b, 0x11, 0x92, 0x18, - 0xe5, 0x6f, 0xec, 0x66, 0xf7, 0x7d, 0xfe, 0x74, 0xc1, 0x4b, - 0xc8, 0x42, 0xd3, 0x59, 0xda, 0x50, 0x7a, 0xf0, 0x73, 0xf9, - 0x68, 0xe2, 0x61, 0xeb, 0x5e, 0xd4, 0x57, 0xdd, 0x4c, 0xc6, - 0x45, 0xcf, 0x32, 0xb8, 0x3b, 0xb1, 0x20, 0xaa, 0x29, 0xa3, - 0x16, 0x9c, 0x1f, 0x95, 0x04, 0x8e, 0x0d, 0x87, 0xea, 0x60, - 0xe3, 0x69, 0xf8, 0x72, 0xf1, 0x7b, 0xce, 0x44, 0xc7, 0x4d, - 0xdc, 0x56, 0xd5, 0x5f, 0xa2, 0x28, 0xab, 0x21, 0xb0, 0x3a, - 0xb9, 0x33, 0x86, 0x0c, 0x8f, 0x05, 0x94, 0x1e, 0x9d, 0x17, - 0x47, 0xcd, 0x4e, 0xc4, 0x55, 0xdf, 0x5c, 0xd6, 0x63, 0xe9, - 0x6a, 0xe0, 0x71, 0xfb, 0x78, 0xf2, 0x0f, 0x85, 0x06, 0x8c, - 0x1d, 0x97, 0x14, 0x9e, 0x2b, 0xa1, 0x22, 0xa8, 0x39, 0xb3, - 0x30, 0xba, 0xd7, 0x5d, 0xde, 0x54, 0xc5, 0x4f, 0xcc, 0x46, - 0xf3, 0x79, 0xfa, 0x70, 0xe1, 0x6b, 0xe8, 0x62, 0x9f, 0x15, - 0x96, 0x1c, 0x8d, 0x07, 0x84, 0x0e, 0xbb, 0x31, 0xb2, 0x38, - 0xa9, 0x23, 0xa0, 0x2a, 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, - 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba, - 0x58, 0xd3, 0x53, 0xd8, 0x4e, 0xc5, 0x45, 0xce, 0x74, 0xff, - 0x7f, 0xf4, 0x62, 0xe9, 0x69, 0xe2, 0xb0, 0x3b, 0xbb, 0x30, - 0xa6, 0x2d, 0xad, 0x26, 0x9c, 0x17, 0x97, 0x1c, 0x8a, 0x01, - 0x81, 0x0a, 0xe8, 0x63, 0xe3, 0x68, 0xfe, 0x75, 0xf5, 0x7e, - 0xc4, 0x4f, 0xcf, 0x44, 0xd2, 0x59, 0xd9, 0x52, 0x7d, 0xf6, - 0x76, 0xfd, 0x6b, 0xe0, 0x60, 0xeb, 0x51, 0xda, 0x5a, 0xd1, - 0x47, 0xcc, 0x4c, 0xc7, 0x25, 0xae, 0x2e, 0xa5, 0x33, 0xb8, - 0x38, 0xb3, 0x09, 0x82, 0x02, 0x89, 0x1f, 0x94, 0x14, 0x9f, - 0xcd, 0x46, 0xc6, 0x4d, 0xdb, 0x50, 0xd0, 0x5b, 0xe1, 0x6a, - 0xea, 0x61, 0xf7, 0x7c, 0xfc, 0x77, 0x95, 0x1e, 0x9e, 0x15, - 0x83, 0x08, 0x88, 0x03, 0xb9, 0x32, 0xb2, 0x39, 0xaf, 0x24, - 0xa4, 0x2f, 0xfa, 0x71, 0xf1, 0x7a, 0xec, 0x67, 0xe7, 0x6c, - 0xd6, 0x5d, 0xdd, 0x56, 0xc0, 0x4b, 0xcb, 0x40, 0xa2, 0x29, - 0xa9, 0x22, 0xb4, 0x3f, 0xbf, 0x34, 0x8e, 0x05, 0x85, 0x0e, - 0x98, 0x13, 0x93, 0x18, 0x4a, 0xc1, 0x41, 0xca, 0x5c, 0xd7, - 0x57, 0xdc, 0x66, 0xed, 0x6d, 0xe6, 0x70, 0xfb, 0x7b, 0xf0, - 0x12, 0x99, 0x19, 0x92, 0x04, 0x8f, 0x0f, 0x84, 0x3e, 0xb5, - 0x35, 0xbe, 0x28, 0xa3, 0x23, 0xa8, 0x87, 0x0c, 0x8c, 0x07, - 0x91, 0x1a, 0x9a, 0x11, 0xab, 0x20, 0xa0, 0x2b, 0xbd, 0x36, - 0xb6, 0x3d, 0xdf, 0x54, 0xd4, 0x5f, 0xc9, 0x42, 0xc2, 0x49, - 0xf3, 0x78, 0xf8, 0x73, 0xe5, 0x6e, 0xee, 0x65, 0x37, 0xbc, - 0x3c, 0xb7, 0x21, 0xaa, 0x2a, 0xa1, 0x1b, 0x90, 0x10, 0x9b, - 0x0d, 0x86, 0x06, 0x8d, 0x6f, 0xe4, 0x64, 0xef, 0x79, 0xf2, - 0x72, 0xf9, 0x43, 0xc8, 0x48, 0xc3, 0x55, 0xde, 0x5e, 0xd5, - 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, - 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97, 0x28, 0xa4, 0x2d, 0xa1, - 0x22, 0xae, 0x27, 0xab, 0x3c, 0xb0, 0x39, 0xb5, 0x36, 0xba, - 0x33, 0xbf, 0x50, 0xdc, 0x55, 0xd9, 0x5a, 0xd6, 0x5f, 0xd3, - 0x44, 0xc8, 0x41, 0xcd, 0x4e, 0xc2, 0x4b, 0xc7, 0x78, 0xf4, - 0x7d, 0xf1, 0x72, 0xfe, 0x77, 0xfb, 0x6c, 0xe0, 0x69, 0xe5, - 0x66, 0xea, 0x63, 0xef, 0xa0, 0x2c, 0xa5, 0x29, 0xaa, 0x26, - 0xaf, 0x23, 0xb4, 0x38, 0xb1, 0x3d, 0xbe, 0x32, 0xbb, 0x37, - 0x88, 0x04, 0x8d, 0x01, 0x82, 0x0e, 0x87, 0x0b, 0x9c, 0x10, - 0x99, 0x15, 0x96, 0x1a, 0x93, 0x1f, 0xf0, 0x7c, 0xf5, 0x79, - 0xfa, 0x76, 0xff, 0x73, 0xe4, 0x68, 0xe1, 0x6d, 0xee, 0x62, - 0xeb, 0x67, 0xd8, 0x54, 0xdd, 0x51, 0xd2, 0x5e, 0xd7, 0x5b, - 0xcc, 0x40, 0xc9, 0x45, 0xc6, 0x4a, 0xc3, 0x4f, 0x5d, 0xd1, - 0x58, 0xd4, 0x57, 0xdb, 0x52, 0xde, 0x49, 0xc5, 0x4c, 0xc0, - 0x43, 0xcf, 0x46, 0xca, 0x75, 0xf9, 0x70, 0xfc, 0x7f, 0xf3, - 0x7a, 0xf6, 0x61, 0xed, 0x64, 0xe8, 0x6b, 0xe7, 0x6e, 0xe2, - 0x0d, 0x81, 0x08, 0x84, 0x07, 0x8b, 0x02, 0x8e, 0x19, 0x95, - 0x1c, 0x90, 0x13, 0x9f, 0x16, 0x9a, 0x25, 0xa9, 0x20, 0xac, - 0x2f, 0xa3, 0x2a, 0xa6, 0x31, 0xbd, 0x34, 0xb8, 0x3b, 0xb7, - 0x3e, 0xb2, 0xfd, 0x71, 0xf8, 0x74, 0xf7, 0x7b, 0xf2, 0x7e, - 0xe9, 0x65, 0xec, 0x60, 0xe3, 0x6f, 0xe6, 0x6a, 0xd5, 0x59, - 0xd0, 0x5c, 0xdf, 0x53, 0xda, 0x56, 0xc1, 0x4d, 0xc4, 0x48, - 0xcb, 0x47, 0xce, 0x42, 0xad, 0x21, 0xa8, 0x24, 0xa7, 0x2b, - 0xa2, 0x2e, 0xb9, 0x35, 0xbc, 0x30, 0xb3, 0x3f, 0xb6, 0x3a, - 0x85, 0x09, 0x80, 0x0c, 0x8f, 0x03, 0x8a, 0x06, 0x91, 0x1d, - 0x94, 0x18, 0x9b, 0x17, 0x9e, 0x12, 0x00, 0x8d, 0x07, 0x8a, - 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, - 0x15, 0x98, 0x38, 0xb5, 0x3f, 0xb2, 0x36, 0xbb, 0x31, 0xbc, - 0x24, 0xa9, 0x23, 0xae, 0x2a, 0xa7, 0x2d, 0xa0, 0x70, 0xfd, - 0x77, 0xfa, 0x7e, 0xf3, 0x79, 0xf4, 0x6c, 0xe1, 0x6b, 0xe6, - 0x62, 0xef, 0x65, 0xe8, 0x48, 0xc5, 0x4f, 0xc2, 0x46, 0xcb, - 0x41, 0xcc, 0x54, 0xd9, 0x53, 0xde, 0x5a, 0xd7, 0x5d, 0xd0, - 0xe0, 0x6d, 0xe7, 0x6a, 0xee, 0x63, 0xe9, 0x64, 0xfc, 0x71, - 0xfb, 0x76, 0xf2, 0x7f, 0xf5, 0x78, 0xd8, 0x55, 0xdf, 0x52, - 0xd6, 0x5b, 0xd1, 0x5c, 0xc4, 0x49, 0xc3, 0x4e, 0xca, 0x47, - 0xcd, 0x40, 0x90, 0x1d, 0x97, 0x1a, 0x9e, 0x13, 0x99, 0x14, - 0x8c, 0x01, 0x8b, 0x06, 0x82, 0x0f, 0x85, 0x08, 0xa8, 0x25, - 0xaf, 0x22, 0xa6, 0x2b, 0xa1, 0x2c, 0xb4, 0x39, 0xb3, 0x3e, - 0xba, 0x37, 0xbd, 0x30, 0xdd, 0x50, 0xda, 0x57, 0xd3, 0x5e, - 0xd4, 0x59, 0xc1, 0x4c, 0xc6, 0x4b, 0xcf, 0x42, 0xc8, 0x45, - 0xe5, 0x68, 0xe2, 0x6f, 0xeb, 0x66, 0xec, 0x61, 0xf9, 0x74, - 0xfe, 0x73, 0xf7, 0x7a, 0xf0, 0x7d, 0xad, 0x20, 0xaa, 0x27, - 0xa3, 0x2e, 0xa4, 0x29, 0xb1, 0x3c, 0xb6, 0x3b, 0xbf, 0x32, - 0xb8, 0x35, 0x95, 0x18, 0x92, 0x1f, 0x9b, 0x16, 0x9c, 0x11, - 0x89, 0x04, 0x8e, 0x03, 0x87, 0x0a, 0x80, 0x0d, 0x3d, 0xb0, - 0x3a, 0xb7, 0x33, 0xbe, 0x34, 0xb9, 0x21, 0xac, 0x26, 0xab, - 0x2f, 0xa2, 0x28, 0xa5, 0x05, 0x88, 0x02, 0x8f, 0x0b, 0x86, - 0x0c, 0x81, 0x19, 0x94, 0x1e, 0x93, 0x17, 0x9a, 0x10, 0x9d, - 0x4d, 0xc0, 0x4a, 0xc7, 0x43, 0xce, 0x44, 0xc9, 0x51, 0xdc, - 0x56, 0xdb, 0x5f, 0xd2, 0x58, 0xd5, 0x75, 0xf8, 0x72, 0xff, - 0x7b, 0xf6, 0x7c, 0xf1, 0x69, 0xe4, 0x6e, 0xe3, 0x67, 0xea, - 0x60, 0xed, 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, - 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89, 0x08, 0x86, - 0x09, 0x87, 0x0a, 0x84, 0x0b, 0x85, 0x0c, 0x82, 0x0d, 0x83, - 0x0e, 0x80, 0x0f, 0x81, 0x10, 0x9e, 0x11, 0x9f, 0x12, 0x9c, - 0x13, 0x9d, 0x14, 0x9a, 0x15, 0x9b, 0x16, 0x98, 0x17, 0x99, - 0x18, 0x96, 0x19, 0x97, 0x1a, 0x94, 0x1b, 0x95, 0x1c, 0x92, - 0x1d, 0x93, 0x1e, 0x90, 0x1f, 0x91, 0x20, 0xae, 0x21, 0xaf, - 0x22, 0xac, 0x23, 0xad, 0x24, 0xaa, 0x25, 0xab, 0x26, 0xa8, - 0x27, 0xa9, 0x28, 0xa6, 0x29, 0xa7, 0x2a, 0xa4, 0x2b, 0xa5, - 0x2c, 0xa2, 0x2d, 0xa3, 0x2e, 0xa0, 0x2f, 0xa1, 0x30, 0xbe, - 0x31, 0xbf, 0x32, 0xbc, 0x33, 0xbd, 0x34, 0xba, 0x35, 0xbb, - 0x36, 0xb8, 0x37, 0xb9, 0x38, 0xb6, 0x39, 0xb7, 0x3a, 0xb4, - 0x3b, 0xb5, 0x3c, 0xb2, 0x3d, 0xb3, 0x3e, 0xb0, 0x3f, 0xb1, - 0x40, 0xce, 0x41, 0xcf, 0x42, 0xcc, 0x43, 0xcd, 0x44, 0xca, - 0x45, 0xcb, 0x46, 0xc8, 0x47, 0xc9, 0x48, 0xc6, 0x49, 0xc7, - 0x4a, 0xc4, 0x4b, 0xc5, 0x4c, 0xc2, 0x4d, 0xc3, 0x4e, 0xc0, - 0x4f, 0xc1, 0x50, 0xde, 0x51, 0xdf, 0x52, 0xdc, 0x53, 0xdd, - 0x54, 0xda, 0x55, 0xdb, 0x56, 0xd8, 0x57, 0xd9, 0x58, 0xd6, - 0x59, 0xd7, 0x5a, 0xd4, 0x5b, 0xd5, 0x5c, 0xd2, 0x5d, 0xd3, - 0x5e, 0xd0, 0x5f, 0xd1, 0x60, 0xee, 0x61, 0xef, 0x62, 0xec, - 0x63, 0xed, 0x64, 0xea, 0x65, 0xeb, 0x66, 0xe8, 0x67, 0xe9, - 0x68, 0xe6, 0x69, 0xe7, 0x6a, 0xe4, 0x6b, 0xe5, 0x6c, 0xe2, - 0x6d, 0xe3, 0x6e, 0xe0, 0x6f, 0xe1, 0x70, 0xfe, 0x71, 0xff, - 0x72, 0xfc, 0x73, 0xfd, 0x74, 0xfa, 0x75, 0xfb, 0x76, 0xf8, - 0x77, 0xf9, 0x78, 0xf6, 0x79, 0xf7, 0x7a, 0xf4, 0x7b, 0xf5, - 0x7c, 0xf2, 0x7d, 0xf3, 0x7e, 0xf0, 0x7f, 0xf1, 0x00, 0x8f, - 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, - 0x0a, 0x85, 0x09, 0x86, 0x18, 0x97, 0x1b, 0x94, 0x1e, 0x91, - 0x1d, 0x92, 0x14, 0x9b, 0x17, 0x98, 0x12, 0x9d, 0x11, 0x9e, - 0x30, 0xbf, 0x33, 0xbc, 0x36, 0xb9, 0x35, 0xba, 0x3c, 0xb3, - 0x3f, 0xb0, 0x3a, 0xb5, 0x39, 0xb6, 0x28, 0xa7, 0x2b, 0xa4, - 0x2e, 0xa1, 0x2d, 0xa2, 0x24, 0xab, 0x27, 0xa8, 0x22, 0xad, - 0x21, 0xae, 0x60, 0xef, 0x63, 0xec, 0x66, 0xe9, 0x65, 0xea, - 0x6c, 0xe3, 0x6f, 0xe0, 0x6a, 0xe5, 0x69, 0xe6, 0x78, 0xf7, - 0x7b, 0xf4, 0x7e, 0xf1, 0x7d, 0xf2, 0x74, 0xfb, 0x77, 0xf8, - 0x72, 0xfd, 0x71, 0xfe, 0x50, 0xdf, 0x53, 0xdc, 0x56, 0xd9, - 0x55, 0xda, 0x5c, 0xd3, 0x5f, 0xd0, 0x5a, 0xd5, 0x59, 0xd6, - 0x48, 0xc7, 0x4b, 0xc4, 0x4e, 0xc1, 0x4d, 0xc2, 0x44, 0xcb, - 0x47, 0xc8, 0x42, 0xcd, 0x41, 0xce, 0xc0, 0x4f, 0xc3, 0x4c, - 0xc6, 0x49, 0xc5, 0x4a, 0xcc, 0x43, 0xcf, 0x40, 0xca, 0x45, - 0xc9, 0x46, 0xd8, 0x57, 0xdb, 0x54, 0xde, 0x51, 0xdd, 0x52, - 0xd4, 0x5b, 0xd7, 0x58, 0xd2, 0x5d, 0xd1, 0x5e, 0xf0, 0x7f, - 0xf3, 0x7c, 0xf6, 0x79, 0xf5, 0x7a, 0xfc, 0x73, 0xff, 0x70, - 0xfa, 0x75, 0xf9, 0x76, 0xe8, 0x67, 0xeb, 0x64, 0xee, 0x61, - 0xed, 0x62, 0xe4, 0x6b, 0xe7, 0x68, 0xe2, 0x6d, 0xe1, 0x6e, - 0xa0, 0x2f, 0xa3, 0x2c, 0xa6, 0x29, 0xa5, 0x2a, 0xac, 0x23, - 0xaf, 0x20, 0xaa, 0x25, 0xa9, 0x26, 0xb8, 0x37, 0xbb, 0x34, - 0xbe, 0x31, 0xbd, 0x32, 0xb4, 0x3b, 0xb7, 0x38, 0xb2, 0x3d, - 0xb1, 0x3e, 0x90, 0x1f, 0x93, 0x1c, 0x96, 0x19, 0x95, 0x1a, - 0x9c, 0x13, 0x9f, 0x10, 0x9a, 0x15, 0x99, 0x16, 0x88, 0x07, - 0x8b, 0x04, 0x8e, 0x01, 0x8d, 0x02, 0x84, 0x0b, 0x87, 0x08, - 0x82, 0x0d, 0x81, 0x0e, 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, - 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23, - 0xf5, 0x65, 0xc8, 0x58, 0x8f, 0x1f, 0xb2, 0x22, 0x01, 0x91, - 0x3c, 0xac, 0x7b, 0xeb, 0x46, 0xd6, 0xf7, 0x67, 0xca, 0x5a, - 0x8d, 0x1d, 0xb0, 0x20, 0x03, 0x93, 0x3e, 0xae, 0x79, 0xe9, - 0x44, 0xd4, 0x02, 0x92, 0x3f, 0xaf, 0x78, 0xe8, 0x45, 0xd5, - 0xf6, 0x66, 0xcb, 0x5b, 0x8c, 0x1c, 0xb1, 0x21, 0xf3, 0x63, - 0xce, 0x5e, 0x89, 0x19, 0xb4, 0x24, 0x07, 0x97, 0x3a, 0xaa, - 0x7d, 0xed, 0x40, 0xd0, 0x06, 0x96, 0x3b, 0xab, 0x7c, 0xec, - 0x41, 0xd1, 0xf2, 0x62, 0xcf, 0x5f, 0x88, 0x18, 0xb5, 0x25, - 0x04, 0x94, 0x39, 0xa9, 0x7e, 0xee, 0x43, 0xd3, 0xf0, 0x60, - 0xcd, 0x5d, 0x8a, 0x1a, 0xb7, 0x27, 0xf1, 0x61, 0xcc, 0x5c, - 0x8b, 0x1b, 0xb6, 0x26, 0x05, 0x95, 0x38, 0xa8, 0x7f, 0xef, - 0x42, 0xd2, 0xfb, 0x6b, 0xc6, 0x56, 0x81, 0x11, 0xbc, 0x2c, - 0x0f, 0x9f, 0x32, 0xa2, 0x75, 0xe5, 0x48, 0xd8, 0x0e, 0x9e, - 0x33, 0xa3, 0x74, 0xe4, 0x49, 0xd9, 0xfa, 0x6a, 0xc7, 0x57, - 0x80, 0x10, 0xbd, 0x2d, 0x0c, 0x9c, 0x31, 0xa1, 0x76, 0xe6, - 0x4b, 0xdb, 0xf8, 0x68, 0xc5, 0x55, 0x82, 0x12, 0xbf, 0x2f, - 0xf9, 0x69, 0xc4, 0x54, 0x83, 0x13, 0xbe, 0x2e, 0x0d, 0x9d, - 0x30, 0xa0, 0x77, 0xe7, 0x4a, 0xda, 0x08, 0x98, 0x35, 0xa5, - 0x72, 0xe2, 0x4f, 0xdf, 0xfc, 0x6c, 0xc1, 0x51, 0x86, 0x16, - 0xbb, 0x2b, 0xfd, 0x6d, 0xc0, 0x50, 0x87, 0x17, 0xba, 0x2a, - 0x09, 0x99, 0x34, 0xa4, 0x73, 0xe3, 0x4e, 0xde, 0xff, 0x6f, - 0xc2, 0x52, 0x85, 0x15, 0xb8, 0x28, 0x0b, 0x9b, 0x36, 0xa6, - 0x71, 0xe1, 0x4c, 0xdc, 0x0a, 0x9a, 0x37, 0xa7, 0x70, 0xe0, - 0x4d, 0xdd, 0xfe, 0x6e, 0xc3, 0x53, 0x84, 0x14, 0xb9, 0x29, - 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, - 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c, 0xe5, 0x74, 0xda, 0x4b, - 0x9b, 0x0a, 0xa4, 0x35, 0x19, 0x88, 0x26, 0xb7, 0x67, 0xf6, - 0x58, 0xc9, 0xd7, 0x46, 0xe8, 0x79, 0xa9, 0x38, 0x96, 0x07, - 0x2b, 0xba, 0x14, 0x85, 0x55, 0xc4, 0x6a, 0xfb, 0x32, 0xa3, - 0x0d, 0x9c, 0x4c, 0xdd, 0x73, 0xe2, 0xce, 0x5f, 0xf1, 0x60, - 0xb0, 0x21, 0x8f, 0x1e, 0xb3, 0x22, 0x8c, 0x1d, 0xcd, 0x5c, - 0xf2, 0x63, 0x4f, 0xde, 0x70, 0xe1, 0x31, 0xa0, 0x0e, 0x9f, - 0x56, 0xc7, 0x69, 0xf8, 0x28, 0xb9, 0x17, 0x86, 0xaa, 0x3b, - 0x95, 0x04, 0xd4, 0x45, 0xeb, 0x7a, 0x64, 0xf5, 0x5b, 0xca, - 0x1a, 0x8b, 0x25, 0xb4, 0x98, 0x09, 0xa7, 0x36, 0xe6, 0x77, - 0xd9, 0x48, 0x81, 0x10, 0xbe, 0x2f, 0xff, 0x6e, 0xc0, 0x51, - 0x7d, 0xec, 0x42, 0xd3, 0x03, 0x92, 0x3c, 0xad, 0x7b, 0xea, - 0x44, 0xd5, 0x05, 0x94, 0x3a, 0xab, 0x87, 0x16, 0xb8, 0x29, - 0xf9, 0x68, 0xc6, 0x57, 0x9e, 0x0f, 0xa1, 0x30, 0xe0, 0x71, - 0xdf, 0x4e, 0x62, 0xf3, 0x5d, 0xcc, 0x1c, 0x8d, 0x23, 0xb2, - 0xac, 0x3d, 0x93, 0x02, 0xd2, 0x43, 0xed, 0x7c, 0x50, 0xc1, - 0x6f, 0xfe, 0x2e, 0xbf, 0x11, 0x80, 0x49, 0xd8, 0x76, 0xe7, - 0x37, 0xa6, 0x08, 0x99, 0xb5, 0x24, 0x8a, 0x1b, 0xcb, 0x5a, - 0xf4, 0x65, 0xc8, 0x59, 0xf7, 0x66, 0xb6, 0x27, 0x89, 0x18, - 0x34, 0xa5, 0x0b, 0x9a, 0x4a, 0xdb, 0x75, 0xe4, 0x2d, 0xbc, - 0x12, 0x83, 0x53, 0xc2, 0x6c, 0xfd, 0xd1, 0x40, 0xee, 0x7f, - 0xaf, 0x3e, 0x90, 0x01, 0x1f, 0x8e, 0x20, 0xb1, 0x61, 0xf0, - 0x5e, 0xcf, 0xe3, 0x72, 0xdc, 0x4d, 0x9d, 0x0c, 0xa2, 0x33, - 0xfa, 0x6b, 0xc5, 0x54, 0x84, 0x15, 0xbb, 0x2a, 0x06, 0x97, - 0x39, 0xa8, 0x78, 0xe9, 0x47, 0xd6, 0x00, 0x92, 0x39, 0xab, - 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, - 0xaf, 0x3d, 0xd5, 0x47, 0xec, 0x7e, 0xa7, 0x35, 0x9e, 0x0c, - 0x31, 0xa3, 0x08, 0x9a, 0x43, 0xd1, 0x7a, 0xe8, 0xb7, 0x25, - 0x8e, 0x1c, 0xc5, 0x57, 0xfc, 0x6e, 0x53, 0xc1, 0x6a, 0xf8, - 0x21, 0xb3, 0x18, 0x8a, 0x62, 0xf0, 0x5b, 0xc9, 0x10, 0x82, - 0x29, 0xbb, 0x86, 0x14, 0xbf, 0x2d, 0xf4, 0x66, 0xcd, 0x5f, - 0x73, 0xe1, 0x4a, 0xd8, 0x01, 0x93, 0x38, 0xaa, 0x97, 0x05, - 0xae, 0x3c, 0xe5, 0x77, 0xdc, 0x4e, 0xa6, 0x34, 0x9f, 0x0d, - 0xd4, 0x46, 0xed, 0x7f, 0x42, 0xd0, 0x7b, 0xe9, 0x30, 0xa2, - 0x09, 0x9b, 0xc4, 0x56, 0xfd, 0x6f, 0xb6, 0x24, 0x8f, 0x1d, - 0x20, 0xb2, 0x19, 0x8b, 0x52, 0xc0, 0x6b, 0xf9, 0x11, 0x83, - 0x28, 0xba, 0x63, 0xf1, 0x5a, 0xc8, 0xf5, 0x67, 0xcc, 0x5e, - 0x87, 0x15, 0xbe, 0x2c, 0xe6, 0x74, 0xdf, 0x4d, 0x94, 0x06, - 0xad, 0x3f, 0x02, 0x90, 0x3b, 0xa9, 0x70, 0xe2, 0x49, 0xdb, - 0x33, 0xa1, 0x0a, 0x98, 0x41, 0xd3, 0x78, 0xea, 0xd7, 0x45, - 0xee, 0x7c, 0xa5, 0x37, 0x9c, 0x0e, 0x51, 0xc3, 0x68, 0xfa, - 0x23, 0xb1, 0x1a, 0x88, 0xb5, 0x27, 0x8c, 0x1e, 0xc7, 0x55, - 0xfe, 0x6c, 0x84, 0x16, 0xbd, 0x2f, 0xf6, 0x64, 0xcf, 0x5d, - 0x60, 0xf2, 0x59, 0xcb, 0x12, 0x80, 0x2b, 0xb9, 0x95, 0x07, - 0xac, 0x3e, 0xe7, 0x75, 0xde, 0x4c, 0x71, 0xe3, 0x48, 0xda, - 0x03, 0x91, 0x3a, 0xa8, 0x40, 0xd2, 0x79, 0xeb, 0x32, 0xa0, - 0x0b, 0x99, 0xa4, 0x36, 0x9d, 0x0f, 0xd6, 0x44, 0xef, 0x7d, - 0x22, 0xb0, 0x1b, 0x89, 0x50, 0xc2, 0x69, 0xfb, 0xc6, 0x54, - 0xff, 0x6d, 0xb4, 0x26, 0x8d, 0x1f, 0xf7, 0x65, 0xce, 0x5c, - 0x85, 0x17, 0xbc, 0x2e, 0x13, 0x81, 0x2a, 0xb8, 0x61, 0xf3, - 0x58, 0xca, 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, - 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32, 0xc5, 0x56, - 0xfe, 0x6d, 0xb3, 0x20, 0x88, 0x1b, 0x29, 0xba, 0x12, 0x81, - 0x5f, 0xcc, 0x64, 0xf7, 0x97, 0x04, 0xac, 0x3f, 0xe1, 0x72, - 0xda, 0x49, 0x7b, 0xe8, 0x40, 0xd3, 0x0d, 0x9e, 0x36, 0xa5, - 0x52, 0xc1, 0x69, 0xfa, 0x24, 0xb7, 0x1f, 0x8c, 0xbe, 0x2d, - 0x85, 0x16, 0xc8, 0x5b, 0xf3, 0x60, 0x33, 0xa0, 0x08, 0x9b, - 0x45, 0xd6, 0x7e, 0xed, 0xdf, 0x4c, 0xe4, 0x77, 0xa9, 0x3a, - 0x92, 0x01, 0xf6, 0x65, 0xcd, 0x5e, 0x80, 0x13, 0xbb, 0x28, - 0x1a, 0x89, 0x21, 0xb2, 0x6c, 0xff, 0x57, 0xc4, 0xa4, 0x37, - 0x9f, 0x0c, 0xd2, 0x41, 0xe9, 0x7a, 0x48, 0xdb, 0x73, 0xe0, - 0x3e, 0xad, 0x05, 0x96, 0x61, 0xf2, 0x5a, 0xc9, 0x17, 0x84, - 0x2c, 0xbf, 0x8d, 0x1e, 0xb6, 0x25, 0xfb, 0x68, 0xc0, 0x53, - 0x66, 0xf5, 0x5d, 0xce, 0x10, 0x83, 0x2b, 0xb8, 0x8a, 0x19, - 0xb1, 0x22, 0xfc, 0x6f, 0xc7, 0x54, 0xa3, 0x30, 0x98, 0x0b, - 0xd5, 0x46, 0xee, 0x7d, 0x4f, 0xdc, 0x74, 0xe7, 0x39, 0xaa, - 0x02, 0x91, 0xf1, 0x62, 0xca, 0x59, 0x87, 0x14, 0xbc, 0x2f, - 0x1d, 0x8e, 0x26, 0xb5, 0x6b, 0xf8, 0x50, 0xc3, 0x34, 0xa7, - 0x0f, 0x9c, 0x42, 0xd1, 0x79, 0xea, 0xd8, 0x4b, 0xe3, 0x70, - 0xae, 0x3d, 0x95, 0x06, 0x55, 0xc6, 0x6e, 0xfd, 0x23, 0xb0, - 0x18, 0x8b, 0xb9, 0x2a, 0x82, 0x11, 0xcf, 0x5c, 0xf4, 0x67, - 0x90, 0x03, 0xab, 0x38, 0xe6, 0x75, 0xdd, 0x4e, 0x7c, 0xef, - 0x47, 0xd4, 0x0a, 0x99, 0x31, 0xa2, 0xc2, 0x51, 0xf9, 0x6a, - 0xb4, 0x27, 0x8f, 0x1c, 0x2e, 0xbd, 0x15, 0x86, 0x58, 0xcb, - 0x63, 0xf0, 0x07, 0x94, 0x3c, 0xaf, 0x71, 0xe2, 0x4a, 0xd9, - 0xeb, 0x78, 0xd0, 0x43, 0x9d, 0x0e, 0xa6, 0x35, 0x00, 0x94, - 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, - 0xbe, 0x2a, 0x8b, 0x1f, 0xb5, 0x21, 0x80, 0x14, 0xdf, 0x4b, - 0xea, 0x7e, 0x61, 0xf5, 0x54, 0xc0, 0x0b, 0x9f, 0x3e, 0xaa, - 0x77, 0xe3, 0x42, 0xd6, 0x1d, 0x89, 0x28, 0xbc, 0xa3, 0x37, - 0x96, 0x02, 0xc9, 0x5d, 0xfc, 0x68, 0xc2, 0x56, 0xf7, 0x63, - 0xa8, 0x3c, 0x9d, 0x09, 0x16, 0x82, 0x23, 0xb7, 0x7c, 0xe8, - 0x49, 0xdd, 0xee, 0x7a, 0xdb, 0x4f, 0x84, 0x10, 0xb1, 0x25, - 0x3a, 0xae, 0x0f, 0x9b, 0x50, 0xc4, 0x65, 0xf1, 0x5b, 0xcf, - 0x6e, 0xfa, 0x31, 0xa5, 0x04, 0x90, 0x8f, 0x1b, 0xba, 0x2e, - 0xe5, 0x71, 0xd0, 0x44, 0x99, 0x0d, 0xac, 0x38, 0xf3, 0x67, - 0xc6, 0x52, 0x4d, 0xd9, 0x78, 0xec, 0x27, 0xb3, 0x12, 0x86, - 0x2c, 0xb8, 0x19, 0x8d, 0x46, 0xd2, 0x73, 0xe7, 0xf8, 0x6c, - 0xcd, 0x59, 0x92, 0x06, 0xa7, 0x33, 0xc1, 0x55, 0xf4, 0x60, - 0xab, 0x3f, 0x9e, 0x0a, 0x15, 0x81, 0x20, 0xb4, 0x7f, 0xeb, - 0x4a, 0xde, 0x74, 0xe0, 0x41, 0xd5, 0x1e, 0x8a, 0x2b, 0xbf, - 0xa0, 0x34, 0x95, 0x01, 0xca, 0x5e, 0xff, 0x6b, 0xb6, 0x22, - 0x83, 0x17, 0xdc, 0x48, 0xe9, 0x7d, 0x62, 0xf6, 0x57, 0xc3, - 0x08, 0x9c, 0x3d, 0xa9, 0x03, 0x97, 0x36, 0xa2, 0x69, 0xfd, - 0x5c, 0xc8, 0xd7, 0x43, 0xe2, 0x76, 0xbd, 0x29, 0x88, 0x1c, - 0x2f, 0xbb, 0x1a, 0x8e, 0x45, 0xd1, 0x70, 0xe4, 0xfb, 0x6f, - 0xce, 0x5a, 0x91, 0x05, 0xa4, 0x30, 0x9a, 0x0e, 0xaf, 0x3b, - 0xf0, 0x64, 0xc5, 0x51, 0x4e, 0xda, 0x7b, 0xef, 0x24, 0xb0, - 0x11, 0x85, 0x58, 0xcc, 0x6d, 0xf9, 0x32, 0xa6, 0x07, 0x93, - 0x8c, 0x18, 0xb9, 0x2d, 0xe6, 0x72, 0xd3, 0x47, 0xed, 0x79, - 0xd8, 0x4c, 0x87, 0x13, 0xb2, 0x26, 0x39, 0xad, 0x0c, 0x98, - 0x53, 0xc7, 0x66, 0xf2, 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, - 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10, - 0xa5, 0x30, 0x92, 0x07, 0xcb, 0x5e, 0xfc, 0x69, 0x79, 0xec, - 0x4e, 0xdb, 0x17, 0x82, 0x20, 0xb5, 0x57, 0xc2, 0x60, 0xf5, - 0x39, 0xac, 0x0e, 0x9b, 0x8b, 0x1e, 0xbc, 0x29, 0xe5, 0x70, - 0xd2, 0x47, 0xf2, 0x67, 0xc5, 0x50, 0x9c, 0x09, 0xab, 0x3e, - 0x2e, 0xbb, 0x19, 0x8c, 0x40, 0xd5, 0x77, 0xe2, 0xae, 0x3b, - 0x99, 0x0c, 0xc0, 0x55, 0xf7, 0x62, 0x72, 0xe7, 0x45, 0xd0, - 0x1c, 0x89, 0x2b, 0xbe, 0x0b, 0x9e, 0x3c, 0xa9, 0x65, 0xf0, - 0x52, 0xc7, 0xd7, 0x42, 0xe0, 0x75, 0xb9, 0x2c, 0x8e, 0x1b, - 0xf9, 0x6c, 0xce, 0x5b, 0x97, 0x02, 0xa0, 0x35, 0x25, 0xb0, - 0x12, 0x87, 0x4b, 0xde, 0x7c, 0xe9, 0x5c, 0xc9, 0x6b, 0xfe, - 0x32, 0xa7, 0x05, 0x90, 0x80, 0x15, 0xb7, 0x22, 0xee, 0x7b, - 0xd9, 0x4c, 0x41, 0xd4, 0x76, 0xe3, 0x2f, 0xba, 0x18, 0x8d, - 0x9d, 0x08, 0xaa, 0x3f, 0xf3, 0x66, 0xc4, 0x51, 0xe4, 0x71, - 0xd3, 0x46, 0x8a, 0x1f, 0xbd, 0x28, 0x38, 0xad, 0x0f, 0x9a, - 0x56, 0xc3, 0x61, 0xf4, 0x16, 0x83, 0x21, 0xb4, 0x78, 0xed, - 0x4f, 0xda, 0xca, 0x5f, 0xfd, 0x68, 0xa4, 0x31, 0x93, 0x06, - 0xb3, 0x26, 0x84, 0x11, 0xdd, 0x48, 0xea, 0x7f, 0x6f, 0xfa, - 0x58, 0xcd, 0x01, 0x94, 0x36, 0xa3, 0xef, 0x7a, 0xd8, 0x4d, - 0x81, 0x14, 0xb6, 0x23, 0x33, 0xa6, 0x04, 0x91, 0x5d, 0xc8, - 0x6a, 0xff, 0x4a, 0xdf, 0x7d, 0xe8, 0x24, 0xb1, 0x13, 0x86, - 0x96, 0x03, 0xa1, 0x34, 0xf8, 0x6d, 0xcf, 0x5a, 0xb8, 0x2d, - 0x8f, 0x1a, 0xd6, 0x43, 0xe1, 0x74, 0x64, 0xf1, 0x53, 0xc6, - 0x0a, 0x9f, 0x3d, 0xa8, 0x1d, 0x88, 0x2a, 0xbf, 0x73, 0xe6, - 0x44, 0xd1, 0xc1, 0x54, 0xf6, 0x63, 0xaf, 0x3a, 0x98, 0x0d, - 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, - 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01, 0x95, 0x03, 0xa4, 0x32, - 0xf7, 0x61, 0xc6, 0x50, 0x51, 0xc7, 0x60, 0xf6, 0x33, 0xa5, - 0x02, 0x94, 0x37, 0xa1, 0x06, 0x90, 0x55, 0xc3, 0x64, 0xf2, - 0xf3, 0x65, 0xc2, 0x54, 0x91, 0x07, 0xa0, 0x36, 0xa2, 0x34, - 0x93, 0x05, 0xc0, 0x56, 0xf1, 0x67, 0x66, 0xf0, 0x57, 0xc1, - 0x04, 0x92, 0x35, 0xa3, 0x6e, 0xf8, 0x5f, 0xc9, 0x0c, 0x9a, - 0x3d, 0xab, 0xaa, 0x3c, 0x9b, 0x0d, 0xc8, 0x5e, 0xf9, 0x6f, - 0xfb, 0x6d, 0xca, 0x5c, 0x99, 0x0f, 0xa8, 0x3e, 0x3f, 0xa9, - 0x0e, 0x98, 0x5d, 0xcb, 0x6c, 0xfa, 0x59, 0xcf, 0x68, 0xfe, - 0x3b, 0xad, 0x0a, 0x9c, 0x9d, 0x0b, 0xac, 0x3a, 0xff, 0x69, - 0xce, 0x58, 0xcc, 0x5a, 0xfd, 0x6b, 0xae, 0x38, 0x9f, 0x09, - 0x08, 0x9e, 0x39, 0xaf, 0x6a, 0xfc, 0x5b, 0xcd, 0xdc, 0x4a, - 0xed, 0x7b, 0xbe, 0x28, 0x8f, 0x19, 0x18, 0x8e, 0x29, 0xbf, - 0x7a, 0xec, 0x4b, 0xdd, 0x49, 0xdf, 0x78, 0xee, 0x2b, 0xbd, - 0x1a, 0x8c, 0x8d, 0x1b, 0xbc, 0x2a, 0xef, 0x79, 0xde, 0x48, - 0xeb, 0x7d, 0xda, 0x4c, 0x89, 0x1f, 0xb8, 0x2e, 0x2f, 0xb9, - 0x1e, 0x88, 0x4d, 0xdb, 0x7c, 0xea, 0x7e, 0xe8, 0x4f, 0xd9, - 0x1c, 0x8a, 0x2d, 0xbb, 0xba, 0x2c, 0x8b, 0x1d, 0xd8, 0x4e, - 0xe9, 0x7f, 0xb2, 0x24, 0x83, 0x15, 0xd0, 0x46, 0xe1, 0x77, - 0x76, 0xe0, 0x47, 0xd1, 0x14, 0x82, 0x25, 0xb3, 0x27, 0xb1, - 0x16, 0x80, 0x45, 0xd3, 0x74, 0xe2, 0xe3, 0x75, 0xd2, 0x44, - 0x81, 0x17, 0xb0, 0x26, 0x85, 0x13, 0xb4, 0x22, 0xe7, 0x71, - 0xd6, 0x40, 0x41, 0xd7, 0x70, 0xe6, 0x23, 0xb5, 0x12, 0x84, - 0x10, 0x86, 0x21, 0xb7, 0x72, 0xe4, 0x43, 0xd5, 0xd4, 0x42, - 0xe5, 0x73, 0xb6, 0x20, 0x87, 0x11, 0x00, 0x97, 0x33, 0xa4, - 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, - 0x99, 0x0e, 0x85, 0x12, 0xb6, 0x21, 0xe3, 0x74, 0xd0, 0x47, - 0x49, 0xde, 0x7a, 0xed, 0x2f, 0xb8, 0x1c, 0x8b, 0x17, 0x80, - 0x24, 0xb3, 0x71, 0xe6, 0x42, 0xd5, 0xdb, 0x4c, 0xe8, 0x7f, - 0xbd, 0x2a, 0x8e, 0x19, 0x92, 0x05, 0xa1, 0x36, 0xf4, 0x63, - 0xc7, 0x50, 0x5e, 0xc9, 0x6d, 0xfa, 0x38, 0xaf, 0x0b, 0x9c, - 0x2e, 0xb9, 0x1d, 0x8a, 0x48, 0xdf, 0x7b, 0xec, 0xe2, 0x75, - 0xd1, 0x46, 0x84, 0x13, 0xb7, 0x20, 0xab, 0x3c, 0x98, 0x0f, - 0xcd, 0x5a, 0xfe, 0x69, 0x67, 0xf0, 0x54, 0xc3, 0x01, 0x96, - 0x32, 0xa5, 0x39, 0xae, 0x0a, 0x9d, 0x5f, 0xc8, 0x6c, 0xfb, - 0xf5, 0x62, 0xc6, 0x51, 0x93, 0x04, 0xa0, 0x37, 0xbc, 0x2b, - 0x8f, 0x18, 0xda, 0x4d, 0xe9, 0x7e, 0x70, 0xe7, 0x43, 0xd4, - 0x16, 0x81, 0x25, 0xb2, 0x5c, 0xcb, 0x6f, 0xf8, 0x3a, 0xad, - 0x09, 0x9e, 0x90, 0x07, 0xa3, 0x34, 0xf6, 0x61, 0xc5, 0x52, - 0xd9, 0x4e, 0xea, 0x7d, 0xbf, 0x28, 0x8c, 0x1b, 0x15, 0x82, - 0x26, 0xb1, 0x73, 0xe4, 0x40, 0xd7, 0x4b, 0xdc, 0x78, 0xef, - 0x2d, 0xba, 0x1e, 0x89, 0x87, 0x10, 0xb4, 0x23, 0xe1, 0x76, - 0xd2, 0x45, 0xce, 0x59, 0xfd, 0x6a, 0xa8, 0x3f, 0x9b, 0x0c, - 0x02, 0x95, 0x31, 0xa6, 0x64, 0xf3, 0x57, 0xc0, 0x72, 0xe5, - 0x41, 0xd6, 0x14, 0x83, 0x27, 0xb0, 0xbe, 0x29, 0x8d, 0x1a, - 0xd8, 0x4f, 0xeb, 0x7c, 0xf7, 0x60, 0xc4, 0x53, 0x91, 0x06, - 0xa2, 0x35, 0x3b, 0xac, 0x08, 0x9f, 0x5d, 0xca, 0x6e, 0xf9, - 0x65, 0xf2, 0x56, 0xc1, 0x03, 0x94, 0x30, 0xa7, 0xa9, 0x3e, - 0x9a, 0x0d, 0xcf, 0x58, 0xfc, 0x6b, 0xe0, 0x77, 0xd3, 0x44, - 0x86, 0x11, 0xb5, 0x22, 0x2c, 0xbb, 0x1f, 0x88, 0x4a, 0xdd, - 0x79, 0xee, 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, - 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b, 0x75, 0xed, - 0x58, 0xc0, 0x2f, 0xb7, 0x02, 0x9a, 0xc1, 0x59, 0xec, 0x74, - 0x9b, 0x03, 0xb6, 0x2e, 0xea, 0x72, 0xc7, 0x5f, 0xb0, 0x28, - 0x9d, 0x05, 0x5e, 0xc6, 0x73, 0xeb, 0x04, 0x9c, 0x29, 0xb1, - 0x9f, 0x07, 0xb2, 0x2a, 0xc5, 0x5d, 0xe8, 0x70, 0x2b, 0xb3, - 0x06, 0x9e, 0x71, 0xe9, 0x5c, 0xc4, 0xc9, 0x51, 0xe4, 0x7c, - 0x93, 0x0b, 0xbe, 0x26, 0x7d, 0xe5, 0x50, 0xc8, 0x27, 0xbf, - 0x0a, 0x92, 0xbc, 0x24, 0x91, 0x09, 0xe6, 0x7e, 0xcb, 0x53, - 0x08, 0x90, 0x25, 0xbd, 0x52, 0xca, 0x7f, 0xe7, 0x23, 0xbb, - 0x0e, 0x96, 0x79, 0xe1, 0x54, 0xcc, 0x97, 0x0f, 0xba, 0x22, - 0xcd, 0x55, 0xe0, 0x78, 0x56, 0xce, 0x7b, 0xe3, 0x0c, 0x94, - 0x21, 0xb9, 0xe2, 0x7a, 0xcf, 0x57, 0xb8, 0x20, 0x95, 0x0d, - 0x8f, 0x17, 0xa2, 0x3a, 0xd5, 0x4d, 0xf8, 0x60, 0x3b, 0xa3, - 0x16, 0x8e, 0x61, 0xf9, 0x4c, 0xd4, 0xfa, 0x62, 0xd7, 0x4f, - 0xa0, 0x38, 0x8d, 0x15, 0x4e, 0xd6, 0x63, 0xfb, 0x14, 0x8c, - 0x39, 0xa1, 0x65, 0xfd, 0x48, 0xd0, 0x3f, 0xa7, 0x12, 0x8a, - 0xd1, 0x49, 0xfc, 0x64, 0x8b, 0x13, 0xa6, 0x3e, 0x10, 0x88, - 0x3d, 0xa5, 0x4a, 0xd2, 0x67, 0xff, 0xa4, 0x3c, 0x89, 0x11, - 0xfe, 0x66, 0xd3, 0x4b, 0x46, 0xde, 0x6b, 0xf3, 0x1c, 0x84, - 0x31, 0xa9, 0xf2, 0x6a, 0xdf, 0x47, 0xa8, 0x30, 0x85, 0x1d, - 0x33, 0xab, 0x1e, 0x86, 0x69, 0xf1, 0x44, 0xdc, 0x87, 0x1f, - 0xaa, 0x32, 0xdd, 0x45, 0xf0, 0x68, 0xac, 0x34, 0x81, 0x19, - 0xf6, 0x6e, 0xdb, 0x43, 0x18, 0x80, 0x35, 0xad, 0x42, 0xda, - 0x6f, 0xf7, 0xd9, 0x41, 0xf4, 0x6c, 0x83, 0x1b, 0xae, 0x36, - 0x6d, 0xf5, 0x40, 0xd8, 0x37, 0xaf, 0x1a, 0x82, 0x00, 0x99, - 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, - 0xe2, 0x7b, 0xcd, 0x54, 0x65, 0xfc, 0x4a, 0xd3, 0x3b, 0xa2, - 0x14, 0x8d, 0xd9, 0x40, 0xf6, 0x6f, 0x87, 0x1e, 0xa8, 0x31, - 0xca, 0x53, 0xe5, 0x7c, 0x94, 0x0d, 0xbb, 0x22, 0x76, 0xef, - 0x59, 0xc0, 0x28, 0xb1, 0x07, 0x9e, 0xaf, 0x36, 0x80, 0x19, - 0xf1, 0x68, 0xde, 0x47, 0x13, 0x8a, 0x3c, 0xa5, 0x4d, 0xd4, - 0x62, 0xfb, 0x89, 0x10, 0xa6, 0x3f, 0xd7, 0x4e, 0xf8, 0x61, - 0x35, 0xac, 0x1a, 0x83, 0x6b, 0xf2, 0x44, 0xdd, 0xec, 0x75, - 0xc3, 0x5a, 0xb2, 0x2b, 0x9d, 0x04, 0x50, 0xc9, 0x7f, 0xe6, - 0x0e, 0x97, 0x21, 0xb8, 0x43, 0xda, 0x6c, 0xf5, 0x1d, 0x84, - 0x32, 0xab, 0xff, 0x66, 0xd0, 0x49, 0xa1, 0x38, 0x8e, 0x17, - 0x26, 0xbf, 0x09, 0x90, 0x78, 0xe1, 0x57, 0xce, 0x9a, 0x03, - 0xb5, 0x2c, 0xc4, 0x5d, 0xeb, 0x72, 0x0f, 0x96, 0x20, 0xb9, - 0x51, 0xc8, 0x7e, 0xe7, 0xb3, 0x2a, 0x9c, 0x05, 0xed, 0x74, - 0xc2, 0x5b, 0x6a, 0xf3, 0x45, 0xdc, 0x34, 0xad, 0x1b, 0x82, - 0xd6, 0x4f, 0xf9, 0x60, 0x88, 0x11, 0xa7, 0x3e, 0xc5, 0x5c, - 0xea, 0x73, 0x9b, 0x02, 0xb4, 0x2d, 0x79, 0xe0, 0x56, 0xcf, - 0x27, 0xbe, 0x08, 0x91, 0xa0, 0x39, 0x8f, 0x16, 0xfe, 0x67, - 0xd1, 0x48, 0x1c, 0x85, 0x33, 0xaa, 0x42, 0xdb, 0x6d, 0xf4, - 0x86, 0x1f, 0xa9, 0x30, 0xd8, 0x41, 0xf7, 0x6e, 0x3a, 0xa3, - 0x15, 0x8c, 0x64, 0xfd, 0x4b, 0xd2, 0xe3, 0x7a, 0xcc, 0x55, - 0xbd, 0x24, 0x92, 0x0b, 0x5f, 0xc6, 0x70, 0xe9, 0x01, 0x98, - 0x2e, 0xb7, 0x4c, 0xd5, 0x63, 0xfa, 0x12, 0x8b, 0x3d, 0xa4, - 0xf0, 0x69, 0xdf, 0x46, 0xae, 0x37, 0x81, 0x18, 0x29, 0xb0, - 0x06, 0x9f, 0x77, 0xee, 0x58, 0xc1, 0x95, 0x0c, 0xba, 0x23, - 0xcb, 0x52, 0xe4, 0x7d, 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, - 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45, - 0x55, 0xcf, 0x7c, 0xe6, 0x07, 0x9d, 0x2e, 0xb4, 0xf1, 0x6b, - 0xd8, 0x42, 0xa3, 0x39, 0x8a, 0x10, 0xaa, 0x30, 0x83, 0x19, - 0xf8, 0x62, 0xd1, 0x4b, 0x0e, 0x94, 0x27, 0xbd, 0x5c, 0xc6, - 0x75, 0xef, 0xff, 0x65, 0xd6, 0x4c, 0xad, 0x37, 0x84, 0x1e, - 0x5b, 0xc1, 0x72, 0xe8, 0x09, 0x93, 0x20, 0xba, 0x49, 0xd3, - 0x60, 0xfa, 0x1b, 0x81, 0x32, 0xa8, 0xed, 0x77, 0xc4, 0x5e, - 0xbf, 0x25, 0x96, 0x0c, 0x1c, 0x86, 0x35, 0xaf, 0x4e, 0xd4, - 0x67, 0xfd, 0xb8, 0x22, 0x91, 0x0b, 0xea, 0x70, 0xc3, 0x59, - 0xe3, 0x79, 0xca, 0x50, 0xb1, 0x2b, 0x98, 0x02, 0x47, 0xdd, - 0x6e, 0xf4, 0x15, 0x8f, 0x3c, 0xa6, 0xb6, 0x2c, 0x9f, 0x05, - 0xe4, 0x7e, 0xcd, 0x57, 0x12, 0x88, 0x3b, 0xa1, 0x40, 0xda, - 0x69, 0xf3, 0x92, 0x08, 0xbb, 0x21, 0xc0, 0x5a, 0xe9, 0x73, - 0x36, 0xac, 0x1f, 0x85, 0x64, 0xfe, 0x4d, 0xd7, 0xc7, 0x5d, - 0xee, 0x74, 0x95, 0x0f, 0xbc, 0x26, 0x63, 0xf9, 0x4a, 0xd0, - 0x31, 0xab, 0x18, 0x82, 0x38, 0xa2, 0x11, 0x8b, 0x6a, 0xf0, - 0x43, 0xd9, 0x9c, 0x06, 0xb5, 0x2f, 0xce, 0x54, 0xe7, 0x7d, - 0x6d, 0xf7, 0x44, 0xde, 0x3f, 0xa5, 0x16, 0x8c, 0xc9, 0x53, - 0xe0, 0x7a, 0x9b, 0x01, 0xb2, 0x28, 0xdb, 0x41, 0xf2, 0x68, - 0x89, 0x13, 0xa0, 0x3a, 0x7f, 0xe5, 0x56, 0xcc, 0x2d, 0xb7, - 0x04, 0x9e, 0x8e, 0x14, 0xa7, 0x3d, 0xdc, 0x46, 0xf5, 0x6f, - 0x2a, 0xb0, 0x03, 0x99, 0x78, 0xe2, 0x51, 0xcb, 0x71, 0xeb, - 0x58, 0xc2, 0x23, 0xb9, 0x0a, 0x90, 0xd5, 0x4f, 0xfc, 0x66, - 0x87, 0x1d, 0xae, 0x34, 0x24, 0xbe, 0x0d, 0x97, 0x76, 0xec, - 0x5f, 0xc5, 0x80, 0x1a, 0xa9, 0x33, 0xd2, 0x48, 0xfb, 0x61, - 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, - 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a, 0x45, 0xde, 0x6e, 0xf5, - 0x13, 0x88, 0x38, 0xa3, 0xe9, 0x72, 0xc2, 0x59, 0xbf, 0x24, - 0x94, 0x0f, 0x8a, 0x11, 0xa1, 0x3a, 0xdc, 0x47, 0xf7, 0x6c, - 0x26, 0xbd, 0x0d, 0x96, 0x70, 0xeb, 0x5b, 0xc0, 0xcf, 0x54, - 0xe4, 0x7f, 0x99, 0x02, 0xb2, 0x29, 0x63, 0xf8, 0x48, 0xd3, - 0x35, 0xae, 0x1e, 0x85, 0x09, 0x92, 0x22, 0xb9, 0x5f, 0xc4, - 0x74, 0xef, 0xa5, 0x3e, 0x8e, 0x15, 0xf3, 0x68, 0xd8, 0x43, - 0x4c, 0xd7, 0x67, 0xfc, 0x1a, 0x81, 0x31, 0xaa, 0xe0, 0x7b, - 0xcb, 0x50, 0xb6, 0x2d, 0x9d, 0x06, 0x83, 0x18, 0xa8, 0x33, - 0xd5, 0x4e, 0xfe, 0x65, 0x2f, 0xb4, 0x04, 0x9f, 0x79, 0xe2, - 0x52, 0xc9, 0xc6, 0x5d, 0xed, 0x76, 0x90, 0x0b, 0xbb, 0x20, - 0x6a, 0xf1, 0x41, 0xda, 0x3c, 0xa7, 0x17, 0x8c, 0x12, 0x89, - 0x39, 0xa2, 0x44, 0xdf, 0x6f, 0xf4, 0xbe, 0x25, 0x95, 0x0e, - 0xe8, 0x73, 0xc3, 0x58, 0x57, 0xcc, 0x7c, 0xe7, 0x01, 0x9a, - 0x2a, 0xb1, 0xfb, 0x60, 0xd0, 0x4b, 0xad, 0x36, 0x86, 0x1d, - 0x98, 0x03, 0xb3, 0x28, 0xce, 0x55, 0xe5, 0x7e, 0x34, 0xaf, - 0x1f, 0x84, 0x62, 0xf9, 0x49, 0xd2, 0xdd, 0x46, 0xf6, 0x6d, - 0x8b, 0x10, 0xa0, 0x3b, 0x71, 0xea, 0x5a, 0xc1, 0x27, 0xbc, - 0x0c, 0x97, 0x1b, 0x80, 0x30, 0xab, 0x4d, 0xd6, 0x66, 0xfd, - 0xb7, 0x2c, 0x9c, 0x07, 0xe1, 0x7a, 0xca, 0x51, 0x5e, 0xc5, - 0x75, 0xee, 0x08, 0x93, 0x23, 0xb8, 0xf2, 0x69, 0xd9, 0x42, - 0xa4, 0x3f, 0x8f, 0x14, 0x91, 0x0a, 0xba, 0x21, 0xc7, 0x5c, - 0xec, 0x77, 0x3d, 0xa6, 0x16, 0x8d, 0x6b, 0xf0, 0x40, 0xdb, - 0xd4, 0x4f, 0xff, 0x64, 0x82, 0x19, 0xa9, 0x32, 0x78, 0xe3, - 0x53, 0xc8, 0x2e, 0xb5, 0x05, 0x9e, 0x00, 0x9c, 0x25, 0xb9, - 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, - 0xfb, 0x67, 0x35, 0xa9, 0x10, 0x8c, 0x7f, 0xe3, 0x5a, 0xc6, - 0xa1, 0x3d, 0x84, 0x18, 0xeb, 0x77, 0xce, 0x52, 0x6a, 0xf6, - 0x4f, 0xd3, 0x20, 0xbc, 0x05, 0x99, 0xfe, 0x62, 0xdb, 0x47, - 0xb4, 0x28, 0x91, 0x0d, 0x5f, 0xc3, 0x7a, 0xe6, 0x15, 0x89, - 0x30, 0xac, 0xcb, 0x57, 0xee, 0x72, 0x81, 0x1d, 0xa4, 0x38, - 0xd4, 0x48, 0xf1, 0x6d, 0x9e, 0x02, 0xbb, 0x27, 0x40, 0xdc, - 0x65, 0xf9, 0x0a, 0x96, 0x2f, 0xb3, 0xe1, 0x7d, 0xc4, 0x58, - 0xab, 0x37, 0x8e, 0x12, 0x75, 0xe9, 0x50, 0xcc, 0x3f, 0xa3, - 0x1a, 0x86, 0xbe, 0x22, 0x9b, 0x07, 0xf4, 0x68, 0xd1, 0x4d, - 0x2a, 0xb6, 0x0f, 0x93, 0x60, 0xfc, 0x45, 0xd9, 0x8b, 0x17, - 0xae, 0x32, 0xc1, 0x5d, 0xe4, 0x78, 0x1f, 0x83, 0x3a, 0xa6, - 0x55, 0xc9, 0x70, 0xec, 0xb5, 0x29, 0x90, 0x0c, 0xff, 0x63, - 0xda, 0x46, 0x21, 0xbd, 0x04, 0x98, 0x6b, 0xf7, 0x4e, 0xd2, - 0x80, 0x1c, 0xa5, 0x39, 0xca, 0x56, 0xef, 0x73, 0x14, 0x88, - 0x31, 0xad, 0x5e, 0xc2, 0x7b, 0xe7, 0xdf, 0x43, 0xfa, 0x66, - 0x95, 0x09, 0xb0, 0x2c, 0x4b, 0xd7, 0x6e, 0xf2, 0x01, 0x9d, - 0x24, 0xb8, 0xea, 0x76, 0xcf, 0x53, 0xa0, 0x3c, 0x85, 0x19, - 0x7e, 0xe2, 0x5b, 0xc7, 0x34, 0xa8, 0x11, 0x8d, 0x61, 0xfd, - 0x44, 0xd8, 0x2b, 0xb7, 0x0e, 0x92, 0xf5, 0x69, 0xd0, 0x4c, - 0xbf, 0x23, 0x9a, 0x06, 0x54, 0xc8, 0x71, 0xed, 0x1e, 0x82, - 0x3b, 0xa7, 0xc0, 0x5c, 0xe5, 0x79, 0x8a, 0x16, 0xaf, 0x33, - 0x0b, 0x97, 0x2e, 0xb2, 0x41, 0xdd, 0x64, 0xf8, 0x9f, 0x03, - 0xba, 0x26, 0xd5, 0x49, 0xf0, 0x6c, 0x3e, 0xa2, 0x1b, 0x87, - 0x74, 0xe8, 0x51, 0xcd, 0xaa, 0x36, 0x8f, 0x13, 0xe0, 0x7c, - 0xc5, 0x59, 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, - 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68, 0x25, 0xb8, - 0x02, 0x9f, 0x6b, 0xf6, 0x4c, 0xd1, 0xb9, 0x24, 0x9e, 0x03, - 0xf7, 0x6a, 0xd0, 0x4d, 0x4a, 0xd7, 0x6d, 0xf0, 0x04, 0x99, - 0x23, 0xbe, 0xd6, 0x4b, 0xf1, 0x6c, 0x98, 0x05, 0xbf, 0x22, - 0x6f, 0xf2, 0x48, 0xd5, 0x21, 0xbc, 0x06, 0x9b, 0xf3, 0x6e, - 0xd4, 0x49, 0xbd, 0x20, 0x9a, 0x07, 0x94, 0x09, 0xb3, 0x2e, - 0xda, 0x47, 0xfd, 0x60, 0x08, 0x95, 0x2f, 0xb2, 0x46, 0xdb, - 0x61, 0xfc, 0xb1, 0x2c, 0x96, 0x0b, 0xff, 0x62, 0xd8, 0x45, - 0x2d, 0xb0, 0x0a, 0x97, 0x63, 0xfe, 0x44, 0xd9, 0xde, 0x43, - 0xf9, 0x64, 0x90, 0x0d, 0xb7, 0x2a, 0x42, 0xdf, 0x65, 0xf8, - 0x0c, 0x91, 0x2b, 0xb6, 0xfb, 0x66, 0xdc, 0x41, 0xb5, 0x28, - 0x92, 0x0f, 0x67, 0xfa, 0x40, 0xdd, 0x29, 0xb4, 0x0e, 0x93, - 0x35, 0xa8, 0x12, 0x8f, 0x7b, 0xe6, 0x5c, 0xc1, 0xa9, 0x34, - 0x8e, 0x13, 0xe7, 0x7a, 0xc0, 0x5d, 0x10, 0x8d, 0x37, 0xaa, - 0x5e, 0xc3, 0x79, 0xe4, 0x8c, 0x11, 0xab, 0x36, 0xc2, 0x5f, - 0xe5, 0x78, 0x7f, 0xe2, 0x58, 0xc5, 0x31, 0xac, 0x16, 0x8b, - 0xe3, 0x7e, 0xc4, 0x59, 0xad, 0x30, 0x8a, 0x17, 0x5a, 0xc7, - 0x7d, 0xe0, 0x14, 0x89, 0x33, 0xae, 0xc6, 0x5b, 0xe1, 0x7c, - 0x88, 0x15, 0xaf, 0x32, 0xa1, 0x3c, 0x86, 0x1b, 0xef, 0x72, - 0xc8, 0x55, 0x3d, 0xa0, 0x1a, 0x87, 0x73, 0xee, 0x54, 0xc9, - 0x84, 0x19, 0xa3, 0x3e, 0xca, 0x57, 0xed, 0x70, 0x18, 0x85, - 0x3f, 0xa2, 0x56, 0xcb, 0x71, 0xec, 0xeb, 0x76, 0xcc, 0x51, - 0xa5, 0x38, 0x82, 0x1f, 0x77, 0xea, 0x50, 0xcd, 0x39, 0xa4, - 0x1e, 0x83, 0xce, 0x53, 0xe9, 0x74, 0x80, 0x1d, 0xa7, 0x3a, - 0x52, 0xcf, 0x75, 0xe8, 0x1c, 0x81, 0x3b, 0xa6, 0x00, 0x9e, - 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, - 0xc6, 0x58, 0xe7, 0x79, 0x15, 0x8b, 0x34, 0xaa, 0x57, 0xc9, - 0x76, 0xe8, 0x91, 0x0f, 0xb0, 0x2e, 0xd3, 0x4d, 0xf2, 0x6c, - 0x2a, 0xb4, 0x0b, 0x95, 0x68, 0xf6, 0x49, 0xd7, 0xae, 0x30, - 0x8f, 0x11, 0xec, 0x72, 0xcd, 0x53, 0x3f, 0xa1, 0x1e, 0x80, - 0x7d, 0xe3, 0x5c, 0xc2, 0xbb, 0x25, 0x9a, 0x04, 0xf9, 0x67, - 0xd8, 0x46, 0x54, 0xca, 0x75, 0xeb, 0x16, 0x88, 0x37, 0xa9, - 0xd0, 0x4e, 0xf1, 0x6f, 0x92, 0x0c, 0xb3, 0x2d, 0x41, 0xdf, - 0x60, 0xfe, 0x03, 0x9d, 0x22, 0xbc, 0xc5, 0x5b, 0xe4, 0x7a, - 0x87, 0x19, 0xa6, 0x38, 0x7e, 0xe0, 0x5f, 0xc1, 0x3c, 0xa2, - 0x1d, 0x83, 0xfa, 0x64, 0xdb, 0x45, 0xb8, 0x26, 0x99, 0x07, - 0x6b, 0xf5, 0x4a, 0xd4, 0x29, 0xb7, 0x08, 0x96, 0xef, 0x71, - 0xce, 0x50, 0xad, 0x33, 0x8c, 0x12, 0xa8, 0x36, 0x89, 0x17, - 0xea, 0x74, 0xcb, 0x55, 0x2c, 0xb2, 0x0d, 0x93, 0x6e, 0xf0, - 0x4f, 0xd1, 0xbd, 0x23, 0x9c, 0x02, 0xff, 0x61, 0xde, 0x40, - 0x39, 0xa7, 0x18, 0x86, 0x7b, 0xe5, 0x5a, 0xc4, 0x82, 0x1c, - 0xa3, 0x3d, 0xc0, 0x5e, 0xe1, 0x7f, 0x06, 0x98, 0x27, 0xb9, - 0x44, 0xda, 0x65, 0xfb, 0x97, 0x09, 0xb6, 0x28, 0xd5, 0x4b, - 0xf4, 0x6a, 0x13, 0x8d, 0x32, 0xac, 0x51, 0xcf, 0x70, 0xee, - 0xfc, 0x62, 0xdd, 0x43, 0xbe, 0x20, 0x9f, 0x01, 0x78, 0xe6, - 0x59, 0xc7, 0x3a, 0xa4, 0x1b, 0x85, 0xe9, 0x77, 0xc8, 0x56, - 0xab, 0x35, 0x8a, 0x14, 0x6d, 0xf3, 0x4c, 0xd2, 0x2f, 0xb1, - 0x0e, 0x90, 0xd6, 0x48, 0xf7, 0x69, 0x94, 0x0a, 0xb5, 0x2b, - 0x52, 0xcc, 0x73, 0xed, 0x10, 0x8e, 0x31, 0xaf, 0xc3, 0x5d, - 0xe2, 0x7c, 0x81, 0x1f, 0xa0, 0x3e, 0x47, 0xd9, 0x66, 0xf8, - 0x05, 0x9b, 0x24, 0xba, 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, - 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76, - 0x05, 0x9a, 0x26, 0xb9, 0x43, 0xdc, 0x60, 0xff, 0x89, 0x16, - 0xaa, 0x35, 0xcf, 0x50, 0xec, 0x73, 0x0a, 0x95, 0x29, 0xb6, - 0x4c, 0xd3, 0x6f, 0xf0, 0x86, 0x19, 0xa5, 0x3a, 0xc0, 0x5f, - 0xe3, 0x7c, 0x0f, 0x90, 0x2c, 0xb3, 0x49, 0xd6, 0x6a, 0xf5, - 0x83, 0x1c, 0xa0, 0x3f, 0xc5, 0x5a, 0xe6, 0x79, 0x14, 0x8b, - 0x37, 0xa8, 0x52, 0xcd, 0x71, 0xee, 0x98, 0x07, 0xbb, 0x24, - 0xde, 0x41, 0xfd, 0x62, 0x11, 0x8e, 0x32, 0xad, 0x57, 0xc8, - 0x74, 0xeb, 0x9d, 0x02, 0xbe, 0x21, 0xdb, 0x44, 0xf8, 0x67, - 0x1e, 0x81, 0x3d, 0xa2, 0x58, 0xc7, 0x7b, 0xe4, 0x92, 0x0d, - 0xb1, 0x2e, 0xd4, 0x4b, 0xf7, 0x68, 0x1b, 0x84, 0x38, 0xa7, - 0x5d, 0xc2, 0x7e, 0xe1, 0x97, 0x08, 0xb4, 0x2b, 0xd1, 0x4e, - 0xf2, 0x6d, 0x28, 0xb7, 0x0b, 0x94, 0x6e, 0xf1, 0x4d, 0xd2, - 0xa4, 0x3b, 0x87, 0x18, 0xe2, 0x7d, 0xc1, 0x5e, 0x2d, 0xb2, - 0x0e, 0x91, 0x6b, 0xf4, 0x48, 0xd7, 0xa1, 0x3e, 0x82, 0x1d, - 0xe7, 0x78, 0xc4, 0x5b, 0x22, 0xbd, 0x01, 0x9e, 0x64, 0xfb, - 0x47, 0xd8, 0xae, 0x31, 0x8d, 0x12, 0xe8, 0x77, 0xcb, 0x54, - 0x27, 0xb8, 0x04, 0x9b, 0x61, 0xfe, 0x42, 0xdd, 0xab, 0x34, - 0x88, 0x17, 0xed, 0x72, 0xce, 0x51, 0x3c, 0xa3, 0x1f, 0x80, - 0x7a, 0xe5, 0x59, 0xc6, 0xb0, 0x2f, 0x93, 0x0c, 0xf6, 0x69, - 0xd5, 0x4a, 0x39, 0xa6, 0x1a, 0x85, 0x7f, 0xe0, 0x5c, 0xc3, - 0xb5, 0x2a, 0x96, 0x09, 0xf3, 0x6c, 0xd0, 0x4f, 0x36, 0xa9, - 0x15, 0x8a, 0x70, 0xef, 0x53, 0xcc, 0xba, 0x25, 0x99, 0x06, - 0xfc, 0x63, 0xdf, 0x40, 0x33, 0xac, 0x10, 0x8f, 0x75, 0xea, - 0x56, 0xc9, 0xbf, 0x20, 0x9c, 0x03, 0xf9, 0x66, 0xda, 0x45, - 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, - 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e, 0xd2, 0x72, 0x8f, 0x2f, - 0x68, 0xc8, 0x35, 0x95, 0xbb, 0x1b, 0xe6, 0x46, 0x01, 0xa1, - 0x5c, 0xfc, 0xb9, 0x19, 0xe4, 0x44, 0x03, 0xa3, 0x5e, 0xfe, - 0xd0, 0x70, 0x8d, 0x2d, 0x6a, 0xca, 0x37, 0x97, 0x6b, 0xcb, - 0x36, 0x96, 0xd1, 0x71, 0x8c, 0x2c, 0x02, 0xa2, 0x5f, 0xff, - 0xb8, 0x18, 0xe5, 0x45, 0x6f, 0xcf, 0x32, 0x92, 0xd5, 0x75, - 0x88, 0x28, 0x06, 0xa6, 0x5b, 0xfb, 0xbc, 0x1c, 0xe1, 0x41, - 0xbd, 0x1d, 0xe0, 0x40, 0x07, 0xa7, 0x5a, 0xfa, 0xd4, 0x74, - 0x89, 0x29, 0x6e, 0xce, 0x33, 0x93, 0xd6, 0x76, 0x8b, 0x2b, - 0x6c, 0xcc, 0x31, 0x91, 0xbf, 0x1f, 0xe2, 0x42, 0x05, 0xa5, - 0x58, 0xf8, 0x04, 0xa4, 0x59, 0xf9, 0xbe, 0x1e, 0xe3, 0x43, - 0x6d, 0xcd, 0x30, 0x90, 0xd7, 0x77, 0x8a, 0x2a, 0xde, 0x7e, - 0x83, 0x23, 0x64, 0xc4, 0x39, 0x99, 0xb7, 0x17, 0xea, 0x4a, - 0x0d, 0xad, 0x50, 0xf0, 0x0c, 0xac, 0x51, 0xf1, 0xb6, 0x16, - 0xeb, 0x4b, 0x65, 0xc5, 0x38, 0x98, 0xdf, 0x7f, 0x82, 0x22, - 0x67, 0xc7, 0x3a, 0x9a, 0xdd, 0x7d, 0x80, 0x20, 0x0e, 0xae, - 0x53, 0xf3, 0xb4, 0x14, 0xe9, 0x49, 0xb5, 0x15, 0xe8, 0x48, - 0x0f, 0xaf, 0x52, 0xf2, 0xdc, 0x7c, 0x81, 0x21, 0x66, 0xc6, - 0x3b, 0x9b, 0xb1, 0x11, 0xec, 0x4c, 0x0b, 0xab, 0x56, 0xf6, - 0xd8, 0x78, 0x85, 0x25, 0x62, 0xc2, 0x3f, 0x9f, 0x63, 0xc3, - 0x3e, 0x9e, 0xd9, 0x79, 0x84, 0x24, 0x0a, 0xaa, 0x57, 0xf7, - 0xb0, 0x10, 0xed, 0x4d, 0x08, 0xa8, 0x55, 0xf5, 0xb2, 0x12, - 0xef, 0x4f, 0x61, 0xc1, 0x3c, 0x9c, 0xdb, 0x7b, 0x86, 0x26, - 0xda, 0x7a, 0x87, 0x27, 0x60, 0xc0, 0x3d, 0x9d, 0xb3, 0x13, - 0xee, 0x4e, 0x09, 0xa9, 0x54, 0xf4, 0x00, 0xa1, 0x5f, 0xfe, - 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, - 0x80, 0x21, 0xc2, 0x63, 0x9d, 0x3c, 0x7c, 0xdd, 0x23, 0x82, - 0xa3, 0x02, 0xfc, 0x5d, 0x1d, 0xbc, 0x42, 0xe3, 0x99, 0x38, - 0xc6, 0x67, 0x27, 0x86, 0x78, 0xd9, 0xf8, 0x59, 0xa7, 0x06, - 0x46, 0xe7, 0x19, 0xb8, 0x5b, 0xfa, 0x04, 0xa5, 0xe5, 0x44, - 0xba, 0x1b, 0x3a, 0x9b, 0x65, 0xc4, 0x84, 0x25, 0xdb, 0x7a, - 0x2f, 0x8e, 0x70, 0xd1, 0x91, 0x30, 0xce, 0x6f, 0x4e, 0xef, - 0x11, 0xb0, 0xf0, 0x51, 0xaf, 0x0e, 0xed, 0x4c, 0xb2, 0x13, - 0x53, 0xf2, 0x0c, 0xad, 0x8c, 0x2d, 0xd3, 0x72, 0x32, 0x93, - 0x6d, 0xcc, 0xb6, 0x17, 0xe9, 0x48, 0x08, 0xa9, 0x57, 0xf6, - 0xd7, 0x76, 0x88, 0x29, 0x69, 0xc8, 0x36, 0x97, 0x74, 0xd5, - 0x2b, 0x8a, 0xca, 0x6b, 0x95, 0x34, 0x15, 0xb4, 0x4a, 0xeb, - 0xab, 0x0a, 0xf4, 0x55, 0x5e, 0xff, 0x01, 0xa0, 0xe0, 0x41, - 0xbf, 0x1e, 0x3f, 0x9e, 0x60, 0xc1, 0x81, 0x20, 0xde, 0x7f, - 0x9c, 0x3d, 0xc3, 0x62, 0x22, 0x83, 0x7d, 0xdc, 0xfd, 0x5c, - 0xa2, 0x03, 0x43, 0xe2, 0x1c, 0xbd, 0xc7, 0x66, 0x98, 0x39, - 0x79, 0xd8, 0x26, 0x87, 0xa6, 0x07, 0xf9, 0x58, 0x18, 0xb9, - 0x47, 0xe6, 0x05, 0xa4, 0x5a, 0xfb, 0xbb, 0x1a, 0xe4, 0x45, - 0x64, 0xc5, 0x3b, 0x9a, 0xda, 0x7b, 0x85, 0x24, 0x71, 0xd0, - 0x2e, 0x8f, 0xcf, 0x6e, 0x90, 0x31, 0x10, 0xb1, 0x4f, 0xee, - 0xae, 0x0f, 0xf1, 0x50, 0xb3, 0x12, 0xec, 0x4d, 0x0d, 0xac, - 0x52, 0xf3, 0xd2, 0x73, 0x8d, 0x2c, 0x6c, 0xcd, 0x33, 0x92, - 0xe8, 0x49, 0xb7, 0x16, 0x56, 0xf7, 0x09, 0xa8, 0x89, 0x28, - 0xd6, 0x77, 0x37, 0x96, 0x68, 0xc9, 0x2a, 0x8b, 0x75, 0xd4, - 0x94, 0x35, 0xcb, 0x6a, 0x4b, 0xea, 0x14, 0xb5, 0xf5, 0x54, - 0xaa, 0x0b, 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, - 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30, 0xf2, 0x50, - 0xab, 0x09, 0x40, 0xe2, 0x19, 0xbb, 0x8b, 0x29, 0xd2, 0x70, - 0x39, 0x9b, 0x60, 0xc2, 0xf9, 0x5b, 0xa0, 0x02, 0x4b, 0xe9, - 0x12, 0xb0, 0x80, 0x22, 0xd9, 0x7b, 0x32, 0x90, 0x6b, 0xc9, - 0x0b, 0xa9, 0x52, 0xf0, 0xb9, 0x1b, 0xe0, 0x42, 0x72, 0xd0, - 0x2b, 0x89, 0xc0, 0x62, 0x99, 0x3b, 0xef, 0x4d, 0xb6, 0x14, - 0x5d, 0xff, 0x04, 0xa6, 0x96, 0x34, 0xcf, 0x6d, 0x24, 0x86, - 0x7d, 0xdf, 0x1d, 0xbf, 0x44, 0xe6, 0xaf, 0x0d, 0xf6, 0x54, - 0x64, 0xc6, 0x3d, 0x9f, 0xd6, 0x74, 0x8f, 0x2d, 0x16, 0xb4, - 0x4f, 0xed, 0xa4, 0x06, 0xfd, 0x5f, 0x6f, 0xcd, 0x36, 0x94, - 0xdd, 0x7f, 0x84, 0x26, 0xe4, 0x46, 0xbd, 0x1f, 0x56, 0xf4, - 0x0f, 0xad, 0x9d, 0x3f, 0xc4, 0x66, 0x2f, 0x8d, 0x76, 0xd4, - 0xc3, 0x61, 0x9a, 0x38, 0x71, 0xd3, 0x28, 0x8a, 0xba, 0x18, - 0xe3, 0x41, 0x08, 0xaa, 0x51, 0xf3, 0x31, 0x93, 0x68, 0xca, - 0x83, 0x21, 0xda, 0x78, 0x48, 0xea, 0x11, 0xb3, 0xfa, 0x58, - 0xa3, 0x01, 0x3a, 0x98, 0x63, 0xc1, 0x88, 0x2a, 0xd1, 0x73, - 0x43, 0xe1, 0x1a, 0xb8, 0xf1, 0x53, 0xa8, 0x0a, 0xc8, 0x6a, - 0x91, 0x33, 0x7a, 0xd8, 0x23, 0x81, 0xb1, 0x13, 0xe8, 0x4a, - 0x03, 0xa1, 0x5a, 0xf8, 0x2c, 0x8e, 0x75, 0xd7, 0x9e, 0x3c, - 0xc7, 0x65, 0x55, 0xf7, 0x0c, 0xae, 0xe7, 0x45, 0xbe, 0x1c, - 0xde, 0x7c, 0x87, 0x25, 0x6c, 0xce, 0x35, 0x97, 0xa7, 0x05, - 0xfe, 0x5c, 0x15, 0xb7, 0x4c, 0xee, 0xd5, 0x77, 0x8c, 0x2e, - 0x67, 0xc5, 0x3e, 0x9c, 0xac, 0x0e, 0xf5, 0x57, 0x1e, 0xbc, - 0x47, 0xe5, 0x27, 0x85, 0x7e, 0xdc, 0x95, 0x37, 0xcc, 0x6e, - 0x5e, 0xfc, 0x07, 0xa5, 0xec, 0x4e, 0xb5, 0x17, 0x00, 0xa3, - 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, - 0xc7, 0x64, 0x9c, 0x3f, 0xe2, 0x41, 0xb9, 0x1a, 0x54, 0xf7, - 0x0f, 0xac, 0x93, 0x30, 0xc8, 0x6b, 0x25, 0x86, 0x7e, 0xdd, - 0xd9, 0x7a, 0x82, 0x21, 0x6f, 0xcc, 0x34, 0x97, 0xa8, 0x0b, - 0xf3, 0x50, 0x1e, 0xbd, 0x45, 0xe6, 0x3b, 0x98, 0x60, 0xc3, - 0x8d, 0x2e, 0xd6, 0x75, 0x4a, 0xe9, 0x11, 0xb2, 0xfc, 0x5f, - 0xa7, 0x04, 0xaf, 0x0c, 0xf4, 0x57, 0x19, 0xba, 0x42, 0xe1, - 0xde, 0x7d, 0x85, 0x26, 0x68, 0xcb, 0x33, 0x90, 0x4d, 0xee, - 0x16, 0xb5, 0xfb, 0x58, 0xa0, 0x03, 0x3c, 0x9f, 0x67, 0xc4, - 0x8a, 0x29, 0xd1, 0x72, 0x76, 0xd5, 0x2d, 0x8e, 0xc0, 0x63, - 0x9b, 0x38, 0x07, 0xa4, 0x5c, 0xff, 0xb1, 0x12, 0xea, 0x49, - 0x94, 0x37, 0xcf, 0x6c, 0x22, 0x81, 0x79, 0xda, 0xe5, 0x46, - 0xbe, 0x1d, 0x53, 0xf0, 0x08, 0xab, 0x43, 0xe0, 0x18, 0xbb, - 0xf5, 0x56, 0xae, 0x0d, 0x32, 0x91, 0x69, 0xca, 0x84, 0x27, - 0xdf, 0x7c, 0xa1, 0x02, 0xfa, 0x59, 0x17, 0xb4, 0x4c, 0xef, - 0xd0, 0x73, 0x8b, 0x28, 0x66, 0xc5, 0x3d, 0x9e, 0x9a, 0x39, - 0xc1, 0x62, 0x2c, 0x8f, 0x77, 0xd4, 0xeb, 0x48, 0xb0, 0x13, - 0x5d, 0xfe, 0x06, 0xa5, 0x78, 0xdb, 0x23, 0x80, 0xce, 0x6d, - 0x95, 0x36, 0x09, 0xaa, 0x52, 0xf1, 0xbf, 0x1c, 0xe4, 0x47, - 0xec, 0x4f, 0xb7, 0x14, 0x5a, 0xf9, 0x01, 0xa2, 0x9d, 0x3e, - 0xc6, 0x65, 0x2b, 0x88, 0x70, 0xd3, 0x0e, 0xad, 0x55, 0xf6, - 0xb8, 0x1b, 0xe3, 0x40, 0x7f, 0xdc, 0x24, 0x87, 0xc9, 0x6a, - 0x92, 0x31, 0x35, 0x96, 0x6e, 0xcd, 0x83, 0x20, 0xd8, 0x7b, - 0x44, 0xe7, 0x1f, 0xbc, 0xf2, 0x51, 0xa9, 0x0a, 0xd7, 0x74, - 0x8c, 0x2f, 0x61, 0xc2, 0x3a, 0x99, 0xa6, 0x05, 0xfd, 0x5e, - 0x10, 0xb3, 0x4b, 0xe8, 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, - 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12, - 0x92, 0x36, 0xc7, 0x63, 0x38, 0x9c, 0x6d, 0xc9, 0xdb, 0x7f, - 0x8e, 0x2a, 0x71, 0xd5, 0x24, 0x80, 0x39, 0x9d, 0x6c, 0xc8, - 0x93, 0x37, 0xc6, 0x62, 0x70, 0xd4, 0x25, 0x81, 0xda, 0x7e, - 0x8f, 0x2b, 0xab, 0x0f, 0xfe, 0x5a, 0x01, 0xa5, 0x54, 0xf0, - 0xe2, 0x46, 0xb7, 0x13, 0x48, 0xec, 0x1d, 0xb9, 0x72, 0xd6, - 0x27, 0x83, 0xd8, 0x7c, 0x8d, 0x29, 0x3b, 0x9f, 0x6e, 0xca, - 0x91, 0x35, 0xc4, 0x60, 0xe0, 0x44, 0xb5, 0x11, 0x4a, 0xee, - 0x1f, 0xbb, 0xa9, 0x0d, 0xfc, 0x58, 0x03, 0xa7, 0x56, 0xf2, - 0x4b, 0xef, 0x1e, 0xba, 0xe1, 0x45, 0xb4, 0x10, 0x02, 0xa6, - 0x57, 0xf3, 0xa8, 0x0c, 0xfd, 0x59, 0xd9, 0x7d, 0x8c, 0x28, - 0x73, 0xd7, 0x26, 0x82, 0x90, 0x34, 0xc5, 0x61, 0x3a, 0x9e, - 0x6f, 0xcb, 0xe4, 0x40, 0xb1, 0x15, 0x4e, 0xea, 0x1b, 0xbf, - 0xad, 0x09, 0xf8, 0x5c, 0x07, 0xa3, 0x52, 0xf6, 0x76, 0xd2, - 0x23, 0x87, 0xdc, 0x78, 0x89, 0x2d, 0x3f, 0x9b, 0x6a, 0xce, - 0x95, 0x31, 0xc0, 0x64, 0xdd, 0x79, 0x88, 0x2c, 0x77, 0xd3, - 0x22, 0x86, 0x94, 0x30, 0xc1, 0x65, 0x3e, 0x9a, 0x6b, 0xcf, - 0x4f, 0xeb, 0x1a, 0xbe, 0xe5, 0x41, 0xb0, 0x14, 0x06, 0xa2, - 0x53, 0xf7, 0xac, 0x08, 0xf9, 0x5d, 0x96, 0x32, 0xc3, 0x67, - 0x3c, 0x98, 0x69, 0xcd, 0xdf, 0x7b, 0x8a, 0x2e, 0x75, 0xd1, - 0x20, 0x84, 0x04, 0xa0, 0x51, 0xf5, 0xae, 0x0a, 0xfb, 0x5f, - 0x4d, 0xe9, 0x18, 0xbc, 0xe7, 0x43, 0xb2, 0x16, 0xaf, 0x0b, - 0xfa, 0x5e, 0x05, 0xa1, 0x50, 0xf4, 0xe6, 0x42, 0xb3, 0x17, - 0x4c, 0xe8, 0x19, 0xbd, 0x3d, 0x99, 0x68, 0xcc, 0x97, 0x33, - 0xc2, 0x66, 0x74, 0xd0, 0x21, 0x85, 0xde, 0x7a, 0x8b, 0x2f, - 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, - 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d, 0x82, 0x27, 0xd5, 0x70, - 0x2c, 0x89, 0x7b, 0xde, 0xc3, 0x66, 0x94, 0x31, 0x6d, 0xc8, - 0x3a, 0x9f, 0x19, 0xbc, 0x4e, 0xeb, 0xb7, 0x12, 0xe0, 0x45, - 0x58, 0xfd, 0x0f, 0xaa, 0xf6, 0x53, 0xa1, 0x04, 0x9b, 0x3e, - 0xcc, 0x69, 0x35, 0x90, 0x62, 0xc7, 0xda, 0x7f, 0x8d, 0x28, - 0x74, 0xd1, 0x23, 0x86, 0x32, 0x97, 0x65, 0xc0, 0x9c, 0x39, - 0xcb, 0x6e, 0x73, 0xd6, 0x24, 0x81, 0xdd, 0x78, 0x8a, 0x2f, - 0xb0, 0x15, 0xe7, 0x42, 0x1e, 0xbb, 0x49, 0xec, 0xf1, 0x54, - 0xa6, 0x03, 0x5f, 0xfa, 0x08, 0xad, 0x2b, 0x8e, 0x7c, 0xd9, - 0x85, 0x20, 0xd2, 0x77, 0x6a, 0xcf, 0x3d, 0x98, 0xc4, 0x61, - 0x93, 0x36, 0xa9, 0x0c, 0xfe, 0x5b, 0x07, 0xa2, 0x50, 0xf5, - 0xe8, 0x4d, 0xbf, 0x1a, 0x46, 0xe3, 0x11, 0xb4, 0x64, 0xc1, - 0x33, 0x96, 0xca, 0x6f, 0x9d, 0x38, 0x25, 0x80, 0x72, 0xd7, - 0x8b, 0x2e, 0xdc, 0x79, 0xe6, 0x43, 0xb1, 0x14, 0x48, 0xed, - 0x1f, 0xba, 0xa7, 0x02, 0xf0, 0x55, 0x09, 0xac, 0x5e, 0xfb, - 0x7d, 0xd8, 0x2a, 0x8f, 0xd3, 0x76, 0x84, 0x21, 0x3c, 0x99, - 0x6b, 0xce, 0x92, 0x37, 0xc5, 0x60, 0xff, 0x5a, 0xa8, 0x0d, - 0x51, 0xf4, 0x06, 0xa3, 0xbe, 0x1b, 0xe9, 0x4c, 0x10, 0xb5, - 0x47, 0xe2, 0x56, 0xf3, 0x01, 0xa4, 0xf8, 0x5d, 0xaf, 0x0a, - 0x17, 0xb2, 0x40, 0xe5, 0xb9, 0x1c, 0xee, 0x4b, 0xd4, 0x71, - 0x83, 0x26, 0x7a, 0xdf, 0x2d, 0x88, 0x95, 0x30, 0xc2, 0x67, - 0x3b, 0x9e, 0x6c, 0xc9, 0x4f, 0xea, 0x18, 0xbd, 0xe1, 0x44, - 0xb6, 0x13, 0x0e, 0xab, 0x59, 0xfc, 0xa0, 0x05, 0xf7, 0x52, - 0xcd, 0x68, 0x9a, 0x3f, 0x63, 0xc6, 0x34, 0x91, 0x8c, 0x29, - 0xdb, 0x7e, 0x22, 0x87, 0x75, 0xd0, 0x00, 0xa6, 0x51, 0xf7, - 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, - 0xaa, 0x0c, 0xb2, 0x14, 0xe3, 0x45, 0x10, 0xb6, 0x41, 0xe7, - 0xeb, 0x4d, 0xba, 0x1c, 0x49, 0xef, 0x18, 0xbe, 0x79, 0xdf, - 0x28, 0x8e, 0xdb, 0x7d, 0x8a, 0x2c, 0x20, 0x86, 0x71, 0xd7, - 0x82, 0x24, 0xd3, 0x75, 0xcb, 0x6d, 0x9a, 0x3c, 0x69, 0xcf, - 0x38, 0x9e, 0x92, 0x34, 0xc3, 0x65, 0x30, 0x96, 0x61, 0xc7, - 0xf2, 0x54, 0xa3, 0x05, 0x50, 0xf6, 0x01, 0xa7, 0xab, 0x0d, - 0xfa, 0x5c, 0x09, 0xaf, 0x58, 0xfe, 0x40, 0xe6, 0x11, 0xb7, - 0xe2, 0x44, 0xb3, 0x15, 0x19, 0xbf, 0x48, 0xee, 0xbb, 0x1d, - 0xea, 0x4c, 0x8b, 0x2d, 0xda, 0x7c, 0x29, 0x8f, 0x78, 0xde, - 0xd2, 0x74, 0x83, 0x25, 0x70, 0xd6, 0x21, 0x87, 0x39, 0x9f, - 0x68, 0xce, 0x9b, 0x3d, 0xca, 0x6c, 0x60, 0xc6, 0x31, 0x97, - 0xc2, 0x64, 0x93, 0x35, 0xf9, 0x5f, 0xa8, 0x0e, 0x5b, 0xfd, - 0x0a, 0xac, 0xa0, 0x06, 0xf1, 0x57, 0x02, 0xa4, 0x53, 0xf5, - 0x4b, 0xed, 0x1a, 0xbc, 0xe9, 0x4f, 0xb8, 0x1e, 0x12, 0xb4, - 0x43, 0xe5, 0xb0, 0x16, 0xe1, 0x47, 0x80, 0x26, 0xd1, 0x77, - 0x22, 0x84, 0x73, 0xd5, 0xd9, 0x7f, 0x88, 0x2e, 0x7b, 0xdd, - 0x2a, 0x8c, 0x32, 0x94, 0x63, 0xc5, 0x90, 0x36, 0xc1, 0x67, - 0x6b, 0xcd, 0x3a, 0x9c, 0xc9, 0x6f, 0x98, 0x3e, 0x0b, 0xad, - 0x5a, 0xfc, 0xa9, 0x0f, 0xf8, 0x5e, 0x52, 0xf4, 0x03, 0xa5, - 0xf0, 0x56, 0xa1, 0x07, 0xb9, 0x1f, 0xe8, 0x4e, 0x1b, 0xbd, - 0x4a, 0xec, 0xe0, 0x46, 0xb1, 0x17, 0x42, 0xe4, 0x13, 0xb5, - 0x72, 0xd4, 0x23, 0x85, 0xd0, 0x76, 0x81, 0x27, 0x2b, 0x8d, - 0x7a, 0xdc, 0x89, 0x2f, 0xd8, 0x7e, 0xc0, 0x66, 0x91, 0x37, - 0x62, 0xc4, 0x33, 0x95, 0x99, 0x3f, 0xc8, 0x6e, 0x3b, 0x9d, - 0x6a, 0xcc, 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, - 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03, 0xa2, 0x05, - 0xf1, 0x56, 0x04, 0xa3, 0x57, 0xf0, 0xf3, 0x54, 0xa0, 0x07, - 0x55, 0xf2, 0x06, 0xa1, 0x59, 0xfe, 0x0a, 0xad, 0xff, 0x58, - 0xac, 0x0b, 0x08, 0xaf, 0x5b, 0xfc, 0xae, 0x09, 0xfd, 0x5a, - 0xfb, 0x5c, 0xa8, 0x0f, 0x5d, 0xfa, 0x0e, 0xa9, 0xaa, 0x0d, - 0xf9, 0x5e, 0x0c, 0xab, 0x5f, 0xf8, 0xb2, 0x15, 0xe1, 0x46, - 0x14, 0xb3, 0x47, 0xe0, 0xe3, 0x44, 0xb0, 0x17, 0x45, 0xe2, - 0x16, 0xb1, 0x10, 0xb7, 0x43, 0xe4, 0xb6, 0x11, 0xe5, 0x42, - 0x41, 0xe6, 0x12, 0xb5, 0xe7, 0x40, 0xb4, 0x13, 0xeb, 0x4c, - 0xb8, 0x1f, 0x4d, 0xea, 0x1e, 0xb9, 0xba, 0x1d, 0xe9, 0x4e, - 0x1c, 0xbb, 0x4f, 0xe8, 0x49, 0xee, 0x1a, 0xbd, 0xef, 0x48, - 0xbc, 0x1b, 0x18, 0xbf, 0x4b, 0xec, 0xbe, 0x19, 0xed, 0x4a, - 0x79, 0xde, 0x2a, 0x8d, 0xdf, 0x78, 0x8c, 0x2b, 0x28, 0x8f, - 0x7b, 0xdc, 0x8e, 0x29, 0xdd, 0x7a, 0xdb, 0x7c, 0x88, 0x2f, - 0x7d, 0xda, 0x2e, 0x89, 0x8a, 0x2d, 0xd9, 0x7e, 0x2c, 0x8b, - 0x7f, 0xd8, 0x20, 0x87, 0x73, 0xd4, 0x86, 0x21, 0xd5, 0x72, - 0x71, 0xd6, 0x22, 0x85, 0xd7, 0x70, 0x84, 0x23, 0x82, 0x25, - 0xd1, 0x76, 0x24, 0x83, 0x77, 0xd0, 0xd3, 0x74, 0x80, 0x27, - 0x75, 0xd2, 0x26, 0x81, 0xcb, 0x6c, 0x98, 0x3f, 0x6d, 0xca, - 0x3e, 0x99, 0x9a, 0x3d, 0xc9, 0x6e, 0x3c, 0x9b, 0x6f, 0xc8, - 0x69, 0xce, 0x3a, 0x9d, 0xcf, 0x68, 0x9c, 0x3b, 0x38, 0x9f, - 0x6b, 0xcc, 0x9e, 0x39, 0xcd, 0x6a, 0x92, 0x35, 0xc1, 0x66, - 0x34, 0x93, 0x67, 0xc0, 0xc3, 0x64, 0x90, 0x37, 0x65, 0xc2, - 0x36, 0x91, 0x30, 0x97, 0x63, 0xc4, 0x96, 0x31, 0xc5, 0x62, - 0x61, 0xc6, 0x32, 0x95, 0xc7, 0x60, 0x94, 0x33, 0x00, 0xa8, - 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, - 0xb3, 0x1b, 0xfe, 0x56, 0x52, 0xfa, 0x1f, 0xb7, 0xc8, 0x60, - 0x85, 0x2d, 0x7b, 0xd3, 0x36, 0x9e, 0xe1, 0x49, 0xac, 0x04, - 0xa4, 0x0c, 0xe9, 0x41, 0x3e, 0x96, 0x73, 0xdb, 0x8d, 0x25, - 0xc0, 0x68, 0x17, 0xbf, 0x5a, 0xf2, 0xf6, 0x5e, 0xbb, 0x13, - 0x6c, 0xc4, 0x21, 0x89, 0xdf, 0x77, 0x92, 0x3a, 0x45, 0xed, - 0x08, 0xa0, 0x55, 0xfd, 0x18, 0xb0, 0xcf, 0x67, 0x82, 0x2a, - 0x7c, 0xd4, 0x31, 0x99, 0xe6, 0x4e, 0xab, 0x03, 0x07, 0xaf, - 0x4a, 0xe2, 0x9d, 0x35, 0xd0, 0x78, 0x2e, 0x86, 0x63, 0xcb, - 0xb4, 0x1c, 0xf9, 0x51, 0xf1, 0x59, 0xbc, 0x14, 0x6b, 0xc3, - 0x26, 0x8e, 0xd8, 0x70, 0x95, 0x3d, 0x42, 0xea, 0x0f, 0xa7, - 0xa3, 0x0b, 0xee, 0x46, 0x39, 0x91, 0x74, 0xdc, 0x8a, 0x22, - 0xc7, 0x6f, 0x10, 0xb8, 0x5d, 0xf5, 0xaa, 0x02, 0xe7, 0x4f, - 0x30, 0x98, 0x7d, 0xd5, 0x83, 0x2b, 0xce, 0x66, 0x19, 0xb1, - 0x54, 0xfc, 0xf8, 0x50, 0xb5, 0x1d, 0x62, 0xca, 0x2f, 0x87, - 0xd1, 0x79, 0x9c, 0x34, 0x4b, 0xe3, 0x06, 0xae, 0x0e, 0xa6, - 0x43, 0xeb, 0x94, 0x3c, 0xd9, 0x71, 0x27, 0x8f, 0x6a, 0xc2, - 0xbd, 0x15, 0xf0, 0x58, 0x5c, 0xf4, 0x11, 0xb9, 0xc6, 0x6e, - 0x8b, 0x23, 0x75, 0xdd, 0x38, 0x90, 0xef, 0x47, 0xa2, 0x0a, - 0xff, 0x57, 0xb2, 0x1a, 0x65, 0xcd, 0x28, 0x80, 0xd6, 0x7e, - 0x9b, 0x33, 0x4c, 0xe4, 0x01, 0xa9, 0xad, 0x05, 0xe0, 0x48, - 0x37, 0x9f, 0x7a, 0xd2, 0x84, 0x2c, 0xc9, 0x61, 0x1e, 0xb6, - 0x53, 0xfb, 0x5b, 0xf3, 0x16, 0xbe, 0xc1, 0x69, 0x8c, 0x24, - 0x72, 0xda, 0x3f, 0x97, 0xe8, 0x40, 0xa5, 0x0d, 0x09, 0xa1, - 0x44, 0xec, 0x93, 0x3b, 0xde, 0x76, 0x20, 0x88, 0x6d, 0xc5, - 0xba, 0x12, 0xf7, 0x5f, 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, - 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59, - 0x42, 0xeb, 0x0d, 0xa4, 0xdc, 0x75, 0x93, 0x3a, 0x63, 0xca, - 0x2c, 0x85, 0xfd, 0x54, 0xb2, 0x1b, 0x84, 0x2d, 0xcb, 0x62, - 0x1a, 0xb3, 0x55, 0xfc, 0xa5, 0x0c, 0xea, 0x43, 0x3b, 0x92, - 0x74, 0xdd, 0xc6, 0x6f, 0x89, 0x20, 0x58, 0xf1, 0x17, 0xbe, - 0xe7, 0x4e, 0xa8, 0x01, 0x79, 0xd0, 0x36, 0x9f, 0x15, 0xbc, - 0x5a, 0xf3, 0x8b, 0x22, 0xc4, 0x6d, 0x34, 0x9d, 0x7b, 0xd2, - 0xaa, 0x03, 0xe5, 0x4c, 0x57, 0xfe, 0x18, 0xb1, 0xc9, 0x60, - 0x86, 0x2f, 0x76, 0xdf, 0x39, 0x90, 0xe8, 0x41, 0xa7, 0x0e, - 0x91, 0x38, 0xde, 0x77, 0x0f, 0xa6, 0x40, 0xe9, 0xb0, 0x19, - 0xff, 0x56, 0x2e, 0x87, 0x61, 0xc8, 0xd3, 0x7a, 0x9c, 0x35, - 0x4d, 0xe4, 0x02, 0xab, 0xf2, 0x5b, 0xbd, 0x14, 0x6c, 0xc5, - 0x23, 0x8a, 0x2a, 0x83, 0x65, 0xcc, 0xb4, 0x1d, 0xfb, 0x52, - 0x0b, 0xa2, 0x44, 0xed, 0x95, 0x3c, 0xda, 0x73, 0x68, 0xc1, - 0x27, 0x8e, 0xf6, 0x5f, 0xb9, 0x10, 0x49, 0xe0, 0x06, 0xaf, - 0xd7, 0x7e, 0x98, 0x31, 0xae, 0x07, 0xe1, 0x48, 0x30, 0x99, - 0x7f, 0xd6, 0x8f, 0x26, 0xc0, 0x69, 0x11, 0xb8, 0x5e, 0xf7, - 0xec, 0x45, 0xa3, 0x0a, 0x72, 0xdb, 0x3d, 0x94, 0xcd, 0x64, - 0x82, 0x2b, 0x53, 0xfa, 0x1c, 0xb5, 0x3f, 0x96, 0x70, 0xd9, - 0xa1, 0x08, 0xee, 0x47, 0x1e, 0xb7, 0x51, 0xf8, 0x80, 0x29, - 0xcf, 0x66, 0x7d, 0xd4, 0x32, 0x9b, 0xe3, 0x4a, 0xac, 0x05, - 0x5c, 0xf5, 0x13, 0xba, 0xc2, 0x6b, 0x8d, 0x24, 0xbb, 0x12, - 0xf4, 0x5d, 0x25, 0x8c, 0x6a, 0xc3, 0x9a, 0x33, 0xd5, 0x7c, - 0x04, 0xad, 0x4b, 0xe2, 0xf9, 0x50, 0xb6, 0x1f, 0x67, 0xce, - 0x28, 0x81, 0xd8, 0x71, 0x97, 0x3e, 0x46, 0xef, 0x09, 0xa0, - 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, - 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48, 0x72, 0xd8, 0x3b, 0x91, - 0xe0, 0x4a, 0xa9, 0x03, 0x4b, 0xe1, 0x02, 0xa8, 0xd9, 0x73, - 0x90, 0x3a, 0xe4, 0x4e, 0xad, 0x07, 0x76, 0xdc, 0x3f, 0x95, - 0xdd, 0x77, 0x94, 0x3e, 0x4f, 0xe5, 0x06, 0xac, 0x96, 0x3c, - 0xdf, 0x75, 0x04, 0xae, 0x4d, 0xe7, 0xaf, 0x05, 0xe6, 0x4c, - 0x3d, 0x97, 0x74, 0xde, 0xd5, 0x7f, 0x9c, 0x36, 0x47, 0xed, - 0x0e, 0xa4, 0xec, 0x46, 0xa5, 0x0f, 0x7e, 0xd4, 0x37, 0x9d, - 0xa7, 0x0d, 0xee, 0x44, 0x35, 0x9f, 0x7c, 0xd6, 0x9e, 0x34, - 0xd7, 0x7d, 0x0c, 0xa6, 0x45, 0xef, 0x31, 0x9b, 0x78, 0xd2, - 0xa3, 0x09, 0xea, 0x40, 0x08, 0xa2, 0x41, 0xeb, 0x9a, 0x30, - 0xd3, 0x79, 0x43, 0xe9, 0x0a, 0xa0, 0xd1, 0x7b, 0x98, 0x32, - 0x7a, 0xd0, 0x33, 0x99, 0xe8, 0x42, 0xa1, 0x0b, 0xb7, 0x1d, - 0xfe, 0x54, 0x25, 0x8f, 0x6c, 0xc6, 0x8e, 0x24, 0xc7, 0x6d, - 0x1c, 0xb6, 0x55, 0xff, 0xc5, 0x6f, 0x8c, 0x26, 0x57, 0xfd, - 0x1e, 0xb4, 0xfc, 0x56, 0xb5, 0x1f, 0x6e, 0xc4, 0x27, 0x8d, - 0x53, 0xf9, 0x1a, 0xb0, 0xc1, 0x6b, 0x88, 0x22, 0x6a, 0xc0, - 0x23, 0x89, 0xf8, 0x52, 0xb1, 0x1b, 0x21, 0x8b, 0x68, 0xc2, - 0xb3, 0x19, 0xfa, 0x50, 0x18, 0xb2, 0x51, 0xfb, 0x8a, 0x20, - 0xc3, 0x69, 0x62, 0xc8, 0x2b, 0x81, 0xf0, 0x5a, 0xb9, 0x13, - 0x5b, 0xf1, 0x12, 0xb8, 0xc9, 0x63, 0x80, 0x2a, 0x10, 0xba, - 0x59, 0xf3, 0x82, 0x28, 0xcb, 0x61, 0x29, 0x83, 0x60, 0xca, - 0xbb, 0x11, 0xf2, 0x58, 0x86, 0x2c, 0xcf, 0x65, 0x14, 0xbe, - 0x5d, 0xf7, 0xbf, 0x15, 0xf6, 0x5c, 0x2d, 0x87, 0x64, 0xce, - 0xf4, 0x5e, 0xbd, 0x17, 0x66, 0xcc, 0x2f, 0x85, 0xcd, 0x67, - 0x84, 0x2e, 0x5f, 0xf5, 0x16, 0xbc, 0x00, 0xab, 0x4b, 0xe0, - 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, - 0xec, 0x47, 0x62, 0xc9, 0x29, 0x82, 0xf4, 0x5f, 0xbf, 0x14, - 0x53, 0xf8, 0x18, 0xb3, 0xc5, 0x6e, 0x8e, 0x25, 0xc4, 0x6f, - 0x8f, 0x24, 0x52, 0xf9, 0x19, 0xb2, 0xf5, 0x5e, 0xbe, 0x15, - 0x63, 0xc8, 0x28, 0x83, 0xa6, 0x0d, 0xed, 0x46, 0x30, 0x9b, - 0x7b, 0xd0, 0x97, 0x3c, 0xdc, 0x77, 0x01, 0xaa, 0x4a, 0xe1, - 0x95, 0x3e, 0xde, 0x75, 0x03, 0xa8, 0x48, 0xe3, 0xa4, 0x0f, - 0xef, 0x44, 0x32, 0x99, 0x79, 0xd2, 0xf7, 0x5c, 0xbc, 0x17, - 0x61, 0xca, 0x2a, 0x81, 0xc6, 0x6d, 0x8d, 0x26, 0x50, 0xfb, - 0x1b, 0xb0, 0x51, 0xfa, 0x1a, 0xb1, 0xc7, 0x6c, 0x8c, 0x27, - 0x60, 0xcb, 0x2b, 0x80, 0xf6, 0x5d, 0xbd, 0x16, 0x33, 0x98, - 0x78, 0xd3, 0xa5, 0x0e, 0xee, 0x45, 0x02, 0xa9, 0x49, 0xe2, - 0x94, 0x3f, 0xdf, 0x74, 0x37, 0x9c, 0x7c, 0xd7, 0xa1, 0x0a, - 0xea, 0x41, 0x06, 0xad, 0x4d, 0xe6, 0x90, 0x3b, 0xdb, 0x70, - 0x55, 0xfe, 0x1e, 0xb5, 0xc3, 0x68, 0x88, 0x23, 0x64, 0xcf, - 0x2f, 0x84, 0xf2, 0x59, 0xb9, 0x12, 0xf3, 0x58, 0xb8, 0x13, - 0x65, 0xce, 0x2e, 0x85, 0xc2, 0x69, 0x89, 0x22, 0x54, 0xff, - 0x1f, 0xb4, 0x91, 0x3a, 0xda, 0x71, 0x07, 0xac, 0x4c, 0xe7, - 0xa0, 0x0b, 0xeb, 0x40, 0x36, 0x9d, 0x7d, 0xd6, 0xa2, 0x09, - 0xe9, 0x42, 0x34, 0x9f, 0x7f, 0xd4, 0x93, 0x38, 0xd8, 0x73, - 0x05, 0xae, 0x4e, 0xe5, 0xc0, 0x6b, 0x8b, 0x20, 0x56, 0xfd, - 0x1d, 0xb6, 0xf1, 0x5a, 0xba, 0x11, 0x67, 0xcc, 0x2c, 0x87, - 0x66, 0xcd, 0x2d, 0x86, 0xf0, 0x5b, 0xbb, 0x10, 0x57, 0xfc, - 0x1c, 0xb7, 0xc1, 0x6a, 0x8a, 0x21, 0x04, 0xaf, 0x4f, 0xe4, - 0x92, 0x39, 0xd9, 0x72, 0x35, 0x9e, 0x7e, 0xd5, 0xa3, 0x08, - 0xe8, 0x43, 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, - 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a, 0x12, 0xbe, - 0x57, 0xfb, 0x98, 0x34, 0xdd, 0x71, 0x1b, 0xb7, 0x5e, 0xf2, - 0x91, 0x3d, 0xd4, 0x78, 0x24, 0x88, 0x61, 0xcd, 0xae, 0x02, - 0xeb, 0x47, 0x2d, 0x81, 0x68, 0xc4, 0xa7, 0x0b, 0xe2, 0x4e, - 0x36, 0x9a, 0x73, 0xdf, 0xbc, 0x10, 0xf9, 0x55, 0x3f, 0x93, - 0x7a, 0xd6, 0xb5, 0x19, 0xf0, 0x5c, 0x48, 0xe4, 0x0d, 0xa1, - 0xc2, 0x6e, 0x87, 0x2b, 0x41, 0xed, 0x04, 0xa8, 0xcb, 0x67, - 0x8e, 0x22, 0x5a, 0xf6, 0x1f, 0xb3, 0xd0, 0x7c, 0x95, 0x39, - 0x53, 0xff, 0x16, 0xba, 0xd9, 0x75, 0x9c, 0x30, 0x6c, 0xc0, - 0x29, 0x85, 0xe6, 0x4a, 0xa3, 0x0f, 0x65, 0xc9, 0x20, 0x8c, - 0xef, 0x43, 0xaa, 0x06, 0x7e, 0xd2, 0x3b, 0x97, 0xf4, 0x58, - 0xb1, 0x1d, 0x77, 0xdb, 0x32, 0x9e, 0xfd, 0x51, 0xb8, 0x14, - 0x90, 0x3c, 0xd5, 0x79, 0x1a, 0xb6, 0x5f, 0xf3, 0x99, 0x35, - 0xdc, 0x70, 0x13, 0xbf, 0x56, 0xfa, 0x82, 0x2e, 0xc7, 0x6b, - 0x08, 0xa4, 0x4d, 0xe1, 0x8b, 0x27, 0xce, 0x62, 0x01, 0xad, - 0x44, 0xe8, 0xb4, 0x18, 0xf1, 0x5d, 0x3e, 0x92, 0x7b, 0xd7, - 0xbd, 0x11, 0xf8, 0x54, 0x37, 0x9b, 0x72, 0xde, 0xa6, 0x0a, - 0xe3, 0x4f, 0x2c, 0x80, 0x69, 0xc5, 0xaf, 0x03, 0xea, 0x46, - 0x25, 0x89, 0x60, 0xcc, 0xd8, 0x74, 0x9d, 0x31, 0x52, 0xfe, - 0x17, 0xbb, 0xd1, 0x7d, 0x94, 0x38, 0x5b, 0xf7, 0x1e, 0xb2, - 0xca, 0x66, 0x8f, 0x23, 0x40, 0xec, 0x05, 0xa9, 0xc3, 0x6f, - 0x86, 0x2a, 0x49, 0xe5, 0x0c, 0xa0, 0xfc, 0x50, 0xb9, 0x15, - 0x76, 0xda, 0x33, 0x9f, 0xf5, 0x59, 0xb0, 0x1c, 0x7f, 0xd3, - 0x3a, 0x96, 0xee, 0x42, 0xab, 0x07, 0x64, 0xc8, 0x21, 0x8d, - 0xe7, 0x4b, 0xa2, 0x0e, 0x6d, 0xc1, 0x28, 0x84, 0x00, 0xad, - 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, - 0x8f, 0x22, 0xc8, 0x65, 0x02, 0xaf, 0x45, 0xe8, 0x8c, 0x21, - 0xcb, 0x66, 0x03, 0xae, 0x44, 0xe9, 0x8d, 0x20, 0xca, 0x67, - 0x04, 0xa9, 0x43, 0xee, 0x8a, 0x27, 0xcd, 0x60, 0x05, 0xa8, - 0x42, 0xef, 0x8b, 0x26, 0xcc, 0x61, 0x06, 0xab, 0x41, 0xec, - 0x88, 0x25, 0xcf, 0x62, 0x07, 0xaa, 0x40, 0xed, 0x89, 0x24, - 0xce, 0x63, 0x08, 0xa5, 0x4f, 0xe2, 0x86, 0x2b, 0xc1, 0x6c, - 0x09, 0xa4, 0x4e, 0xe3, 0x87, 0x2a, 0xc0, 0x6d, 0x0a, 0xa7, - 0x4d, 0xe0, 0x84, 0x29, 0xc3, 0x6e, 0x0b, 0xa6, 0x4c, 0xe1, - 0x85, 0x28, 0xc2, 0x6f, 0x0c, 0xa1, 0x4b, 0xe6, 0x82, 0x2f, - 0xc5, 0x68, 0x0d, 0xa0, 0x4a, 0xe7, 0x83, 0x2e, 0xc4, 0x69, - 0x0e, 0xa3, 0x49, 0xe4, 0x80, 0x2d, 0xc7, 0x6a, 0x0f, 0xa2, - 0x48, 0xe5, 0x81, 0x2c, 0xc6, 0x6b, 0x10, 0xbd, 0x57, 0xfa, - 0x9e, 0x33, 0xd9, 0x74, 0x11, 0xbc, 0x56, 0xfb, 0x9f, 0x32, - 0xd8, 0x75, 0x12, 0xbf, 0x55, 0xf8, 0x9c, 0x31, 0xdb, 0x76, - 0x13, 0xbe, 0x54, 0xf9, 0x9d, 0x30, 0xda, 0x77, 0x14, 0xb9, - 0x53, 0xfe, 0x9a, 0x37, 0xdd, 0x70, 0x15, 0xb8, 0x52, 0xff, - 0x9b, 0x36, 0xdc, 0x71, 0x16, 0xbb, 0x51, 0xfc, 0x98, 0x35, - 0xdf, 0x72, 0x17, 0xba, 0x50, 0xfd, 0x99, 0x34, 0xde, 0x73, - 0x18, 0xb5, 0x5f, 0xf2, 0x96, 0x3b, 0xd1, 0x7c, 0x19, 0xb4, - 0x5e, 0xf3, 0x97, 0x3a, 0xd0, 0x7d, 0x1a, 0xb7, 0x5d, 0xf0, - 0x94, 0x39, 0xd3, 0x7e, 0x1b, 0xb6, 0x5c, 0xf1, 0x95, 0x38, - 0xd2, 0x7f, 0x1c, 0xb1, 0x5b, 0xf6, 0x92, 0x3f, 0xd5, 0x78, - 0x1d, 0xb0, 0x5a, 0xf7, 0x93, 0x3e, 0xd4, 0x79, 0x1e, 0xb3, - 0x59, 0xf4, 0x90, 0x3d, 0xd7, 0x7a, 0x1f, 0xb2, 0x58, 0xf5, - 0x91, 0x3c, 0xd6, 0x7b, 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, - 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74, - 0x32, 0x9c, 0x73, 0xdd, 0xb0, 0x1e, 0xf1, 0x5f, 0x2b, 0x85, - 0x6a, 0xc4, 0xa9, 0x07, 0xe8, 0x46, 0x64, 0xca, 0x25, 0x8b, - 0xe6, 0x48, 0xa7, 0x09, 0x7d, 0xd3, 0x3c, 0x92, 0xff, 0x51, - 0xbe, 0x10, 0x56, 0xf8, 0x17, 0xb9, 0xd4, 0x7a, 0x95, 0x3b, - 0x4f, 0xe1, 0x0e, 0xa0, 0xcd, 0x63, 0x8c, 0x22, 0xc8, 0x66, - 0x89, 0x27, 0x4a, 0xe4, 0x0b, 0xa5, 0xd1, 0x7f, 0x90, 0x3e, - 0x53, 0xfd, 0x12, 0xbc, 0xfa, 0x54, 0xbb, 0x15, 0x78, 0xd6, - 0x39, 0x97, 0xe3, 0x4d, 0xa2, 0x0c, 0x61, 0xcf, 0x20, 0x8e, - 0xac, 0x02, 0xed, 0x43, 0x2e, 0x80, 0x6f, 0xc1, 0xb5, 0x1b, - 0xf4, 0x5a, 0x37, 0x99, 0x76, 0xd8, 0x9e, 0x30, 0xdf, 0x71, - 0x1c, 0xb2, 0x5d, 0xf3, 0x87, 0x29, 0xc6, 0x68, 0x05, 0xab, - 0x44, 0xea, 0x8d, 0x23, 0xcc, 0x62, 0x0f, 0xa1, 0x4e, 0xe0, - 0x94, 0x3a, 0xd5, 0x7b, 0x16, 0xb8, 0x57, 0xf9, 0xbf, 0x11, - 0xfe, 0x50, 0x3d, 0x93, 0x7c, 0xd2, 0xa6, 0x08, 0xe7, 0x49, - 0x24, 0x8a, 0x65, 0xcb, 0xe9, 0x47, 0xa8, 0x06, 0x6b, 0xc5, - 0x2a, 0x84, 0xf0, 0x5e, 0xb1, 0x1f, 0x72, 0xdc, 0x33, 0x9d, - 0xdb, 0x75, 0x9a, 0x34, 0x59, 0xf7, 0x18, 0xb6, 0xc2, 0x6c, - 0x83, 0x2d, 0x40, 0xee, 0x01, 0xaf, 0x45, 0xeb, 0x04, 0xaa, - 0xc7, 0x69, 0x86, 0x28, 0x5c, 0xf2, 0x1d, 0xb3, 0xde, 0x70, - 0x9f, 0x31, 0x77, 0xd9, 0x36, 0x98, 0xf5, 0x5b, 0xb4, 0x1a, - 0x6e, 0xc0, 0x2f, 0x81, 0xec, 0x42, 0xad, 0x03, 0x21, 0x8f, - 0x60, 0xce, 0xa3, 0x0d, 0xe2, 0x4c, 0x38, 0x96, 0x79, 0xd7, - 0xba, 0x14, 0xfb, 0x55, 0x13, 0xbd, 0x52, 0xfc, 0x91, 0x3f, - 0xd0, 0x7e, 0x0a, 0xa4, 0x4b, 0xe5, 0x88, 0x26, 0xc9, 0x67, - 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, - 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b, 0x22, 0x8d, 0x61, 0xce, - 0xa4, 0x0b, 0xe7, 0x48, 0x33, 0x9c, 0x70, 0xdf, 0xb5, 0x1a, - 0xf6, 0x59, 0x44, 0xeb, 0x07, 0xa8, 0xc2, 0x6d, 0x81, 0x2e, - 0x55, 0xfa, 0x16, 0xb9, 0xd3, 0x7c, 0x90, 0x3f, 0x66, 0xc9, - 0x25, 0x8a, 0xe0, 0x4f, 0xa3, 0x0c, 0x77, 0xd8, 0x34, 0x9b, - 0xf1, 0x5e, 0xb2, 0x1d, 0x88, 0x27, 0xcb, 0x64, 0x0e, 0xa1, - 0x4d, 0xe2, 0x99, 0x36, 0xda, 0x75, 0x1f, 0xb0, 0x5c, 0xf3, - 0xaa, 0x05, 0xe9, 0x46, 0x2c, 0x83, 0x6f, 0xc0, 0xbb, 0x14, - 0xf8, 0x57, 0x3d, 0x92, 0x7e, 0xd1, 0xcc, 0x63, 0x8f, 0x20, - 0x4a, 0xe5, 0x09, 0xa6, 0xdd, 0x72, 0x9e, 0x31, 0x5b, 0xf4, - 0x18, 0xb7, 0xee, 0x41, 0xad, 0x02, 0x68, 0xc7, 0x2b, 0x84, - 0xff, 0x50, 0xbc, 0x13, 0x79, 0xd6, 0x3a, 0x95, 0x0d, 0xa2, - 0x4e, 0xe1, 0x8b, 0x24, 0xc8, 0x67, 0x1c, 0xb3, 0x5f, 0xf0, - 0x9a, 0x35, 0xd9, 0x76, 0x2f, 0x80, 0x6c, 0xc3, 0xa9, 0x06, - 0xea, 0x45, 0x3e, 0x91, 0x7d, 0xd2, 0xb8, 0x17, 0xfb, 0x54, - 0x49, 0xe6, 0x0a, 0xa5, 0xcf, 0x60, 0x8c, 0x23, 0x58, 0xf7, - 0x1b, 0xb4, 0xde, 0x71, 0x9d, 0x32, 0x6b, 0xc4, 0x28, 0x87, - 0xed, 0x42, 0xae, 0x01, 0x7a, 0xd5, 0x39, 0x96, 0xfc, 0x53, - 0xbf, 0x10, 0x85, 0x2a, 0xc6, 0x69, 0x03, 0xac, 0x40, 0xef, - 0x94, 0x3b, 0xd7, 0x78, 0x12, 0xbd, 0x51, 0xfe, 0xa7, 0x08, - 0xe4, 0x4b, 0x21, 0x8e, 0x62, 0xcd, 0xb6, 0x19, 0xf5, 0x5a, - 0x30, 0x9f, 0x73, 0xdc, 0xc1, 0x6e, 0x82, 0x2d, 0x47, 0xe8, - 0x04, 0xab, 0xd0, 0x7f, 0x93, 0x3c, 0x56, 0xf9, 0x15, 0xba, - 0xe3, 0x4c, 0xa0, 0x0f, 0x65, 0xca, 0x26, 0x89, 0xf2, 0x5d, - 0xb1, 0x1e, 0x74, 0xdb, 0x37, 0x98, 0x00, 0xb0, 0x7d, 0xcd, - 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, - 0x6e, 0xde, 0xcf, 0x7f, 0xb2, 0x02, 0x35, 0x85, 0x48, 0xf8, - 0x26, 0x96, 0x5b, 0xeb, 0xdc, 0x6c, 0xa1, 0x11, 0x83, 0x33, - 0xfe, 0x4e, 0x79, 0xc9, 0x04, 0xb4, 0x6a, 0xda, 0x17, 0xa7, - 0x90, 0x20, 0xed, 0x5d, 0x4c, 0xfc, 0x31, 0x81, 0xb6, 0x06, - 0xcb, 0x7b, 0xa5, 0x15, 0xd8, 0x68, 0x5f, 0xef, 0x22, 0x92, - 0x1b, 0xab, 0x66, 0xd6, 0xe1, 0x51, 0x9c, 0x2c, 0xf2, 0x42, - 0x8f, 0x3f, 0x08, 0xb8, 0x75, 0xc5, 0xd4, 0x64, 0xa9, 0x19, - 0x2e, 0x9e, 0x53, 0xe3, 0x3d, 0x8d, 0x40, 0xf0, 0xc7, 0x77, - 0xba, 0x0a, 0x98, 0x28, 0xe5, 0x55, 0x62, 0xd2, 0x1f, 0xaf, - 0x71, 0xc1, 0x0c, 0xbc, 0x8b, 0x3b, 0xf6, 0x46, 0x57, 0xe7, - 0x2a, 0x9a, 0xad, 0x1d, 0xd0, 0x60, 0xbe, 0x0e, 0xc3, 0x73, - 0x44, 0xf4, 0x39, 0x89, 0x36, 0x86, 0x4b, 0xfb, 0xcc, 0x7c, - 0xb1, 0x01, 0xdf, 0x6f, 0xa2, 0x12, 0x25, 0x95, 0x58, 0xe8, - 0xf9, 0x49, 0x84, 0x34, 0x03, 0xb3, 0x7e, 0xce, 0x10, 0xa0, - 0x6d, 0xdd, 0xea, 0x5a, 0x97, 0x27, 0xb5, 0x05, 0xc8, 0x78, - 0x4f, 0xff, 0x32, 0x82, 0x5c, 0xec, 0x21, 0x91, 0xa6, 0x16, - 0xdb, 0x6b, 0x7a, 0xca, 0x07, 0xb7, 0x80, 0x30, 0xfd, 0x4d, - 0x93, 0x23, 0xee, 0x5e, 0x69, 0xd9, 0x14, 0xa4, 0x2d, 0x9d, - 0x50, 0xe0, 0xd7, 0x67, 0xaa, 0x1a, 0xc4, 0x74, 0xb9, 0x09, - 0x3e, 0x8e, 0x43, 0xf3, 0xe2, 0x52, 0x9f, 0x2f, 0x18, 0xa8, - 0x65, 0xd5, 0x0b, 0xbb, 0x76, 0xc6, 0xf1, 0x41, 0x8c, 0x3c, - 0xae, 0x1e, 0xd3, 0x63, 0x54, 0xe4, 0x29, 0x99, 0x47, 0xf7, - 0x3a, 0x8a, 0xbd, 0x0d, 0xc0, 0x70, 0x61, 0xd1, 0x1c, 0xac, - 0x9b, 0x2b, 0xe6, 0x56, 0x88, 0x38, 0xf5, 0x45, 0x72, 0xc2, - 0x0f, 0xbf, 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, - 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1, 0xdf, 0x6e, - 0xa0, 0x11, 0x21, 0x90, 0x5e, 0xef, 0x3e, 0x8f, 0x41, 0xf0, - 0xc0, 0x71, 0xbf, 0x0e, 0xa3, 0x12, 0xdc, 0x6d, 0x5d, 0xec, - 0x22, 0x93, 0x42, 0xf3, 0x3d, 0x8c, 0xbc, 0x0d, 0xc3, 0x72, - 0x7c, 0xcd, 0x03, 0xb2, 0x82, 0x33, 0xfd, 0x4c, 0x9d, 0x2c, - 0xe2, 0x53, 0x63, 0xd2, 0x1c, 0xad, 0x5b, 0xea, 0x24, 0x95, - 0xa5, 0x14, 0xda, 0x6b, 0xba, 0x0b, 0xc5, 0x74, 0x44, 0xf5, - 0x3b, 0x8a, 0x84, 0x35, 0xfb, 0x4a, 0x7a, 0xcb, 0x05, 0xb4, - 0x65, 0xd4, 0x1a, 0xab, 0x9b, 0x2a, 0xe4, 0x55, 0xf8, 0x49, - 0x87, 0x36, 0x06, 0xb7, 0x79, 0xc8, 0x19, 0xa8, 0x66, 0xd7, - 0xe7, 0x56, 0x98, 0x29, 0x27, 0x96, 0x58, 0xe9, 0xd9, 0x68, - 0xa6, 0x17, 0xc6, 0x77, 0xb9, 0x08, 0x38, 0x89, 0x47, 0xf6, - 0xb6, 0x07, 0xc9, 0x78, 0x48, 0xf9, 0x37, 0x86, 0x57, 0xe6, - 0x28, 0x99, 0xa9, 0x18, 0xd6, 0x67, 0x69, 0xd8, 0x16, 0xa7, - 0x97, 0x26, 0xe8, 0x59, 0x88, 0x39, 0xf7, 0x46, 0x76, 0xc7, - 0x09, 0xb8, 0x15, 0xa4, 0x6a, 0xdb, 0xeb, 0x5a, 0x94, 0x25, - 0xf4, 0x45, 0x8b, 0x3a, 0x0a, 0xbb, 0x75, 0xc4, 0xca, 0x7b, - 0xb5, 0x04, 0x34, 0x85, 0x4b, 0xfa, 0x2b, 0x9a, 0x54, 0xe5, - 0xd5, 0x64, 0xaa, 0x1b, 0xed, 0x5c, 0x92, 0x23, 0x13, 0xa2, - 0x6c, 0xdd, 0x0c, 0xbd, 0x73, 0xc2, 0xf2, 0x43, 0x8d, 0x3c, - 0x32, 0x83, 0x4d, 0xfc, 0xcc, 0x7d, 0xb3, 0x02, 0xd3, 0x62, - 0xac, 0x1d, 0x2d, 0x9c, 0x52, 0xe3, 0x4e, 0xff, 0x31, 0x80, - 0xb0, 0x01, 0xcf, 0x7e, 0xaf, 0x1e, 0xd0, 0x61, 0x51, 0xe0, - 0x2e, 0x9f, 0x91, 0x20, 0xee, 0x5f, 0x6f, 0xde, 0x10, 0xa1, - 0x70, 0xc1, 0x0f, 0xbe, 0x8e, 0x3f, 0xf1, 0x40, 0x00, 0xb2, - 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, - 0x0b, 0xb9, 0x72, 0xc0, 0xef, 0x5d, 0x96, 0x24, 0x1d, 0xaf, - 0x64, 0xd6, 0x16, 0xa4, 0x6f, 0xdd, 0xe4, 0x56, 0x9d, 0x2f, - 0xc3, 0x71, 0xba, 0x08, 0x31, 0x83, 0x48, 0xfa, 0x3a, 0x88, - 0x43, 0xf1, 0xc8, 0x7a, 0xb1, 0x03, 0x2c, 0x9e, 0x55, 0xe7, - 0xde, 0x6c, 0xa7, 0x15, 0xd5, 0x67, 0xac, 0x1e, 0x27, 0x95, - 0x5e, 0xec, 0x9b, 0x29, 0xe2, 0x50, 0x69, 0xdb, 0x10, 0xa2, - 0x62, 0xd0, 0x1b, 0xa9, 0x90, 0x22, 0xe9, 0x5b, 0x74, 0xc6, - 0x0d, 0xbf, 0x86, 0x34, 0xff, 0x4d, 0x8d, 0x3f, 0xf4, 0x46, - 0x7f, 0xcd, 0x06, 0xb4, 0x58, 0xea, 0x21, 0x93, 0xaa, 0x18, - 0xd3, 0x61, 0xa1, 0x13, 0xd8, 0x6a, 0x53, 0xe1, 0x2a, 0x98, - 0xb7, 0x05, 0xce, 0x7c, 0x45, 0xf7, 0x3c, 0x8e, 0x4e, 0xfc, - 0x37, 0x85, 0xbc, 0x0e, 0xc5, 0x77, 0x2b, 0x99, 0x52, 0xe0, - 0xd9, 0x6b, 0xa0, 0x12, 0xd2, 0x60, 0xab, 0x19, 0x20, 0x92, - 0x59, 0xeb, 0xc4, 0x76, 0xbd, 0x0f, 0x36, 0x84, 0x4f, 0xfd, - 0x3d, 0x8f, 0x44, 0xf6, 0xcf, 0x7d, 0xb6, 0x04, 0xe8, 0x5a, - 0x91, 0x23, 0x1a, 0xa8, 0x63, 0xd1, 0x11, 0xa3, 0x68, 0xda, - 0xe3, 0x51, 0x9a, 0x28, 0x07, 0xb5, 0x7e, 0xcc, 0xf5, 0x47, - 0x8c, 0x3e, 0xfe, 0x4c, 0x87, 0x35, 0x0c, 0xbe, 0x75, 0xc7, - 0xb0, 0x02, 0xc9, 0x7b, 0x42, 0xf0, 0x3b, 0x89, 0x49, 0xfb, - 0x30, 0x82, 0xbb, 0x09, 0xc2, 0x70, 0x5f, 0xed, 0x26, 0x94, - 0xad, 0x1f, 0xd4, 0x66, 0xa6, 0x14, 0xdf, 0x6d, 0x54, 0xe6, - 0x2d, 0x9f, 0x73, 0xc1, 0x0a, 0xb8, 0x81, 0x33, 0xf8, 0x4a, - 0x8a, 0x38, 0xf3, 0x41, 0x78, 0xca, 0x01, 0xb3, 0x9c, 0x2e, - 0xe5, 0x57, 0x6e, 0xdc, 0x17, 0xa5, 0x65, 0xd7, 0x1c, 0xae, - 0x97, 0x25, 0xee, 0x5c, 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, - 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf, - 0xff, 0x4c, 0x84, 0x37, 0x09, 0xba, 0x72, 0xc1, 0x0e, 0xbd, - 0x75, 0xc6, 0xf8, 0x4b, 0x83, 0x30, 0xe3, 0x50, 0x98, 0x2b, - 0x15, 0xa6, 0x6e, 0xdd, 0x12, 0xa1, 0x69, 0xda, 0xe4, 0x57, - 0x9f, 0x2c, 0x1c, 0xaf, 0x67, 0xd4, 0xea, 0x59, 0x91, 0x22, - 0xed, 0x5e, 0x96, 0x25, 0x1b, 0xa8, 0x60, 0xd3, 0xdb, 0x68, - 0xa0, 0x13, 0x2d, 0x9e, 0x56, 0xe5, 0x2a, 0x99, 0x51, 0xe2, - 0xdc, 0x6f, 0xa7, 0x14, 0x24, 0x97, 0x5f, 0xec, 0xd2, 0x61, - 0xa9, 0x1a, 0xd5, 0x66, 0xae, 0x1d, 0x23, 0x90, 0x58, 0xeb, - 0x38, 0x8b, 0x43, 0xf0, 0xce, 0x7d, 0xb5, 0x06, 0xc9, 0x7a, - 0xb2, 0x01, 0x3f, 0x8c, 0x44, 0xf7, 0xc7, 0x74, 0xbc, 0x0f, - 0x31, 0x82, 0x4a, 0xf9, 0x36, 0x85, 0x4d, 0xfe, 0xc0, 0x73, - 0xbb, 0x08, 0xab, 0x18, 0xd0, 0x63, 0x5d, 0xee, 0x26, 0x95, - 0x5a, 0xe9, 0x21, 0x92, 0xac, 0x1f, 0xd7, 0x64, 0x54, 0xe7, - 0x2f, 0x9c, 0xa2, 0x11, 0xd9, 0x6a, 0xa5, 0x16, 0xde, 0x6d, - 0x53, 0xe0, 0x28, 0x9b, 0x48, 0xfb, 0x33, 0x80, 0xbe, 0x0d, - 0xc5, 0x76, 0xb9, 0x0a, 0xc2, 0x71, 0x4f, 0xfc, 0x34, 0x87, - 0xb7, 0x04, 0xcc, 0x7f, 0x41, 0xf2, 0x3a, 0x89, 0x46, 0xf5, - 0x3d, 0x8e, 0xb0, 0x03, 0xcb, 0x78, 0x70, 0xc3, 0x0b, 0xb8, - 0x86, 0x35, 0xfd, 0x4e, 0x81, 0x32, 0xfa, 0x49, 0x77, 0xc4, - 0x0c, 0xbf, 0x8f, 0x3c, 0xf4, 0x47, 0x79, 0xca, 0x02, 0xb1, - 0x7e, 0xcd, 0x05, 0xb6, 0x88, 0x3b, 0xf3, 0x40, 0x93, 0x20, - 0xe8, 0x5b, 0x65, 0xd6, 0x1e, 0xad, 0x62, 0xd1, 0x19, 0xaa, - 0x94, 0x27, 0xef, 0x5c, 0x6c, 0xdf, 0x17, 0xa4, 0x9a, 0x29, - 0xe1, 0x52, 0x9d, 0x2e, 0xe6, 0x55, 0x6b, 0xd8, 0x10, 0xa3, - 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, - 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2, 0x8f, 0x3b, 0xfa, 0x4e, - 0x65, 0xd1, 0x10, 0xa4, 0x46, 0xf2, 0x33, 0x87, 0xac, 0x18, - 0xd9, 0x6d, 0x03, 0xb7, 0x76, 0xc2, 0xe9, 0x5d, 0x9c, 0x28, - 0xca, 0x7e, 0xbf, 0x0b, 0x20, 0x94, 0x55, 0xe1, 0x8c, 0x38, - 0xf9, 0x4d, 0x66, 0xd2, 0x13, 0xa7, 0x45, 0xf1, 0x30, 0x84, - 0xaf, 0x1b, 0xda, 0x6e, 0x06, 0xb2, 0x73, 0xc7, 0xec, 0x58, - 0x99, 0x2d, 0xcf, 0x7b, 0xba, 0x0e, 0x25, 0x91, 0x50, 0xe4, - 0x89, 0x3d, 0xfc, 0x48, 0x63, 0xd7, 0x16, 0xa2, 0x40, 0xf4, - 0x35, 0x81, 0xaa, 0x1e, 0xdf, 0x6b, 0x05, 0xb1, 0x70, 0xc4, - 0xef, 0x5b, 0x9a, 0x2e, 0xcc, 0x78, 0xb9, 0x0d, 0x26, 0x92, - 0x53, 0xe7, 0x8a, 0x3e, 0xff, 0x4b, 0x60, 0xd4, 0x15, 0xa1, - 0x43, 0xf7, 0x36, 0x82, 0xa9, 0x1d, 0xdc, 0x68, 0x0c, 0xb8, - 0x79, 0xcd, 0xe6, 0x52, 0x93, 0x27, 0xc5, 0x71, 0xb0, 0x04, - 0x2f, 0x9b, 0x5a, 0xee, 0x83, 0x37, 0xf6, 0x42, 0x69, 0xdd, - 0x1c, 0xa8, 0x4a, 0xfe, 0x3f, 0x8b, 0xa0, 0x14, 0xd5, 0x61, - 0x0f, 0xbb, 0x7a, 0xce, 0xe5, 0x51, 0x90, 0x24, 0xc6, 0x72, - 0xb3, 0x07, 0x2c, 0x98, 0x59, 0xed, 0x80, 0x34, 0xf5, 0x41, - 0x6a, 0xde, 0x1f, 0xab, 0x49, 0xfd, 0x3c, 0x88, 0xa3, 0x17, - 0xd6, 0x62, 0x0a, 0xbe, 0x7f, 0xcb, 0xe0, 0x54, 0x95, 0x21, - 0xc3, 0x77, 0xb6, 0x02, 0x29, 0x9d, 0x5c, 0xe8, 0x85, 0x31, - 0xf0, 0x44, 0x6f, 0xdb, 0x1a, 0xae, 0x4c, 0xf8, 0x39, 0x8d, - 0xa6, 0x12, 0xd3, 0x67, 0x09, 0xbd, 0x7c, 0xc8, 0xe3, 0x57, - 0x96, 0x22, 0xc0, 0x74, 0xb5, 0x01, 0x2a, 0x9e, 0x5f, 0xeb, - 0x86, 0x32, 0xf3, 0x47, 0x6c, 0xd8, 0x19, 0xad, 0x4f, 0xfb, - 0x3a, 0x8e, 0xa5, 0x11, 0xd0, 0x64, 0x00, 0xb5, 0x77, 0xc2, - 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, - 0x58, 0xed, 0x9f, 0x2a, 0xe8, 0x5d, 0x71, 0xc4, 0x06, 0xb3, - 0x5e, 0xeb, 0x29, 0x9c, 0xb0, 0x05, 0xc7, 0x72, 0x23, 0x96, - 0x54, 0xe1, 0xcd, 0x78, 0xba, 0x0f, 0xe2, 0x57, 0x95, 0x20, - 0x0c, 0xb9, 0x7b, 0xce, 0xbc, 0x09, 0xcb, 0x7e, 0x52, 0xe7, - 0x25, 0x90, 0x7d, 0xc8, 0x0a, 0xbf, 0x93, 0x26, 0xe4, 0x51, - 0x46, 0xf3, 0x31, 0x84, 0xa8, 0x1d, 0xdf, 0x6a, 0x87, 0x32, - 0xf0, 0x45, 0x69, 0xdc, 0x1e, 0xab, 0xd9, 0x6c, 0xae, 0x1b, - 0x37, 0x82, 0x40, 0xf5, 0x18, 0xad, 0x6f, 0xda, 0xf6, 0x43, - 0x81, 0x34, 0x65, 0xd0, 0x12, 0xa7, 0x8b, 0x3e, 0xfc, 0x49, - 0xa4, 0x11, 0xd3, 0x66, 0x4a, 0xff, 0x3d, 0x88, 0xfa, 0x4f, - 0x8d, 0x38, 0x14, 0xa1, 0x63, 0xd6, 0x3b, 0x8e, 0x4c, 0xf9, - 0xd5, 0x60, 0xa2, 0x17, 0x8c, 0x39, 0xfb, 0x4e, 0x62, 0xd7, - 0x15, 0xa0, 0x4d, 0xf8, 0x3a, 0x8f, 0xa3, 0x16, 0xd4, 0x61, - 0x13, 0xa6, 0x64, 0xd1, 0xfd, 0x48, 0x8a, 0x3f, 0xd2, 0x67, - 0xa5, 0x10, 0x3c, 0x89, 0x4b, 0xfe, 0xaf, 0x1a, 0xd8, 0x6d, - 0x41, 0xf4, 0x36, 0x83, 0x6e, 0xdb, 0x19, 0xac, 0x80, 0x35, - 0xf7, 0x42, 0x30, 0x85, 0x47, 0xf2, 0xde, 0x6b, 0xa9, 0x1c, - 0xf1, 0x44, 0x86, 0x33, 0x1f, 0xaa, 0x68, 0xdd, 0xca, 0x7f, - 0xbd, 0x08, 0x24, 0x91, 0x53, 0xe6, 0x0b, 0xbe, 0x7c, 0xc9, - 0xe5, 0x50, 0x92, 0x27, 0x55, 0xe0, 0x22, 0x97, 0xbb, 0x0e, - 0xcc, 0x79, 0x94, 0x21, 0xe3, 0x56, 0x7a, 0xcf, 0x0d, 0xb8, - 0xe9, 0x5c, 0x9e, 0x2b, 0x07, 0xb2, 0x70, 0xc5, 0x28, 0x9d, - 0x5f, 0xea, 0xc6, 0x73, 0xb1, 0x04, 0x76, 0xc3, 0x01, 0xb4, - 0x98, 0x2d, 0xef, 0x5a, 0xb7, 0x02, 0xc0, 0x75, 0x59, 0xec, - 0x2e, 0x9b, 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, - 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc, 0xaf, 0x19, - 0xde, 0x68, 0x4d, 0xfb, 0x3c, 0x8a, 0x76, 0xc0, 0x07, 0xb1, - 0x94, 0x22, 0xe5, 0x53, 0x43, 0xf5, 0x32, 0x84, 0xa1, 0x17, - 0xd0, 0x66, 0x9a, 0x2c, 0xeb, 0x5d, 0x78, 0xce, 0x09, 0xbf, - 0xec, 0x5a, 0x9d, 0x2b, 0x0e, 0xb8, 0x7f, 0xc9, 0x35, 0x83, - 0x44, 0xf2, 0xd7, 0x61, 0xa6, 0x10, 0x86, 0x30, 0xf7, 0x41, - 0x64, 0xd2, 0x15, 0xa3, 0x5f, 0xe9, 0x2e, 0x98, 0xbd, 0x0b, - 0xcc, 0x7a, 0x29, 0x9f, 0x58, 0xee, 0xcb, 0x7d, 0xba, 0x0c, - 0xf0, 0x46, 0x81, 0x37, 0x12, 0xa4, 0x63, 0xd5, 0xc5, 0x73, - 0xb4, 0x02, 0x27, 0x91, 0x56, 0xe0, 0x1c, 0xaa, 0x6d, 0xdb, - 0xfe, 0x48, 0x8f, 0x39, 0x6a, 0xdc, 0x1b, 0xad, 0x88, 0x3e, - 0xf9, 0x4f, 0xb3, 0x05, 0xc2, 0x74, 0x51, 0xe7, 0x20, 0x96, - 0x11, 0xa7, 0x60, 0xd6, 0xf3, 0x45, 0x82, 0x34, 0xc8, 0x7e, - 0xb9, 0x0f, 0x2a, 0x9c, 0x5b, 0xed, 0xbe, 0x08, 0xcf, 0x79, - 0x5c, 0xea, 0x2d, 0x9b, 0x67, 0xd1, 0x16, 0xa0, 0x85, 0x33, - 0xf4, 0x42, 0x52, 0xe4, 0x23, 0x95, 0xb0, 0x06, 0xc1, 0x77, - 0x8b, 0x3d, 0xfa, 0x4c, 0x69, 0xdf, 0x18, 0xae, 0xfd, 0x4b, - 0x8c, 0x3a, 0x1f, 0xa9, 0x6e, 0xd8, 0x24, 0x92, 0x55, 0xe3, - 0xc6, 0x70, 0xb7, 0x01, 0x97, 0x21, 0xe6, 0x50, 0x75, 0xc3, - 0x04, 0xb2, 0x4e, 0xf8, 0x3f, 0x89, 0xac, 0x1a, 0xdd, 0x6b, - 0x38, 0x8e, 0x49, 0xff, 0xda, 0x6c, 0xab, 0x1d, 0xe1, 0x57, - 0x90, 0x26, 0x03, 0xb5, 0x72, 0xc4, 0xd4, 0x62, 0xa5, 0x13, - 0x36, 0x80, 0x47, 0xf1, 0x0d, 0xbb, 0x7c, 0xca, 0xef, 0x59, - 0x9e, 0x28, 0x7b, 0xcd, 0x0a, 0xbc, 0x99, 0x2f, 0xe8, 0x5e, - 0xa2, 0x14, 0xd3, 0x65, 0x40, 0xf6, 0x31, 0x87, 0x00, 0xb7, - 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, - 0x37, 0x80, 0x44, 0xf3, 0xbf, 0x08, 0xcc, 0x7b, 0x59, 0xee, - 0x2a, 0x9d, 0x6e, 0xd9, 0x1d, 0xaa, 0x88, 0x3f, 0xfb, 0x4c, - 0x63, 0xd4, 0x10, 0xa7, 0x85, 0x32, 0xf6, 0x41, 0xb2, 0x05, - 0xc1, 0x76, 0x54, 0xe3, 0x27, 0x90, 0xdc, 0x6b, 0xaf, 0x18, - 0x3a, 0x8d, 0x49, 0xfe, 0x0d, 0xba, 0x7e, 0xc9, 0xeb, 0x5c, - 0x98, 0x2f, 0xc6, 0x71, 0xb5, 0x02, 0x20, 0x97, 0x53, 0xe4, - 0x17, 0xa0, 0x64, 0xd3, 0xf1, 0x46, 0x82, 0x35, 0x79, 0xce, - 0x0a, 0xbd, 0x9f, 0x28, 0xec, 0x5b, 0xa8, 0x1f, 0xdb, 0x6c, - 0x4e, 0xf9, 0x3d, 0x8a, 0xa5, 0x12, 0xd6, 0x61, 0x43, 0xf4, - 0x30, 0x87, 0x74, 0xc3, 0x07, 0xb0, 0x92, 0x25, 0xe1, 0x56, - 0x1a, 0xad, 0x69, 0xde, 0xfc, 0x4b, 0x8f, 0x38, 0xcb, 0x7c, - 0xb8, 0x0f, 0x2d, 0x9a, 0x5e, 0xe9, 0x91, 0x26, 0xe2, 0x55, - 0x77, 0xc0, 0x04, 0xb3, 0x40, 0xf7, 0x33, 0x84, 0xa6, 0x11, - 0xd5, 0x62, 0x2e, 0x99, 0x5d, 0xea, 0xc8, 0x7f, 0xbb, 0x0c, - 0xff, 0x48, 0x8c, 0x3b, 0x19, 0xae, 0x6a, 0xdd, 0xf2, 0x45, - 0x81, 0x36, 0x14, 0xa3, 0x67, 0xd0, 0x23, 0x94, 0x50, 0xe7, - 0xc5, 0x72, 0xb6, 0x01, 0x4d, 0xfa, 0x3e, 0x89, 0xab, 0x1c, - 0xd8, 0x6f, 0x9c, 0x2b, 0xef, 0x58, 0x7a, 0xcd, 0x09, 0xbe, - 0x57, 0xe0, 0x24, 0x93, 0xb1, 0x06, 0xc2, 0x75, 0x86, 0x31, - 0xf5, 0x42, 0x60, 0xd7, 0x13, 0xa4, 0xe8, 0x5f, 0x9b, 0x2c, - 0x0e, 0xb9, 0x7d, 0xca, 0x39, 0x8e, 0x4a, 0xfd, 0xdf, 0x68, - 0xac, 0x1b, 0x34, 0x83, 0x47, 0xf0, 0xd2, 0x65, 0xa1, 0x16, - 0xe5, 0x52, 0x96, 0x21, 0x03, 0xb4, 0x70, 0xc7, 0x8b, 0x3c, - 0xf8, 0x4f, 0x6d, 0xda, 0x1e, 0xa9, 0x5a, 0xed, 0x29, 0x9e, - 0xbc, 0x0b, 0xcf, 0x78, 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, - 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6, - 0x4f, 0xf7, 0x22, 0x9a, 0x95, 0x2d, 0xf8, 0x40, 0xe6, 0x5e, - 0x8b, 0x33, 0x3c, 0x84, 0x51, 0xe9, 0x9e, 0x26, 0xf3, 0x4b, - 0x44, 0xfc, 0x29, 0x91, 0x37, 0x8f, 0x5a, 0xe2, 0xed, 0x55, - 0x80, 0x38, 0xd1, 0x69, 0xbc, 0x04, 0x0b, 0xb3, 0x66, 0xde, - 0x78, 0xc0, 0x15, 0xad, 0xa2, 0x1a, 0xcf, 0x77, 0x21, 0x99, - 0x4c, 0xf4, 0xfb, 0x43, 0x96, 0x2e, 0x88, 0x30, 0xe5, 0x5d, - 0x52, 0xea, 0x3f, 0x87, 0x6e, 0xd6, 0x03, 0xbb, 0xb4, 0x0c, - 0xd9, 0x61, 0xc7, 0x7f, 0xaa, 0x12, 0x1d, 0xa5, 0x70, 0xc8, - 0xbf, 0x07, 0xd2, 0x6a, 0x65, 0xdd, 0x08, 0xb0, 0x16, 0xae, - 0x7b, 0xc3, 0xcc, 0x74, 0xa1, 0x19, 0xf0, 0x48, 0x9d, 0x25, - 0x2a, 0x92, 0x47, 0xff, 0x59, 0xe1, 0x34, 0x8c, 0x83, 0x3b, - 0xee, 0x56, 0x42, 0xfa, 0x2f, 0x97, 0x98, 0x20, 0xf5, 0x4d, - 0xeb, 0x53, 0x86, 0x3e, 0x31, 0x89, 0x5c, 0xe4, 0x0d, 0xb5, - 0x60, 0xd8, 0xd7, 0x6f, 0xba, 0x02, 0xa4, 0x1c, 0xc9, 0x71, - 0x7e, 0xc6, 0x13, 0xab, 0xdc, 0x64, 0xb1, 0x09, 0x06, 0xbe, - 0x6b, 0xd3, 0x75, 0xcd, 0x18, 0xa0, 0xaf, 0x17, 0xc2, 0x7a, - 0x93, 0x2b, 0xfe, 0x46, 0x49, 0xf1, 0x24, 0x9c, 0x3a, 0x82, - 0x57, 0xef, 0xe0, 0x58, 0x8d, 0x35, 0x63, 0xdb, 0x0e, 0xb6, - 0xb9, 0x01, 0xd4, 0x6c, 0xca, 0x72, 0xa7, 0x1f, 0x10, 0xa8, - 0x7d, 0xc5, 0x2c, 0x94, 0x41, 0xf9, 0xf6, 0x4e, 0x9b, 0x23, - 0x85, 0x3d, 0xe8, 0x50, 0x5f, 0xe7, 0x32, 0x8a, 0xfd, 0x45, - 0x90, 0x28, 0x27, 0x9f, 0x4a, 0xf2, 0x54, 0xec, 0x39, 0x81, - 0x8e, 0x36, 0xe3, 0x5b, 0xb2, 0x0a, 0xdf, 0x67, 0x68, 0xd0, - 0x05, 0xbd, 0x1b, 0xa3, 0x76, 0xce, 0xc1, 0x79, 0xac, 0x14, - 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, - 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9, 0x5f, 0xe6, 0x30, 0x89, - 0x81, 0x38, 0xee, 0x57, 0xfe, 0x47, 0x91, 0x28, 0x20, 0x99, - 0x4f, 0xf6, 0xbe, 0x07, 0xd1, 0x68, 0x60, 0xd9, 0x0f, 0xb6, - 0x1f, 0xa6, 0x70, 0xc9, 0xc1, 0x78, 0xae, 0x17, 0xe1, 0x58, - 0x8e, 0x37, 0x3f, 0x86, 0x50, 0xe9, 0x40, 0xf9, 0x2f, 0x96, - 0x9e, 0x27, 0xf1, 0x48, 0x61, 0xd8, 0x0e, 0xb7, 0xbf, 0x06, - 0xd0, 0x69, 0xc0, 0x79, 0xaf, 0x16, 0x1e, 0xa7, 0x71, 0xc8, - 0x3e, 0x87, 0x51, 0xe8, 0xe0, 0x59, 0x8f, 0x36, 0x9f, 0x26, - 0xf0, 0x49, 0x41, 0xf8, 0x2e, 0x97, 0xdf, 0x66, 0xb0, 0x09, - 0x01, 0xb8, 0x6e, 0xd7, 0x7e, 0xc7, 0x11, 0xa8, 0xa0, 0x19, - 0xcf, 0x76, 0x80, 0x39, 0xef, 0x56, 0x5e, 0xe7, 0x31, 0x88, - 0x21, 0x98, 0x4e, 0xf7, 0xff, 0x46, 0x90, 0x29, 0xc2, 0x7b, - 0xad, 0x14, 0x1c, 0xa5, 0x73, 0xca, 0x63, 0xda, 0x0c, 0xb5, - 0xbd, 0x04, 0xd2, 0x6b, 0x9d, 0x24, 0xf2, 0x4b, 0x43, 0xfa, - 0x2c, 0x95, 0x3c, 0x85, 0x53, 0xea, 0xe2, 0x5b, 0x8d, 0x34, - 0x7c, 0xc5, 0x13, 0xaa, 0xa2, 0x1b, 0xcd, 0x74, 0xdd, 0x64, - 0xb2, 0x0b, 0x03, 0xba, 0x6c, 0xd5, 0x23, 0x9a, 0x4c, 0xf5, - 0xfd, 0x44, 0x92, 0x2b, 0x82, 0x3b, 0xed, 0x54, 0x5c, 0xe5, - 0x33, 0x8a, 0xa3, 0x1a, 0xcc, 0x75, 0x7d, 0xc4, 0x12, 0xab, - 0x02, 0xbb, 0x6d, 0xd4, 0xdc, 0x65, 0xb3, 0x0a, 0xfc, 0x45, - 0x93, 0x2a, 0x22, 0x9b, 0x4d, 0xf4, 0x5d, 0xe4, 0x32, 0x8b, - 0x83, 0x3a, 0xec, 0x55, 0x1d, 0xa4, 0x72, 0xcb, 0xc3, 0x7a, - 0xac, 0x15, 0xbc, 0x05, 0xd3, 0x6a, 0x62, 0xdb, 0x0d, 0xb4, - 0x42, 0xfb, 0x2d, 0x94, 0x9c, 0x25, 0xf3, 0x4a, 0xe3, 0x5a, - 0x8c, 0x35, 0x3d, 0x84, 0x52, 0xeb, 0x00, 0xba, 0x69, 0xd3, - 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, - 0x02, 0xb8, 0x6f, 0xd5, 0x06, 0xbc, 0xbd, 0x07, 0xd4, 0x6e, - 0xd6, 0x6c, 0xbf, 0x05, 0x04, 0xbe, 0x6d, 0xd7, 0xde, 0x64, - 0xb7, 0x0d, 0x0c, 0xb6, 0x65, 0xdf, 0x67, 0xdd, 0x0e, 0xb4, - 0xb5, 0x0f, 0xdc, 0x66, 0xb1, 0x0b, 0xd8, 0x62, 0x63, 0xd9, - 0x0a, 0xb0, 0x08, 0xb2, 0x61, 0xdb, 0xda, 0x60, 0xb3, 0x09, - 0xa1, 0x1b, 0xc8, 0x72, 0x73, 0xc9, 0x1a, 0xa0, 0x18, 0xa2, - 0x71, 0xcb, 0xca, 0x70, 0xa3, 0x19, 0xce, 0x74, 0xa7, 0x1d, - 0x1c, 0xa6, 0x75, 0xcf, 0x77, 0xcd, 0x1e, 0xa4, 0xa5, 0x1f, - 0xcc, 0x76, 0x7f, 0xc5, 0x16, 0xac, 0xad, 0x17, 0xc4, 0x7e, - 0xc6, 0x7c, 0xaf, 0x15, 0x14, 0xae, 0x7d, 0xc7, 0x10, 0xaa, - 0x79, 0xc3, 0xc2, 0x78, 0xab, 0x11, 0xa9, 0x13, 0xc0, 0x7a, - 0x7b, 0xc1, 0x12, 0xa8, 0x5f, 0xe5, 0x36, 0x8c, 0x8d, 0x37, - 0xe4, 0x5e, 0xe6, 0x5c, 0x8f, 0x35, 0x34, 0x8e, 0x5d, 0xe7, - 0x30, 0x8a, 0x59, 0xe3, 0xe2, 0x58, 0x8b, 0x31, 0x89, 0x33, - 0xe0, 0x5a, 0x5b, 0xe1, 0x32, 0x88, 0x81, 0x3b, 0xe8, 0x52, - 0x53, 0xe9, 0x3a, 0x80, 0x38, 0x82, 0x51, 0xeb, 0xea, 0x50, - 0x83, 0x39, 0xee, 0x54, 0x87, 0x3d, 0x3c, 0x86, 0x55, 0xef, - 0x57, 0xed, 0x3e, 0x84, 0x85, 0x3f, 0xec, 0x56, 0xfe, 0x44, - 0x97, 0x2d, 0x2c, 0x96, 0x45, 0xff, 0x47, 0xfd, 0x2e, 0x94, - 0x95, 0x2f, 0xfc, 0x46, 0x91, 0x2b, 0xf8, 0x42, 0x43, 0xf9, - 0x2a, 0x90, 0x28, 0x92, 0x41, 0xfb, 0xfa, 0x40, 0x93, 0x29, - 0x20, 0x9a, 0x49, 0xf3, 0xf2, 0x48, 0x9b, 0x21, 0x99, 0x23, - 0xf0, 0x4a, 0x4b, 0xf1, 0x22, 0x98, 0x4f, 0xf5, 0x26, 0x9c, - 0x9d, 0x27, 0xf4, 0x4e, 0xf6, 0x4c, 0x9f, 0x25, 0x24, 0x9e, - 0x4d, 0xf7, 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, - 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7, 0x7f, 0xc4, - 0x14, 0xaf, 0xa9, 0x12, 0xc2, 0x79, 0xce, 0x75, 0xa5, 0x1e, - 0x18, 0xa3, 0x73, 0xc8, 0xfe, 0x45, 0x95, 0x2e, 0x28, 0x93, - 0x43, 0xf8, 0x4f, 0xf4, 0x24, 0x9f, 0x99, 0x22, 0xf2, 0x49, - 0x81, 0x3a, 0xea, 0x51, 0x57, 0xec, 0x3c, 0x87, 0x30, 0x8b, - 0x5b, 0xe0, 0xe6, 0x5d, 0x8d, 0x36, 0xe1, 0x5a, 0x8a, 0x31, - 0x37, 0x8c, 0x5c, 0xe7, 0x50, 0xeb, 0x3b, 0x80, 0x86, 0x3d, - 0xed, 0x56, 0x9e, 0x25, 0xf5, 0x4e, 0x48, 0xf3, 0x23, 0x98, - 0x2f, 0x94, 0x44, 0xff, 0xf9, 0x42, 0x92, 0x29, 0x1f, 0xa4, - 0x74, 0xcf, 0xc9, 0x72, 0xa2, 0x19, 0xae, 0x15, 0xc5, 0x7e, - 0x78, 0xc3, 0x13, 0xa8, 0x60, 0xdb, 0x0b, 0xb0, 0xb6, 0x0d, - 0xdd, 0x66, 0xd1, 0x6a, 0xba, 0x01, 0x07, 0xbc, 0x6c, 0xd7, - 0xdf, 0x64, 0xb4, 0x0f, 0x09, 0xb2, 0x62, 0xd9, 0x6e, 0xd5, - 0x05, 0xbe, 0xb8, 0x03, 0xd3, 0x68, 0xa0, 0x1b, 0xcb, 0x70, - 0x76, 0xcd, 0x1d, 0xa6, 0x11, 0xaa, 0x7a, 0xc1, 0xc7, 0x7c, - 0xac, 0x17, 0x21, 0x9a, 0x4a, 0xf1, 0xf7, 0x4c, 0x9c, 0x27, - 0x90, 0x2b, 0xfb, 0x40, 0x46, 0xfd, 0x2d, 0x96, 0x5e, 0xe5, - 0x35, 0x8e, 0x88, 0x33, 0xe3, 0x58, 0xef, 0x54, 0x84, 0x3f, - 0x39, 0x82, 0x52, 0xe9, 0x3e, 0x85, 0x55, 0xee, 0xe8, 0x53, - 0x83, 0x38, 0x8f, 0x34, 0xe4, 0x5f, 0x59, 0xe2, 0x32, 0x89, - 0x41, 0xfa, 0x2a, 0x91, 0x97, 0x2c, 0xfc, 0x47, 0xf0, 0x4b, - 0x9b, 0x20, 0x26, 0x9d, 0x4d, 0xf6, 0xc0, 0x7b, 0xab, 0x10, - 0x16, 0xad, 0x7d, 0xc6, 0x71, 0xca, 0x1a, 0xa1, 0xa7, 0x1c, - 0xcc, 0x77, 0xbf, 0x04, 0xd4, 0x6f, 0x69, 0xd2, 0x02, 0xb9, - 0x0e, 0xb5, 0x65, 0xde, 0xd8, 0x63, 0xb3, 0x08, 0x00, 0xbc, - 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, - 0x43, 0xff, 0x26, 0x9a, 0x0f, 0xb3, 0x6a, 0xd6, 0xc5, 0x79, - 0xa0, 0x1c, 0x86, 0x3a, 0xe3, 0x5f, 0x4c, 0xf0, 0x29, 0x95, - 0x1e, 0xa2, 0x7b, 0xc7, 0xd4, 0x68, 0xb1, 0x0d, 0x97, 0x2b, - 0xf2, 0x4e, 0x5d, 0xe1, 0x38, 0x84, 0x11, 0xad, 0x74, 0xc8, - 0xdb, 0x67, 0xbe, 0x02, 0x98, 0x24, 0xfd, 0x41, 0x52, 0xee, - 0x37, 0x8b, 0x3c, 0x80, 0x59, 0xe5, 0xf6, 0x4a, 0x93, 0x2f, - 0xb5, 0x09, 0xd0, 0x6c, 0x7f, 0xc3, 0x1a, 0xa6, 0x33, 0x8f, - 0x56, 0xea, 0xf9, 0x45, 0x9c, 0x20, 0xba, 0x06, 0xdf, 0x63, - 0x70, 0xcc, 0x15, 0xa9, 0x22, 0x9e, 0x47, 0xfb, 0xe8, 0x54, - 0x8d, 0x31, 0xab, 0x17, 0xce, 0x72, 0x61, 0xdd, 0x04, 0xb8, - 0x2d, 0x91, 0x48, 0xf4, 0xe7, 0x5b, 0x82, 0x3e, 0xa4, 0x18, - 0xc1, 0x7d, 0x6e, 0xd2, 0x0b, 0xb7, 0x78, 0xc4, 0x1d, 0xa1, - 0xb2, 0x0e, 0xd7, 0x6b, 0xf1, 0x4d, 0x94, 0x28, 0x3b, 0x87, - 0x5e, 0xe2, 0x77, 0xcb, 0x12, 0xae, 0xbd, 0x01, 0xd8, 0x64, - 0xfe, 0x42, 0x9b, 0x27, 0x34, 0x88, 0x51, 0xed, 0x66, 0xda, - 0x03, 0xbf, 0xac, 0x10, 0xc9, 0x75, 0xef, 0x53, 0x8a, 0x36, - 0x25, 0x99, 0x40, 0xfc, 0x69, 0xd5, 0x0c, 0xb0, 0xa3, 0x1f, - 0xc6, 0x7a, 0xe0, 0x5c, 0x85, 0x39, 0x2a, 0x96, 0x4f, 0xf3, - 0x44, 0xf8, 0x21, 0x9d, 0x8e, 0x32, 0xeb, 0x57, 0xcd, 0x71, - 0xa8, 0x14, 0x07, 0xbb, 0x62, 0xde, 0x4b, 0xf7, 0x2e, 0x92, - 0x81, 0x3d, 0xe4, 0x58, 0xc2, 0x7e, 0xa7, 0x1b, 0x08, 0xb4, - 0x6d, 0xd1, 0x5a, 0xe6, 0x3f, 0x83, 0x90, 0x2c, 0xf5, 0x49, - 0xd3, 0x6f, 0xb6, 0x0a, 0x19, 0xa5, 0x7c, 0xc0, 0x55, 0xe9, - 0x30, 0x8c, 0x9f, 0x23, 0xfa, 0x46, 0xdc, 0x60, 0xb9, 0x05, - 0x16, 0xaa, 0x73, 0xcf, 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, - 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95, - 0x1f, 0xa2, 0x78, 0xc5, 0xd1, 0x6c, 0xb6, 0x0b, 0x9e, 0x23, - 0xf9, 0x44, 0x50, 0xed, 0x37, 0x8a, 0x3e, 0x83, 0x59, 0xe4, - 0xf0, 0x4d, 0x97, 0x2a, 0xbf, 0x02, 0xd8, 0x65, 0x71, 0xcc, - 0x16, 0xab, 0x21, 0x9c, 0x46, 0xfb, 0xef, 0x52, 0x88, 0x35, - 0xa0, 0x1d, 0xc7, 0x7a, 0x6e, 0xd3, 0x09, 0xb4, 0x7c, 0xc1, - 0x1b, 0xa6, 0xb2, 0x0f, 0xd5, 0x68, 0xfd, 0x40, 0x9a, 0x27, - 0x33, 0x8e, 0x54, 0xe9, 0x63, 0xde, 0x04, 0xb9, 0xad, 0x10, - 0xca, 0x77, 0xe2, 0x5f, 0x85, 0x38, 0x2c, 0x91, 0x4b, 0xf6, - 0x42, 0xff, 0x25, 0x98, 0x8c, 0x31, 0xeb, 0x56, 0xc3, 0x7e, - 0xa4, 0x19, 0x0d, 0xb0, 0x6a, 0xd7, 0x5d, 0xe0, 0x3a, 0x87, - 0x93, 0x2e, 0xf4, 0x49, 0xdc, 0x61, 0xbb, 0x06, 0x12, 0xaf, - 0x75, 0xc8, 0xf8, 0x45, 0x9f, 0x22, 0x36, 0x8b, 0x51, 0xec, - 0x79, 0xc4, 0x1e, 0xa3, 0xb7, 0x0a, 0xd0, 0x6d, 0xe7, 0x5a, - 0x80, 0x3d, 0x29, 0x94, 0x4e, 0xf3, 0x66, 0xdb, 0x01, 0xbc, - 0xa8, 0x15, 0xcf, 0x72, 0xc6, 0x7b, 0xa1, 0x1c, 0x08, 0xb5, - 0x6f, 0xd2, 0x47, 0xfa, 0x20, 0x9d, 0x89, 0x34, 0xee, 0x53, - 0xd9, 0x64, 0xbe, 0x03, 0x17, 0xaa, 0x70, 0xcd, 0x58, 0xe5, - 0x3f, 0x82, 0x96, 0x2b, 0xf1, 0x4c, 0x84, 0x39, 0xe3, 0x5e, - 0x4a, 0xf7, 0x2d, 0x90, 0x05, 0xb8, 0x62, 0xdf, 0xcb, 0x76, - 0xac, 0x11, 0x9b, 0x26, 0xfc, 0x41, 0x55, 0xe8, 0x32, 0x8f, - 0x1a, 0xa7, 0x7d, 0xc0, 0xd4, 0x69, 0xb3, 0x0e, 0xba, 0x07, - 0xdd, 0x60, 0x74, 0xc9, 0x13, 0xae, 0x3b, 0x86, 0x5c, 0xe1, - 0xf5, 0x48, 0x92, 0x2f, 0xa5, 0x18, 0xc2, 0x7f, 0x6b, 0xd6, - 0x0c, 0xb1, 0x24, 0x99, 0x43, 0xfe, 0xea, 0x57, 0x8d, 0x30, - 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, - 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84, 0x2f, 0x91, 0x4e, 0xf0, - 0xed, 0x53, 0x8c, 0x32, 0xb6, 0x08, 0xd7, 0x69, 0x74, 0xca, - 0x15, 0xab, 0x5e, 0xe0, 0x3f, 0x81, 0x9c, 0x22, 0xfd, 0x43, - 0xc7, 0x79, 0xa6, 0x18, 0x05, 0xbb, 0x64, 0xda, 0x71, 0xcf, - 0x10, 0xae, 0xb3, 0x0d, 0xd2, 0x6c, 0xe8, 0x56, 0x89, 0x37, - 0x2a, 0x94, 0x4b, 0xf5, 0xbc, 0x02, 0xdd, 0x63, 0x7e, 0xc0, - 0x1f, 0xa1, 0x25, 0x9b, 0x44, 0xfa, 0xe7, 0x59, 0x86, 0x38, - 0x93, 0x2d, 0xf2, 0x4c, 0x51, 0xef, 0x30, 0x8e, 0x0a, 0xb4, - 0x6b, 0xd5, 0xc8, 0x76, 0xa9, 0x17, 0xe2, 0x5c, 0x83, 0x3d, - 0x20, 0x9e, 0x41, 0xff, 0x7b, 0xc5, 0x1a, 0xa4, 0xb9, 0x07, - 0xd8, 0x66, 0xcd, 0x73, 0xac, 0x12, 0x0f, 0xb1, 0x6e, 0xd0, - 0x54, 0xea, 0x35, 0x8b, 0x96, 0x28, 0xf7, 0x49, 0x65, 0xdb, - 0x04, 0xba, 0xa7, 0x19, 0xc6, 0x78, 0xfc, 0x42, 0x9d, 0x23, - 0x3e, 0x80, 0x5f, 0xe1, 0x4a, 0xf4, 0x2b, 0x95, 0x88, 0x36, - 0xe9, 0x57, 0xd3, 0x6d, 0xb2, 0x0c, 0x11, 0xaf, 0x70, 0xce, - 0x3b, 0x85, 0x5a, 0xe4, 0xf9, 0x47, 0x98, 0x26, 0xa2, 0x1c, - 0xc3, 0x7d, 0x60, 0xde, 0x01, 0xbf, 0x14, 0xaa, 0x75, 0xcb, - 0xd6, 0x68, 0xb7, 0x09, 0x8d, 0x33, 0xec, 0x52, 0x4f, 0xf1, - 0x2e, 0x90, 0xd9, 0x67, 0xb8, 0x06, 0x1b, 0xa5, 0x7a, 0xc4, - 0x40, 0xfe, 0x21, 0x9f, 0x82, 0x3c, 0xe3, 0x5d, 0xf6, 0x48, - 0x97, 0x29, 0x34, 0x8a, 0x55, 0xeb, 0x6f, 0xd1, 0x0e, 0xb0, - 0xad, 0x13, 0xcc, 0x72, 0x87, 0x39, 0xe6, 0x58, 0x45, 0xfb, - 0x24, 0x9a, 0x1e, 0xa0, 0x7f, 0xc1, 0xdc, 0x62, 0xbd, 0x03, - 0xa8, 0x16, 0xc9, 0x77, 0x6a, 0xd4, 0x0b, 0xb5, 0x31, 0x8f, - 0x50, 0xee, 0xf3, 0x4d, 0x92, 0x2c, 0x00, 0xbf, 0x63, 0xdc, - 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, - 0x34, 0x8b, 0x3f, 0x80, 0x5c, 0xe3, 0xf9, 0x46, 0x9a, 0x25, - 0xae, 0x11, 0xcd, 0x72, 0x68, 0xd7, 0x0b, 0xb4, 0x7e, 0xc1, - 0x1d, 0xa2, 0xb8, 0x07, 0xdb, 0x64, 0xef, 0x50, 0x8c, 0x33, - 0x29, 0x96, 0x4a, 0xf5, 0x41, 0xfe, 0x22, 0x9d, 0x87, 0x38, - 0xe4, 0x5b, 0xd0, 0x6f, 0xb3, 0x0c, 0x16, 0xa9, 0x75, 0xca, - 0xfc, 0x43, 0x9f, 0x20, 0x3a, 0x85, 0x59, 0xe6, 0x6d, 0xd2, - 0x0e, 0xb1, 0xab, 0x14, 0xc8, 0x77, 0xc3, 0x7c, 0xa0, 0x1f, - 0x05, 0xba, 0x66, 0xd9, 0x52, 0xed, 0x31, 0x8e, 0x94, 0x2b, - 0xf7, 0x48, 0x82, 0x3d, 0xe1, 0x5e, 0x44, 0xfb, 0x27, 0x98, - 0x13, 0xac, 0x70, 0xcf, 0xd5, 0x6a, 0xb6, 0x09, 0xbd, 0x02, - 0xde, 0x61, 0x7b, 0xc4, 0x18, 0xa7, 0x2c, 0x93, 0x4f, 0xf0, - 0xea, 0x55, 0x89, 0x36, 0xe5, 0x5a, 0x86, 0x39, 0x23, 0x9c, - 0x40, 0xff, 0x74, 0xcb, 0x17, 0xa8, 0xb2, 0x0d, 0xd1, 0x6e, - 0xda, 0x65, 0xb9, 0x06, 0x1c, 0xa3, 0x7f, 0xc0, 0x4b, 0xf4, - 0x28, 0x97, 0x8d, 0x32, 0xee, 0x51, 0x9b, 0x24, 0xf8, 0x47, - 0x5d, 0xe2, 0x3e, 0x81, 0x0a, 0xb5, 0x69, 0xd6, 0xcc, 0x73, - 0xaf, 0x10, 0xa4, 0x1b, 0xc7, 0x78, 0x62, 0xdd, 0x01, 0xbe, - 0x35, 0x8a, 0x56, 0xe9, 0xf3, 0x4c, 0x90, 0x2f, 0x19, 0xa6, - 0x7a, 0xc5, 0xdf, 0x60, 0xbc, 0x03, 0x88, 0x37, 0xeb, 0x54, - 0x4e, 0xf1, 0x2d, 0x92, 0x26, 0x99, 0x45, 0xfa, 0xe0, 0x5f, - 0x83, 0x3c, 0xb7, 0x08, 0xd4, 0x6b, 0x71, 0xce, 0x12, 0xad, - 0x67, 0xd8, 0x04, 0xbb, 0xa1, 0x1e, 0xc2, 0x7d, 0xf6, 0x49, - 0x95, 0x2a, 0x30, 0x8f, 0x53, 0xec, 0x58, 0xe7, 0x3b, 0x84, - 0x9e, 0x21, 0xfd, 0x42, 0xc9, 0x76, 0xaa, 0x15, 0x0f, 0xb0, - 0x6c, 0xd3, 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, - 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34, 0x9c, 0x5c, - 0x01, 0xc1, 0xbb, 0x7b, 0x26, 0xe6, 0xd2, 0x12, 0x4f, 0x8f, - 0xf5, 0x35, 0x68, 0xa8, 0x25, 0xe5, 0xb8, 0x78, 0x02, 0xc2, - 0x9f, 0x5f, 0x6b, 0xab, 0xf6, 0x36, 0x4c, 0x8c, 0xd1, 0x11, - 0xb9, 0x79, 0x24, 0xe4, 0x9e, 0x5e, 0x03, 0xc3, 0xf7, 0x37, - 0x6a, 0xaa, 0xd0, 0x10, 0x4d, 0x8d, 0x4a, 0x8a, 0xd7, 0x17, - 0x6d, 0xad, 0xf0, 0x30, 0x04, 0xc4, 0x99, 0x59, 0x23, 0xe3, - 0xbe, 0x7e, 0xd6, 0x16, 0x4b, 0x8b, 0xf1, 0x31, 0x6c, 0xac, - 0x98, 0x58, 0x05, 0xc5, 0xbf, 0x7f, 0x22, 0xe2, 0x6f, 0xaf, - 0xf2, 0x32, 0x48, 0x88, 0xd5, 0x15, 0x21, 0xe1, 0xbc, 0x7c, - 0x06, 0xc6, 0x9b, 0x5b, 0xf3, 0x33, 0x6e, 0xae, 0xd4, 0x14, - 0x49, 0x89, 0xbd, 0x7d, 0x20, 0xe0, 0x9a, 0x5a, 0x07, 0xc7, - 0x94, 0x54, 0x09, 0xc9, 0xb3, 0x73, 0x2e, 0xee, 0xda, 0x1a, - 0x47, 0x87, 0xfd, 0x3d, 0x60, 0xa0, 0x08, 0xc8, 0x95, 0x55, - 0x2f, 0xef, 0xb2, 0x72, 0x46, 0x86, 0xdb, 0x1b, 0x61, 0xa1, - 0xfc, 0x3c, 0xb1, 0x71, 0x2c, 0xec, 0x96, 0x56, 0x0b, 0xcb, - 0xff, 0x3f, 0x62, 0xa2, 0xd8, 0x18, 0x45, 0x85, 0x2d, 0xed, - 0xb0, 0x70, 0x0a, 0xca, 0x97, 0x57, 0x63, 0xa3, 0xfe, 0x3e, - 0x44, 0x84, 0xd9, 0x19, 0xde, 0x1e, 0x43, 0x83, 0xf9, 0x39, - 0x64, 0xa4, 0x90, 0x50, 0x0d, 0xcd, 0xb7, 0x77, 0x2a, 0xea, - 0x42, 0x82, 0xdf, 0x1f, 0x65, 0xa5, 0xf8, 0x38, 0x0c, 0xcc, - 0x91, 0x51, 0x2b, 0xeb, 0xb6, 0x76, 0xfb, 0x3b, 0x66, 0xa6, - 0xdc, 0x1c, 0x41, 0x81, 0xb5, 0x75, 0x28, 0xe8, 0x92, 0x52, - 0x0f, 0xcf, 0x67, 0xa7, 0xfa, 0x3a, 0x40, 0x80, 0xdd, 0x1d, - 0x29, 0xe9, 0xb4, 0x74, 0x0e, 0xce, 0x93, 0x53, 0x00, 0xc1, - 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, - 0x65, 0xa4, 0xfa, 0x3b, 0x8c, 0x4d, 0x13, 0xd2, 0xaf, 0x6e, - 0x30, 0xf1, 0xca, 0x0b, 0x55, 0x94, 0xe9, 0x28, 0x76, 0xb7, - 0x05, 0xc4, 0x9a, 0x5b, 0x26, 0xe7, 0xb9, 0x78, 0x43, 0x82, - 0xdc, 0x1d, 0x60, 0xa1, 0xff, 0x3e, 0x89, 0x48, 0x16, 0xd7, - 0xaa, 0x6b, 0x35, 0xf4, 0xcf, 0x0e, 0x50, 0x91, 0xec, 0x2d, - 0x73, 0xb2, 0x0a, 0xcb, 0x95, 0x54, 0x29, 0xe8, 0xb6, 0x77, - 0x4c, 0x8d, 0xd3, 0x12, 0x6f, 0xae, 0xf0, 0x31, 0x86, 0x47, - 0x19, 0xd8, 0xa5, 0x64, 0x3a, 0xfb, 0xc0, 0x01, 0x5f, 0x9e, - 0xe3, 0x22, 0x7c, 0xbd, 0x0f, 0xce, 0x90, 0x51, 0x2c, 0xed, - 0xb3, 0x72, 0x49, 0x88, 0xd6, 0x17, 0x6a, 0xab, 0xf5, 0x34, - 0x83, 0x42, 0x1c, 0xdd, 0xa0, 0x61, 0x3f, 0xfe, 0xc5, 0x04, - 0x5a, 0x9b, 0xe6, 0x27, 0x79, 0xb8, 0x14, 0xd5, 0x8b, 0x4a, - 0x37, 0xf6, 0xa8, 0x69, 0x52, 0x93, 0xcd, 0x0c, 0x71, 0xb0, - 0xee, 0x2f, 0x98, 0x59, 0x07, 0xc6, 0xbb, 0x7a, 0x24, 0xe5, - 0xde, 0x1f, 0x41, 0x80, 0xfd, 0x3c, 0x62, 0xa3, 0x11, 0xd0, - 0x8e, 0x4f, 0x32, 0xf3, 0xad, 0x6c, 0x57, 0x96, 0xc8, 0x09, - 0x74, 0xb5, 0xeb, 0x2a, 0x9d, 0x5c, 0x02, 0xc3, 0xbe, 0x7f, - 0x21, 0xe0, 0xdb, 0x1a, 0x44, 0x85, 0xf8, 0x39, 0x67, 0xa6, - 0x1e, 0xdf, 0x81, 0x40, 0x3d, 0xfc, 0xa2, 0x63, 0x58, 0x99, - 0xc7, 0x06, 0x7b, 0xba, 0xe4, 0x25, 0x92, 0x53, 0x0d, 0xcc, - 0xb1, 0x70, 0x2e, 0xef, 0xd4, 0x15, 0x4b, 0x8a, 0xf7, 0x36, - 0x68, 0xa9, 0x1b, 0xda, 0x84, 0x45, 0x38, 0xf9, 0xa7, 0x66, - 0x5d, 0x9c, 0xc2, 0x03, 0x7e, 0xbf, 0xe1, 0x20, 0x97, 0x56, - 0x08, 0xc9, 0xb4, 0x75, 0x2b, 0xea, 0xd1, 0x10, 0x4e, 0x8f, - 0xf2, 0x33, 0x6d, 0xac, 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, - 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a, - 0xbc, 0x7e, 0x25, 0xe7, 0x93, 0x51, 0x0a, 0xc8, 0xe2, 0x20, - 0x7b, 0xb9, 0xcd, 0x0f, 0x54, 0x96, 0x65, 0xa7, 0xfc, 0x3e, - 0x4a, 0x88, 0xd3, 0x11, 0x3b, 0xf9, 0xa2, 0x60, 0x14, 0xd6, - 0x8d, 0x4f, 0xd9, 0x1b, 0x40, 0x82, 0xf6, 0x34, 0x6f, 0xad, - 0x87, 0x45, 0x1e, 0xdc, 0xa8, 0x6a, 0x31, 0xf3, 0xca, 0x08, - 0x53, 0x91, 0xe5, 0x27, 0x7c, 0xbe, 0x94, 0x56, 0x0d, 0xcf, - 0xbb, 0x79, 0x22, 0xe0, 0x76, 0xb4, 0xef, 0x2d, 0x59, 0x9b, - 0xc0, 0x02, 0x28, 0xea, 0xb1, 0x73, 0x07, 0xc5, 0x9e, 0x5c, - 0xaf, 0x6d, 0x36, 0xf4, 0x80, 0x42, 0x19, 0xdb, 0xf1, 0x33, - 0x68, 0xaa, 0xde, 0x1c, 0x47, 0x85, 0x13, 0xd1, 0x8a, 0x48, - 0x3c, 0xfe, 0xa5, 0x67, 0x4d, 0x8f, 0xd4, 0x16, 0x62, 0xa0, - 0xfb, 0x39, 0x89, 0x4b, 0x10, 0xd2, 0xa6, 0x64, 0x3f, 0xfd, - 0xd7, 0x15, 0x4e, 0x8c, 0xf8, 0x3a, 0x61, 0xa3, 0x35, 0xf7, - 0xac, 0x6e, 0x1a, 0xd8, 0x83, 0x41, 0x6b, 0xa9, 0xf2, 0x30, - 0x44, 0x86, 0xdd, 0x1f, 0xec, 0x2e, 0x75, 0xb7, 0xc3, 0x01, - 0x5a, 0x98, 0xb2, 0x70, 0x2b, 0xe9, 0x9d, 0x5f, 0x04, 0xc6, - 0x50, 0x92, 0xc9, 0x0b, 0x7f, 0xbd, 0xe6, 0x24, 0x0e, 0xcc, - 0x97, 0x55, 0x21, 0xe3, 0xb8, 0x7a, 0x43, 0x81, 0xda, 0x18, - 0x6c, 0xae, 0xf5, 0x37, 0x1d, 0xdf, 0x84, 0x46, 0x32, 0xf0, - 0xab, 0x69, 0xff, 0x3d, 0x66, 0xa4, 0xd0, 0x12, 0x49, 0x8b, - 0xa1, 0x63, 0x38, 0xfa, 0x8e, 0x4c, 0x17, 0xd5, 0x26, 0xe4, - 0xbf, 0x7d, 0x09, 0xcb, 0x90, 0x52, 0x78, 0xba, 0xe1, 0x23, - 0x57, 0x95, 0xce, 0x0c, 0x9a, 0x58, 0x03, 0xc1, 0xb5, 0x77, - 0x2c, 0xee, 0xc4, 0x06, 0x5d, 0x9f, 0xeb, 0x29, 0x72, 0xb0, - 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, - 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25, 0xac, 0x6f, 0x37, 0xf4, - 0x87, 0x44, 0x1c, 0xdf, 0xfa, 0x39, 0x61, 0xa2, 0xd1, 0x12, - 0x4a, 0x89, 0x45, 0x86, 0xde, 0x1d, 0x6e, 0xad, 0xf5, 0x36, - 0x13, 0xd0, 0x88, 0x4b, 0x38, 0xfb, 0xa3, 0x60, 0xe9, 0x2a, - 0x72, 0xb1, 0xc2, 0x01, 0x59, 0x9a, 0xbf, 0x7c, 0x24, 0xe7, - 0x94, 0x57, 0x0f, 0xcc, 0x8a, 0x49, 0x11, 0xd2, 0xa1, 0x62, - 0x3a, 0xf9, 0xdc, 0x1f, 0x47, 0x84, 0xf7, 0x34, 0x6c, 0xaf, - 0x26, 0xe5, 0xbd, 0x7e, 0x0d, 0xce, 0x96, 0x55, 0x70, 0xb3, - 0xeb, 0x28, 0x5b, 0x98, 0xc0, 0x03, 0xcf, 0x0c, 0x54, 0x97, - 0xe4, 0x27, 0x7f, 0xbc, 0x99, 0x5a, 0x02, 0xc1, 0xb2, 0x71, - 0x29, 0xea, 0x63, 0xa0, 0xf8, 0x3b, 0x48, 0x8b, 0xd3, 0x10, - 0x35, 0xf6, 0xae, 0x6d, 0x1e, 0xdd, 0x85, 0x46, 0x09, 0xca, - 0x92, 0x51, 0x22, 0xe1, 0xb9, 0x7a, 0x5f, 0x9c, 0xc4, 0x07, - 0x74, 0xb7, 0xef, 0x2c, 0xa5, 0x66, 0x3e, 0xfd, 0x8e, 0x4d, - 0x15, 0xd6, 0xf3, 0x30, 0x68, 0xab, 0xd8, 0x1b, 0x43, 0x80, - 0x4c, 0x8f, 0xd7, 0x14, 0x67, 0xa4, 0xfc, 0x3f, 0x1a, 0xd9, - 0x81, 0x42, 0x31, 0xf2, 0xaa, 0x69, 0xe0, 0x23, 0x7b, 0xb8, - 0xcb, 0x08, 0x50, 0x93, 0xb6, 0x75, 0x2d, 0xee, 0x9d, 0x5e, - 0x06, 0xc5, 0x83, 0x40, 0x18, 0xdb, 0xa8, 0x6b, 0x33, 0xf0, - 0xd5, 0x16, 0x4e, 0x8d, 0xfe, 0x3d, 0x65, 0xa6, 0x2f, 0xec, - 0xb4, 0x77, 0x04, 0xc7, 0x9f, 0x5c, 0x79, 0xba, 0xe2, 0x21, - 0x52, 0x91, 0xc9, 0x0a, 0xc6, 0x05, 0x5d, 0x9e, 0xed, 0x2e, - 0x76, 0xb5, 0x90, 0x53, 0x0b, 0xc8, 0xbb, 0x78, 0x20, 0xe3, - 0x6a, 0xa9, 0xf1, 0x32, 0x41, 0x82, 0xda, 0x19, 0x3c, 0xff, - 0xa7, 0x64, 0x17, 0xd4, 0x8c, 0x4f, 0x00, 0xc4, 0x95, 0x51, - 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, - 0xcc, 0x08, 0xdc, 0x18, 0x49, 0x8d, 0xeb, 0x2f, 0x7e, 0xba, - 0xb2, 0x76, 0x27, 0xe3, 0x85, 0x41, 0x10, 0xd4, 0xa5, 0x61, - 0x30, 0xf4, 0x92, 0x56, 0x07, 0xc3, 0xcb, 0x0f, 0x5e, 0x9a, - 0xfc, 0x38, 0x69, 0xad, 0x79, 0xbd, 0xec, 0x28, 0x4e, 0x8a, - 0xdb, 0x1f, 0x17, 0xd3, 0x82, 0x46, 0x20, 0xe4, 0xb5, 0x71, - 0x57, 0x93, 0xc2, 0x06, 0x60, 0xa4, 0xf5, 0x31, 0x39, 0xfd, - 0xac, 0x68, 0x0e, 0xca, 0x9b, 0x5f, 0x8b, 0x4f, 0x1e, 0xda, - 0xbc, 0x78, 0x29, 0xed, 0xe5, 0x21, 0x70, 0xb4, 0xd2, 0x16, - 0x47, 0x83, 0xf2, 0x36, 0x67, 0xa3, 0xc5, 0x01, 0x50, 0x94, - 0x9c, 0x58, 0x09, 0xcd, 0xab, 0x6f, 0x3e, 0xfa, 0x2e, 0xea, - 0xbb, 0x7f, 0x19, 0xdd, 0x8c, 0x48, 0x40, 0x84, 0xd5, 0x11, - 0x77, 0xb3, 0xe2, 0x26, 0xae, 0x6a, 0x3b, 0xff, 0x99, 0x5d, - 0x0c, 0xc8, 0xc0, 0x04, 0x55, 0x91, 0xf7, 0x33, 0x62, 0xa6, - 0x72, 0xb6, 0xe7, 0x23, 0x45, 0x81, 0xd0, 0x14, 0x1c, 0xd8, - 0x89, 0x4d, 0x2b, 0xef, 0xbe, 0x7a, 0x0b, 0xcf, 0x9e, 0x5a, - 0x3c, 0xf8, 0xa9, 0x6d, 0x65, 0xa1, 0xf0, 0x34, 0x52, 0x96, - 0xc7, 0x03, 0xd7, 0x13, 0x42, 0x86, 0xe0, 0x24, 0x75, 0xb1, - 0xb9, 0x7d, 0x2c, 0xe8, 0x8e, 0x4a, 0x1b, 0xdf, 0xf9, 0x3d, - 0x6c, 0xa8, 0xce, 0x0a, 0x5b, 0x9f, 0x97, 0x53, 0x02, 0xc6, - 0xa0, 0x64, 0x35, 0xf1, 0x25, 0xe1, 0xb0, 0x74, 0x12, 0xd6, - 0x87, 0x43, 0x4b, 0x8f, 0xde, 0x1a, 0x7c, 0xb8, 0xe9, 0x2d, - 0x5c, 0x98, 0xc9, 0x0d, 0x6b, 0xaf, 0xfe, 0x3a, 0x32, 0xf6, - 0xa7, 0x63, 0x05, 0xc1, 0x90, 0x54, 0x80, 0x44, 0x15, 0xd1, - 0xb7, 0x73, 0x22, 0xe6, 0xee, 0x2a, 0x7b, 0xbf, 0xd9, 0x1d, - 0x4c, 0x88, 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, - 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07, 0xcc, 0x09, - 0x5b, 0x9e, 0xff, 0x3a, 0x68, 0xad, 0xaa, 0x6f, 0x3d, 0xf8, - 0x99, 0x5c, 0x0e, 0xcb, 0x85, 0x40, 0x12, 0xd7, 0xb6, 0x73, - 0x21, 0xe4, 0xe3, 0x26, 0x74, 0xb1, 0xd0, 0x15, 0x47, 0x82, - 0x49, 0x8c, 0xde, 0x1b, 0x7a, 0xbf, 0xed, 0x28, 0x2f, 0xea, - 0xb8, 0x7d, 0x1c, 0xd9, 0x8b, 0x4e, 0x17, 0xd2, 0x80, 0x45, - 0x24, 0xe1, 0xb3, 0x76, 0x71, 0xb4, 0xe6, 0x23, 0x42, 0x87, - 0xd5, 0x10, 0xdb, 0x1e, 0x4c, 0x89, 0xe8, 0x2d, 0x7f, 0xba, - 0xbd, 0x78, 0x2a, 0xef, 0x8e, 0x4b, 0x19, 0xdc, 0x92, 0x57, - 0x05, 0xc0, 0xa1, 0x64, 0x36, 0xf3, 0xf4, 0x31, 0x63, 0xa6, - 0xc7, 0x02, 0x50, 0x95, 0x5e, 0x9b, 0xc9, 0x0c, 0x6d, 0xa8, - 0xfa, 0x3f, 0x38, 0xfd, 0xaf, 0x6a, 0x0b, 0xce, 0x9c, 0x59, - 0x2e, 0xeb, 0xb9, 0x7c, 0x1d, 0xd8, 0x8a, 0x4f, 0x48, 0x8d, - 0xdf, 0x1a, 0x7b, 0xbe, 0xec, 0x29, 0xe2, 0x27, 0x75, 0xb0, - 0xd1, 0x14, 0x46, 0x83, 0x84, 0x41, 0x13, 0xd6, 0xb7, 0x72, - 0x20, 0xe5, 0xab, 0x6e, 0x3c, 0xf9, 0x98, 0x5d, 0x0f, 0xca, - 0xcd, 0x08, 0x5a, 0x9f, 0xfe, 0x3b, 0x69, 0xac, 0x67, 0xa2, - 0xf0, 0x35, 0x54, 0x91, 0xc3, 0x06, 0x01, 0xc4, 0x96, 0x53, - 0x32, 0xf7, 0xa5, 0x60, 0x39, 0xfc, 0xae, 0x6b, 0x0a, 0xcf, - 0x9d, 0x58, 0x5f, 0x9a, 0xc8, 0x0d, 0x6c, 0xa9, 0xfb, 0x3e, - 0xf5, 0x30, 0x62, 0xa7, 0xc6, 0x03, 0x51, 0x94, 0x93, 0x56, - 0x04, 0xc1, 0xa0, 0x65, 0x37, 0xf2, 0xbc, 0x79, 0x2b, 0xee, - 0x8f, 0x4a, 0x18, 0xdd, 0xda, 0x1f, 0x4d, 0x88, 0xe9, 0x2c, - 0x7e, 0xbb, 0x70, 0xb5, 0xe7, 0x22, 0x43, 0x86, 0xd4, 0x11, - 0x16, 0xd3, 0x81, 0x44, 0x25, 0xe0, 0xb2, 0x77, 0x00, 0xc6, - 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, - 0x41, 0x87, 0xd0, 0x16, 0xfc, 0x3a, 0x6d, 0xab, 0xc3, 0x05, - 0x52, 0x94, 0x82, 0x44, 0x13, 0xd5, 0xbd, 0x7b, 0x2c, 0xea, - 0xe5, 0x23, 0x74, 0xb2, 0xda, 0x1c, 0x4b, 0x8d, 0x9b, 0x5d, - 0x0a, 0xcc, 0xa4, 0x62, 0x35, 0xf3, 0x19, 0xdf, 0x88, 0x4e, - 0x26, 0xe0, 0xb7, 0x71, 0x67, 0xa1, 0xf6, 0x30, 0x58, 0x9e, - 0xc9, 0x0f, 0xd7, 0x11, 0x46, 0x80, 0xe8, 0x2e, 0x79, 0xbf, - 0xa9, 0x6f, 0x38, 0xfe, 0x96, 0x50, 0x07, 0xc1, 0x2b, 0xed, - 0xba, 0x7c, 0x14, 0xd2, 0x85, 0x43, 0x55, 0x93, 0xc4, 0x02, - 0x6a, 0xac, 0xfb, 0x3d, 0x32, 0xf4, 0xa3, 0x65, 0x0d, 0xcb, - 0x9c, 0x5a, 0x4c, 0x8a, 0xdd, 0x1b, 0x73, 0xb5, 0xe2, 0x24, - 0xce, 0x08, 0x5f, 0x99, 0xf1, 0x37, 0x60, 0xa6, 0xb0, 0x76, - 0x21, 0xe7, 0x8f, 0x49, 0x1e, 0xd8, 0xb3, 0x75, 0x22, 0xe4, - 0x8c, 0x4a, 0x1d, 0xdb, 0xcd, 0x0b, 0x5c, 0x9a, 0xf2, 0x34, - 0x63, 0xa5, 0x4f, 0x89, 0xde, 0x18, 0x70, 0xb6, 0xe1, 0x27, - 0x31, 0xf7, 0xa0, 0x66, 0x0e, 0xc8, 0x9f, 0x59, 0x56, 0x90, - 0xc7, 0x01, 0x69, 0xaf, 0xf8, 0x3e, 0x28, 0xee, 0xb9, 0x7f, - 0x17, 0xd1, 0x86, 0x40, 0xaa, 0x6c, 0x3b, 0xfd, 0x95, 0x53, - 0x04, 0xc2, 0xd4, 0x12, 0x45, 0x83, 0xeb, 0x2d, 0x7a, 0xbc, - 0x64, 0xa2, 0xf5, 0x33, 0x5b, 0x9d, 0xca, 0x0c, 0x1a, 0xdc, - 0x8b, 0x4d, 0x25, 0xe3, 0xb4, 0x72, 0x98, 0x5e, 0x09, 0xcf, - 0xa7, 0x61, 0x36, 0xf0, 0xe6, 0x20, 0x77, 0xb1, 0xd9, 0x1f, - 0x48, 0x8e, 0x81, 0x47, 0x10, 0xd6, 0xbe, 0x78, 0x2f, 0xe9, - 0xff, 0x39, 0x6e, 0xa8, 0xc0, 0x06, 0x51, 0x97, 0x7d, 0xbb, - 0xec, 0x2a, 0x42, 0x84, 0xd3, 0x15, 0x03, 0xc5, 0x92, 0x54, - 0x3c, 0xfa, 0xad, 0x6b, 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, - 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19, - 0xec, 0x2b, 0x7f, 0xb8, 0xd7, 0x10, 0x44, 0x83, 0x9a, 0x5d, - 0x09, 0xce, 0xa1, 0x66, 0x32, 0xf5, 0xc5, 0x02, 0x56, 0x91, - 0xfe, 0x39, 0x6d, 0xaa, 0xb3, 0x74, 0x20, 0xe7, 0x88, 0x4f, - 0x1b, 0xdc, 0x29, 0xee, 0xba, 0x7d, 0x12, 0xd5, 0x81, 0x46, - 0x5f, 0x98, 0xcc, 0x0b, 0x64, 0xa3, 0xf7, 0x30, 0x97, 0x50, - 0x04, 0xc3, 0xac, 0x6b, 0x3f, 0xf8, 0xe1, 0x26, 0x72, 0xb5, - 0xda, 0x1d, 0x49, 0x8e, 0x7b, 0xbc, 0xe8, 0x2f, 0x40, 0x87, - 0xd3, 0x14, 0x0d, 0xca, 0x9e, 0x59, 0x36, 0xf1, 0xa5, 0x62, - 0x52, 0x95, 0xc1, 0x06, 0x69, 0xae, 0xfa, 0x3d, 0x24, 0xe3, - 0xb7, 0x70, 0x1f, 0xd8, 0x8c, 0x4b, 0xbe, 0x79, 0x2d, 0xea, - 0x85, 0x42, 0x16, 0xd1, 0xc8, 0x0f, 0x5b, 0x9c, 0xf3, 0x34, - 0x60, 0xa7, 0x33, 0xf4, 0xa0, 0x67, 0x08, 0xcf, 0x9b, 0x5c, - 0x45, 0x82, 0xd6, 0x11, 0x7e, 0xb9, 0xed, 0x2a, 0xdf, 0x18, - 0x4c, 0x8b, 0xe4, 0x23, 0x77, 0xb0, 0xa9, 0x6e, 0x3a, 0xfd, - 0x92, 0x55, 0x01, 0xc6, 0xf6, 0x31, 0x65, 0xa2, 0xcd, 0x0a, - 0x5e, 0x99, 0x80, 0x47, 0x13, 0xd4, 0xbb, 0x7c, 0x28, 0xef, - 0x1a, 0xdd, 0x89, 0x4e, 0x21, 0xe6, 0xb2, 0x75, 0x6c, 0xab, - 0xff, 0x38, 0x57, 0x90, 0xc4, 0x03, 0xa4, 0x63, 0x37, 0xf0, - 0x9f, 0x58, 0x0c, 0xcb, 0xd2, 0x15, 0x41, 0x86, 0xe9, 0x2e, - 0x7a, 0xbd, 0x48, 0x8f, 0xdb, 0x1c, 0x73, 0xb4, 0xe0, 0x27, - 0x3e, 0xf9, 0xad, 0x6a, 0x05, 0xc2, 0x96, 0x51, 0x61, 0xa6, - 0xf2, 0x35, 0x5a, 0x9d, 0xc9, 0x0e, 0x17, 0xd0, 0x84, 0x43, - 0x2c, 0xeb, 0xbf, 0x78, 0x8d, 0x4a, 0x1e, 0xd9, 0xb6, 0x71, - 0x25, 0xe2, 0xfb, 0x3c, 0x68, 0xaf, 0xc0, 0x07, 0x53, 0x94, - 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, - 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c, 0x1c, 0xd4, 0x91, 0x59, - 0x1b, 0xd3, 0x96, 0x5e, 0x12, 0xda, 0x9f, 0x57, 0x15, 0xdd, - 0x98, 0x50, 0x38, 0xf0, 0xb5, 0x7d, 0x3f, 0xf7, 0xb2, 0x7a, - 0x36, 0xfe, 0xbb, 0x73, 0x31, 0xf9, 0xbc, 0x74, 0x24, 0xec, - 0xa9, 0x61, 0x23, 0xeb, 0xae, 0x66, 0x2a, 0xe2, 0xa7, 0x6f, - 0x2d, 0xe5, 0xa0, 0x68, 0x70, 0xb8, 0xfd, 0x35, 0x77, 0xbf, - 0xfa, 0x32, 0x7e, 0xb6, 0xf3, 0x3b, 0x79, 0xb1, 0xf4, 0x3c, - 0x6c, 0xa4, 0xe1, 0x29, 0x6b, 0xa3, 0xe6, 0x2e, 0x62, 0xaa, - 0xef, 0x27, 0x65, 0xad, 0xe8, 0x20, 0x48, 0x80, 0xc5, 0x0d, - 0x4f, 0x87, 0xc2, 0x0a, 0x46, 0x8e, 0xcb, 0x03, 0x41, 0x89, - 0xcc, 0x04, 0x54, 0x9c, 0xd9, 0x11, 0x53, 0x9b, 0xde, 0x16, - 0x5a, 0x92, 0xd7, 0x1f, 0x5d, 0x95, 0xd0, 0x18, 0xe0, 0x28, - 0x6d, 0xa5, 0xe7, 0x2f, 0x6a, 0xa2, 0xee, 0x26, 0x63, 0xab, - 0xe9, 0x21, 0x64, 0xac, 0xfc, 0x34, 0x71, 0xb9, 0xfb, 0x33, - 0x76, 0xbe, 0xf2, 0x3a, 0x7f, 0xb7, 0xf5, 0x3d, 0x78, 0xb0, - 0xd8, 0x10, 0x55, 0x9d, 0xdf, 0x17, 0x52, 0x9a, 0xd6, 0x1e, - 0x5b, 0x93, 0xd1, 0x19, 0x5c, 0x94, 0xc4, 0x0c, 0x49, 0x81, - 0xc3, 0x0b, 0x4e, 0x86, 0xca, 0x02, 0x47, 0x8f, 0xcd, 0x05, - 0x40, 0x88, 0x90, 0x58, 0x1d, 0xd5, 0x97, 0x5f, 0x1a, 0xd2, - 0x9e, 0x56, 0x13, 0xdb, 0x99, 0x51, 0x14, 0xdc, 0x8c, 0x44, - 0x01, 0xc9, 0x8b, 0x43, 0x06, 0xce, 0x82, 0x4a, 0x0f, 0xc7, - 0x85, 0x4d, 0x08, 0xc0, 0xa8, 0x60, 0x25, 0xed, 0xaf, 0x67, - 0x22, 0xea, 0xa6, 0x6e, 0x2b, 0xe3, 0xa1, 0x69, 0x2c, 0xe4, - 0xb4, 0x7c, 0x39, 0xf1, 0xb3, 0x7b, 0x3e, 0xf6, 0xba, 0x72, - 0x37, 0xff, 0xbd, 0x75, 0x30, 0xf8, 0x00, 0xc9, 0x8f, 0x46, - 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, - 0x8a, 0x43, 0x0c, 0xc5, 0x83, 0x4a, 0x0f, 0xc6, 0x80, 0x49, - 0x0a, 0xc3, 0x85, 0x4c, 0x09, 0xc0, 0x86, 0x4f, 0x18, 0xd1, - 0x97, 0x5e, 0x1b, 0xd2, 0x94, 0x5d, 0x1e, 0xd7, 0x91, 0x58, - 0x1d, 0xd4, 0x92, 0x5b, 0x14, 0xdd, 0x9b, 0x52, 0x17, 0xde, - 0x98, 0x51, 0x12, 0xdb, 0x9d, 0x54, 0x11, 0xd8, 0x9e, 0x57, - 0x30, 0xf9, 0xbf, 0x76, 0x33, 0xfa, 0xbc, 0x75, 0x36, 0xff, - 0xb9, 0x70, 0x35, 0xfc, 0xba, 0x73, 0x3c, 0xf5, 0xb3, 0x7a, - 0x3f, 0xf6, 0xb0, 0x79, 0x3a, 0xf3, 0xb5, 0x7c, 0x39, 0xf0, - 0xb6, 0x7f, 0x28, 0xe1, 0xa7, 0x6e, 0x2b, 0xe2, 0xa4, 0x6d, - 0x2e, 0xe7, 0xa1, 0x68, 0x2d, 0xe4, 0xa2, 0x6b, 0x24, 0xed, - 0xab, 0x62, 0x27, 0xee, 0xa8, 0x61, 0x22, 0xeb, 0xad, 0x64, - 0x21, 0xe8, 0xae, 0x67, 0x60, 0xa9, 0xef, 0x26, 0x63, 0xaa, - 0xec, 0x25, 0x66, 0xaf, 0xe9, 0x20, 0x65, 0xac, 0xea, 0x23, - 0x6c, 0xa5, 0xe3, 0x2a, 0x6f, 0xa6, 0xe0, 0x29, 0x6a, 0xa3, - 0xe5, 0x2c, 0x69, 0xa0, 0xe6, 0x2f, 0x78, 0xb1, 0xf7, 0x3e, - 0x7b, 0xb2, 0xf4, 0x3d, 0x7e, 0xb7, 0xf1, 0x38, 0x7d, 0xb4, - 0xf2, 0x3b, 0x74, 0xbd, 0xfb, 0x32, 0x77, 0xbe, 0xf8, 0x31, - 0x72, 0xbb, 0xfd, 0x34, 0x71, 0xb8, 0xfe, 0x37, 0x50, 0x99, - 0xdf, 0x16, 0x53, 0x9a, 0xdc, 0x15, 0x56, 0x9f, 0xd9, 0x10, - 0x55, 0x9c, 0xda, 0x13, 0x5c, 0x95, 0xd3, 0x1a, 0x5f, 0x96, - 0xd0, 0x19, 0x5a, 0x93, 0xd5, 0x1c, 0x59, 0x90, 0xd6, 0x1f, - 0x48, 0x81, 0xc7, 0x0e, 0x4b, 0x82, 0xc4, 0x0d, 0x4e, 0x87, - 0xc1, 0x08, 0x4d, 0x84, 0xc2, 0x0b, 0x44, 0x8d, 0xcb, 0x02, - 0x47, 0x8e, 0xc8, 0x01, 0x42, 0x8b, 0xcd, 0x04, 0x41, 0x88, - 0xce, 0x07, 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, - 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52, 0x3c, 0xf6, - 0xb5, 0x7f, 0x33, 0xf9, 0xba, 0x70, 0x22, 0xe8, 0xab, 0x61, - 0x2d, 0xe7, 0xa4, 0x6e, 0x78, 0xb2, 0xf1, 0x3b, 0x77, 0xbd, - 0xfe, 0x34, 0x66, 0xac, 0xef, 0x25, 0x69, 0xa3, 0xe0, 0x2a, - 0x44, 0x8e, 0xcd, 0x07, 0x4b, 0x81, 0xc2, 0x08, 0x5a, 0x90, - 0xd3, 0x19, 0x55, 0x9f, 0xdc, 0x16, 0xf0, 0x3a, 0x79, 0xb3, - 0xff, 0x35, 0x76, 0xbc, 0xee, 0x24, 0x67, 0xad, 0xe1, 0x2b, - 0x68, 0xa2, 0xcc, 0x06, 0x45, 0x8f, 0xc3, 0x09, 0x4a, 0x80, - 0xd2, 0x18, 0x5b, 0x91, 0xdd, 0x17, 0x54, 0x9e, 0x88, 0x42, - 0x01, 0xcb, 0x87, 0x4d, 0x0e, 0xc4, 0x96, 0x5c, 0x1f, 0xd5, - 0x99, 0x53, 0x10, 0xda, 0xb4, 0x7e, 0x3d, 0xf7, 0xbb, 0x71, - 0x32, 0xf8, 0xaa, 0x60, 0x23, 0xe9, 0xa5, 0x6f, 0x2c, 0xe6, - 0xfd, 0x37, 0x74, 0xbe, 0xf2, 0x38, 0x7b, 0xb1, 0xe3, 0x29, - 0x6a, 0xa0, 0xec, 0x26, 0x65, 0xaf, 0xc1, 0x0b, 0x48, 0x82, - 0xce, 0x04, 0x47, 0x8d, 0xdf, 0x15, 0x56, 0x9c, 0xd0, 0x1a, - 0x59, 0x93, 0x85, 0x4f, 0x0c, 0xc6, 0x8a, 0x40, 0x03, 0xc9, - 0x9b, 0x51, 0x12, 0xd8, 0x94, 0x5e, 0x1d, 0xd7, 0xb9, 0x73, - 0x30, 0xfa, 0xb6, 0x7c, 0x3f, 0xf5, 0xa7, 0x6d, 0x2e, 0xe4, - 0xa8, 0x62, 0x21, 0xeb, 0x0d, 0xc7, 0x84, 0x4e, 0x02, 0xc8, - 0x8b, 0x41, 0x13, 0xd9, 0x9a, 0x50, 0x1c, 0xd6, 0x95, 0x5f, - 0x31, 0xfb, 0xb8, 0x72, 0x3e, 0xf4, 0xb7, 0x7d, 0x2f, 0xe5, - 0xa6, 0x6c, 0x20, 0xea, 0xa9, 0x63, 0x75, 0xbf, 0xfc, 0x36, - 0x7a, 0xb0, 0xf3, 0x39, 0x6b, 0xa1, 0xe2, 0x28, 0x64, 0xae, - 0xed, 0x27, 0x49, 0x83, 0xc0, 0x0a, 0x46, 0x8c, 0xcf, 0x05, - 0x57, 0x9d, 0xde, 0x14, 0x58, 0x92, 0xd1, 0x1b, 0x00, 0xcb, - 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, - 0x1d, 0xd6, 0x96, 0x5d, 0x2c, 0xe7, 0xa7, 0x6c, 0x27, 0xec, - 0xac, 0x67, 0x3a, 0xf1, 0xb1, 0x7a, 0x31, 0xfa, 0xba, 0x71, - 0x58, 0x93, 0xd3, 0x18, 0x53, 0x98, 0xd8, 0x13, 0x4e, 0x85, - 0xc5, 0x0e, 0x45, 0x8e, 0xce, 0x05, 0x74, 0xbf, 0xff, 0x34, - 0x7f, 0xb4, 0xf4, 0x3f, 0x62, 0xa9, 0xe9, 0x22, 0x69, 0xa2, - 0xe2, 0x29, 0xb0, 0x7b, 0x3b, 0xf0, 0xbb, 0x70, 0x30, 0xfb, - 0xa6, 0x6d, 0x2d, 0xe6, 0xad, 0x66, 0x26, 0xed, 0x9c, 0x57, - 0x17, 0xdc, 0x97, 0x5c, 0x1c, 0xd7, 0x8a, 0x41, 0x01, 0xca, - 0x81, 0x4a, 0x0a, 0xc1, 0xe8, 0x23, 0x63, 0xa8, 0xe3, 0x28, - 0x68, 0xa3, 0xfe, 0x35, 0x75, 0xbe, 0xf5, 0x3e, 0x7e, 0xb5, - 0xc4, 0x0f, 0x4f, 0x84, 0xcf, 0x04, 0x44, 0x8f, 0xd2, 0x19, - 0x59, 0x92, 0xd9, 0x12, 0x52, 0x99, 0x7d, 0xb6, 0xf6, 0x3d, - 0x76, 0xbd, 0xfd, 0x36, 0x6b, 0xa0, 0xe0, 0x2b, 0x60, 0xab, - 0xeb, 0x20, 0x51, 0x9a, 0xda, 0x11, 0x5a, 0x91, 0xd1, 0x1a, - 0x47, 0x8c, 0xcc, 0x07, 0x4c, 0x87, 0xc7, 0x0c, 0x25, 0xee, - 0xae, 0x65, 0x2e, 0xe5, 0xa5, 0x6e, 0x33, 0xf8, 0xb8, 0x73, - 0x38, 0xf3, 0xb3, 0x78, 0x09, 0xc2, 0x82, 0x49, 0x02, 0xc9, - 0x89, 0x42, 0x1f, 0xd4, 0x94, 0x5f, 0x14, 0xdf, 0x9f, 0x54, - 0xcd, 0x06, 0x46, 0x8d, 0xc6, 0x0d, 0x4d, 0x86, 0xdb, 0x10, - 0x50, 0x9b, 0xd0, 0x1b, 0x5b, 0x90, 0xe1, 0x2a, 0x6a, 0xa1, - 0xea, 0x21, 0x61, 0xaa, 0xf7, 0x3c, 0x7c, 0xb7, 0xfc, 0x37, - 0x77, 0xbc, 0x95, 0x5e, 0x1e, 0xd5, 0x9e, 0x55, 0x15, 0xde, - 0x83, 0x48, 0x08, 0xc3, 0x88, 0x43, 0x03, 0xc8, 0xb9, 0x72, - 0x32, 0xf9, 0xb2, 0x79, 0x39, 0xf2, 0xaf, 0x64, 0x24, 0xef, - 0xa4, 0x6f, 0x2f, 0xe4, 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, - 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70, - 0x5c, 0x90, 0xd9, 0x15, 0x4b, 0x87, 0xce, 0x02, 0x72, 0xbe, - 0xf7, 0x3b, 0x65, 0xa9, 0xe0, 0x2c, 0xb8, 0x74, 0x3d, 0xf1, - 0xaf, 0x63, 0x2a, 0xe6, 0x96, 0x5a, 0x13, 0xdf, 0x81, 0x4d, - 0x04, 0xc8, 0xe4, 0x28, 0x61, 0xad, 0xf3, 0x3f, 0x76, 0xba, - 0xca, 0x06, 0x4f, 0x83, 0xdd, 0x11, 0x58, 0x94, 0x6d, 0xa1, - 0xe8, 0x24, 0x7a, 0xb6, 0xff, 0x33, 0x43, 0x8f, 0xc6, 0x0a, - 0x54, 0x98, 0xd1, 0x1d, 0x31, 0xfd, 0xb4, 0x78, 0x26, 0xea, - 0xa3, 0x6f, 0x1f, 0xd3, 0x9a, 0x56, 0x08, 0xc4, 0x8d, 0x41, - 0xd5, 0x19, 0x50, 0x9c, 0xc2, 0x0e, 0x47, 0x8b, 0xfb, 0x37, - 0x7e, 0xb2, 0xec, 0x20, 0x69, 0xa5, 0x89, 0x45, 0x0c, 0xc0, - 0x9e, 0x52, 0x1b, 0xd7, 0xa7, 0x6b, 0x22, 0xee, 0xb0, 0x7c, - 0x35, 0xf9, 0xda, 0x16, 0x5f, 0x93, 0xcd, 0x01, 0x48, 0x84, - 0xf4, 0x38, 0x71, 0xbd, 0xe3, 0x2f, 0x66, 0xaa, 0x86, 0x4a, - 0x03, 0xcf, 0x91, 0x5d, 0x14, 0xd8, 0xa8, 0x64, 0x2d, 0xe1, - 0xbf, 0x73, 0x3a, 0xf6, 0x62, 0xae, 0xe7, 0x2b, 0x75, 0xb9, - 0xf0, 0x3c, 0x4c, 0x80, 0xc9, 0x05, 0x5b, 0x97, 0xde, 0x12, - 0x3e, 0xf2, 0xbb, 0x77, 0x29, 0xe5, 0xac, 0x60, 0x10, 0xdc, - 0x95, 0x59, 0x07, 0xcb, 0x82, 0x4e, 0xb7, 0x7b, 0x32, 0xfe, - 0xa0, 0x6c, 0x25, 0xe9, 0x99, 0x55, 0x1c, 0xd0, 0x8e, 0x42, - 0x0b, 0xc7, 0xeb, 0x27, 0x6e, 0xa2, 0xfc, 0x30, 0x79, 0xb5, - 0xc5, 0x09, 0x40, 0x8c, 0xd2, 0x1e, 0x57, 0x9b, 0x0f, 0xc3, - 0x8a, 0x46, 0x18, 0xd4, 0x9d, 0x51, 0x21, 0xed, 0xa4, 0x68, - 0x36, 0xfa, 0xb3, 0x7f, 0x53, 0x9f, 0xd6, 0x1a, 0x44, 0x88, - 0xc1, 0x0d, 0x7d, 0xb1, 0xf8, 0x34, 0x6a, 0xa6, 0xef, 0x23, - 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, - 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f, 0x4c, 0x81, 0xcb, 0x06, - 0x5f, 0x92, 0xd8, 0x15, 0x6a, 0xa7, 0xed, 0x20, 0x79, 0xb4, - 0xfe, 0x33, 0x98, 0x55, 0x1f, 0xd2, 0x8b, 0x46, 0x0c, 0xc1, - 0xbe, 0x73, 0x39, 0xf4, 0xad, 0x60, 0x2a, 0xe7, 0xd4, 0x19, - 0x53, 0x9e, 0xc7, 0x0a, 0x40, 0x8d, 0xf2, 0x3f, 0x75, 0xb8, - 0xe1, 0x2c, 0x66, 0xab, 0x2d, 0xe0, 0xaa, 0x67, 0x3e, 0xf3, - 0xb9, 0x74, 0x0b, 0xc6, 0x8c, 0x41, 0x18, 0xd5, 0x9f, 0x52, - 0x61, 0xac, 0xe6, 0x2b, 0x72, 0xbf, 0xf5, 0x38, 0x47, 0x8a, - 0xc0, 0x0d, 0x54, 0x99, 0xd3, 0x1e, 0xb5, 0x78, 0x32, 0xff, - 0xa6, 0x6b, 0x21, 0xec, 0x93, 0x5e, 0x14, 0xd9, 0x80, 0x4d, - 0x07, 0xca, 0xf9, 0x34, 0x7e, 0xb3, 0xea, 0x27, 0x6d, 0xa0, - 0xdf, 0x12, 0x58, 0x95, 0xcc, 0x01, 0x4b, 0x86, 0x5a, 0x97, - 0xdd, 0x10, 0x49, 0x84, 0xce, 0x03, 0x7c, 0xb1, 0xfb, 0x36, - 0x6f, 0xa2, 0xe8, 0x25, 0x16, 0xdb, 0x91, 0x5c, 0x05, 0xc8, - 0x82, 0x4f, 0x30, 0xfd, 0xb7, 0x7a, 0x23, 0xee, 0xa4, 0x69, - 0xc2, 0x0f, 0x45, 0x88, 0xd1, 0x1c, 0x56, 0x9b, 0xe4, 0x29, - 0x63, 0xae, 0xf7, 0x3a, 0x70, 0xbd, 0x8e, 0x43, 0x09, 0xc4, - 0x9d, 0x50, 0x1a, 0xd7, 0xa8, 0x65, 0x2f, 0xe2, 0xbb, 0x76, - 0x3c, 0xf1, 0x77, 0xba, 0xf0, 0x3d, 0x64, 0xa9, 0xe3, 0x2e, - 0x51, 0x9c, 0xd6, 0x1b, 0x42, 0x8f, 0xc5, 0x08, 0x3b, 0xf6, - 0xbc, 0x71, 0x28, 0xe5, 0xaf, 0x62, 0x1d, 0xd0, 0x9a, 0x57, - 0x0e, 0xc3, 0x89, 0x44, 0xef, 0x22, 0x68, 0xa5, 0xfc, 0x31, - 0x7b, 0xb6, 0xc9, 0x04, 0x4e, 0x83, 0xda, 0x17, 0x5d, 0x90, - 0xa3, 0x6e, 0x24, 0xe9, 0xb0, 0x7d, 0x37, 0xfa, 0x85, 0x48, - 0x02, 0xcf, 0x96, 0x5b, 0x11, 0xdc, 0x00, 0xce, 0x81, 0x4f, - 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, - 0xa0, 0x6e, 0x7c, 0xb2, 0xfd, 0x33, 0x63, 0xad, 0xe2, 0x2c, - 0x42, 0x8c, 0xc3, 0x0d, 0x5d, 0x93, 0xdc, 0x12, 0xf8, 0x36, - 0x79, 0xb7, 0xe7, 0x29, 0x66, 0xa8, 0xc6, 0x08, 0x47, 0x89, - 0xd9, 0x17, 0x58, 0x96, 0x84, 0x4a, 0x05, 0xcb, 0x9b, 0x55, - 0x1a, 0xd4, 0xba, 0x74, 0x3b, 0xf5, 0xa5, 0x6b, 0x24, 0xea, - 0xed, 0x23, 0x6c, 0xa2, 0xf2, 0x3c, 0x73, 0xbd, 0xd3, 0x1d, - 0x52, 0x9c, 0xcc, 0x02, 0x4d, 0x83, 0x91, 0x5f, 0x10, 0xde, - 0x8e, 0x40, 0x0f, 0xc1, 0xaf, 0x61, 0x2e, 0xe0, 0xb0, 0x7e, - 0x31, 0xff, 0x15, 0xdb, 0x94, 0x5a, 0x0a, 0xc4, 0x8b, 0x45, - 0x2b, 0xe5, 0xaa, 0x64, 0x34, 0xfa, 0xb5, 0x7b, 0x69, 0xa7, - 0xe8, 0x26, 0x76, 0xb8, 0xf7, 0x39, 0x57, 0x99, 0xd6, 0x18, - 0x48, 0x86, 0xc9, 0x07, 0xc7, 0x09, 0x46, 0x88, 0xd8, 0x16, - 0x59, 0x97, 0xf9, 0x37, 0x78, 0xb6, 0xe6, 0x28, 0x67, 0xa9, - 0xbb, 0x75, 0x3a, 0xf4, 0xa4, 0x6a, 0x25, 0xeb, 0x85, 0x4b, - 0x04, 0xca, 0x9a, 0x54, 0x1b, 0xd5, 0x3f, 0xf1, 0xbe, 0x70, - 0x20, 0xee, 0xa1, 0x6f, 0x01, 0xcf, 0x80, 0x4e, 0x1e, 0xd0, - 0x9f, 0x51, 0x43, 0x8d, 0xc2, 0x0c, 0x5c, 0x92, 0xdd, 0x13, - 0x7d, 0xb3, 0xfc, 0x32, 0x62, 0xac, 0xe3, 0x2d, 0x2a, 0xe4, - 0xab, 0x65, 0x35, 0xfb, 0xb4, 0x7a, 0x14, 0xda, 0x95, 0x5b, - 0x0b, 0xc5, 0x8a, 0x44, 0x56, 0x98, 0xd7, 0x19, 0x49, 0x87, - 0xc8, 0x06, 0x68, 0xa6, 0xe9, 0x27, 0x77, 0xb9, 0xf6, 0x38, - 0xd2, 0x1c, 0x53, 0x9d, 0xcd, 0x03, 0x4c, 0x82, 0xec, 0x22, - 0x6d, 0xa3, 0xf3, 0x3d, 0x72, 0xbc, 0xae, 0x60, 0x2f, 0xe1, - 0xb1, 0x7f, 0x30, 0xfe, 0x90, 0x5e, 0x11, 0xdf, 0x8f, 0x41, - 0x0e, 0xc0, 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, - 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61, 0x6c, 0xa3, - 0xef, 0x20, 0x77, 0xb8, 0xf4, 0x3b, 0x5a, 0x95, 0xd9, 0x16, - 0x41, 0x8e, 0xc2, 0x0d, 0xd8, 0x17, 0x5b, 0x94, 0xc3, 0x0c, - 0x40, 0x8f, 0xee, 0x21, 0x6d, 0xa2, 0xf5, 0x3a, 0x76, 0xb9, - 0xb4, 0x7b, 0x37, 0xf8, 0xaf, 0x60, 0x2c, 0xe3, 0x82, 0x4d, - 0x01, 0xce, 0x99, 0x56, 0x1a, 0xd5, 0xad, 0x62, 0x2e, 0xe1, - 0xb6, 0x79, 0x35, 0xfa, 0x9b, 0x54, 0x18, 0xd7, 0x80, 0x4f, - 0x03, 0xcc, 0xc1, 0x0e, 0x42, 0x8d, 0xda, 0x15, 0x59, 0x96, - 0xf7, 0x38, 0x74, 0xbb, 0xec, 0x23, 0x6f, 0xa0, 0x75, 0xba, - 0xf6, 0x39, 0x6e, 0xa1, 0xed, 0x22, 0x43, 0x8c, 0xc0, 0x0f, - 0x58, 0x97, 0xdb, 0x14, 0x19, 0xd6, 0x9a, 0x55, 0x02, 0xcd, - 0x81, 0x4e, 0x2f, 0xe0, 0xac, 0x63, 0x34, 0xfb, 0xb7, 0x78, - 0x47, 0x88, 0xc4, 0x0b, 0x5c, 0x93, 0xdf, 0x10, 0x71, 0xbe, - 0xf2, 0x3d, 0x6a, 0xa5, 0xe9, 0x26, 0x2b, 0xe4, 0xa8, 0x67, - 0x30, 0xff, 0xb3, 0x7c, 0x1d, 0xd2, 0x9e, 0x51, 0x06, 0xc9, - 0x85, 0x4a, 0x9f, 0x50, 0x1c, 0xd3, 0x84, 0x4b, 0x07, 0xc8, - 0xa9, 0x66, 0x2a, 0xe5, 0xb2, 0x7d, 0x31, 0xfe, 0xf3, 0x3c, - 0x70, 0xbf, 0xe8, 0x27, 0x6b, 0xa4, 0xc5, 0x0a, 0x46, 0x89, - 0xde, 0x11, 0x5d, 0x92, 0xea, 0x25, 0x69, 0xa6, 0xf1, 0x3e, - 0x72, 0xbd, 0xdc, 0x13, 0x5f, 0x90, 0xc7, 0x08, 0x44, 0x8b, - 0x86, 0x49, 0x05, 0xca, 0x9d, 0x52, 0x1e, 0xd1, 0xb0, 0x7f, - 0x33, 0xfc, 0xab, 0x64, 0x28, 0xe7, 0x32, 0xfd, 0xb1, 0x7e, - 0x29, 0xe6, 0xaa, 0x65, 0x04, 0xcb, 0x87, 0x48, 0x1f, 0xd0, - 0x9c, 0x53, 0x5e, 0x91, 0xdd, 0x12, 0x45, 0x8a, 0xc6, 0x09, - 0x68, 0xa7, 0xeb, 0x24, 0x73, 0xbc, 0xf0, 0x3f, 0x00, 0xd0, - 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, - 0xa9, 0x79, 0x14, 0xc4, 0x81, 0x51, 0x3c, 0xec, 0xe6, 0x36, - 0x5b, 0x8b, 0x4f, 0x9f, 0xf2, 0x22, 0x28, 0xf8, 0x95, 0x45, - 0x1f, 0xcf, 0xa2, 0x72, 0x78, 0xa8, 0xc5, 0x15, 0xd1, 0x01, - 0x6c, 0xbc, 0xb6, 0x66, 0x0b, 0xdb, 0x9e, 0x4e, 0x23, 0xf3, - 0xf9, 0x29, 0x44, 0x94, 0x50, 0x80, 0xed, 0x3d, 0x37, 0xe7, - 0x8a, 0x5a, 0x3e, 0xee, 0x83, 0x53, 0x59, 0x89, 0xe4, 0x34, - 0xf0, 0x20, 0x4d, 0x9d, 0x97, 0x47, 0x2a, 0xfa, 0xbf, 0x6f, - 0x02, 0xd2, 0xd8, 0x08, 0x65, 0xb5, 0x71, 0xa1, 0xcc, 0x1c, - 0x16, 0xc6, 0xab, 0x7b, 0x21, 0xf1, 0x9c, 0x4c, 0x46, 0x96, - 0xfb, 0x2b, 0xef, 0x3f, 0x52, 0x82, 0x88, 0x58, 0x35, 0xe5, - 0xa0, 0x70, 0x1d, 0xcd, 0xc7, 0x17, 0x7a, 0xaa, 0x6e, 0xbe, - 0xd3, 0x03, 0x09, 0xd9, 0xb4, 0x64, 0x7c, 0xac, 0xc1, 0x11, - 0x1b, 0xcb, 0xa6, 0x76, 0xb2, 0x62, 0x0f, 0xdf, 0xd5, 0x05, - 0x68, 0xb8, 0xfd, 0x2d, 0x40, 0x90, 0x9a, 0x4a, 0x27, 0xf7, - 0x33, 0xe3, 0x8e, 0x5e, 0x54, 0x84, 0xe9, 0x39, 0x63, 0xb3, - 0xde, 0x0e, 0x04, 0xd4, 0xb9, 0x69, 0xad, 0x7d, 0x10, 0xc0, - 0xca, 0x1a, 0x77, 0xa7, 0xe2, 0x32, 0x5f, 0x8f, 0x85, 0x55, - 0x38, 0xe8, 0x2c, 0xfc, 0x91, 0x41, 0x4b, 0x9b, 0xf6, 0x26, - 0x42, 0x92, 0xff, 0x2f, 0x25, 0xf5, 0x98, 0x48, 0x8c, 0x5c, - 0x31, 0xe1, 0xeb, 0x3b, 0x56, 0x86, 0xc3, 0x13, 0x7e, 0xae, - 0xa4, 0x74, 0x19, 0xc9, 0x0d, 0xdd, 0xb0, 0x60, 0x6a, 0xba, - 0xd7, 0x07, 0x5d, 0x8d, 0xe0, 0x30, 0x3a, 0xea, 0x87, 0x57, - 0x93, 0x43, 0x2e, 0xfe, 0xf4, 0x24, 0x49, 0x99, 0xdc, 0x0c, - 0x61, 0xb1, 0xbb, 0x6b, 0x06, 0xd6, 0x12, 0xc2, 0xaf, 0x7f, - 0x75, 0xa5, 0xc8, 0x18, 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, - 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb, - 0x91, 0x40, 0x2e, 0xff, 0xf2, 0x23, 0x4d, 0x9c, 0x57, 0x86, - 0xe8, 0x39, 0x34, 0xe5, 0x8b, 0x5a, 0x3f, 0xee, 0x80, 0x51, - 0x5c, 0x8d, 0xe3, 0x32, 0xf9, 0x28, 0x46, 0x97, 0x9a, 0x4b, - 0x25, 0xf4, 0xae, 0x7f, 0x11, 0xc0, 0xcd, 0x1c, 0x72, 0xa3, - 0x68, 0xb9, 0xd7, 0x06, 0x0b, 0xda, 0xb4, 0x65, 0x7e, 0xaf, - 0xc1, 0x10, 0x1d, 0xcc, 0xa2, 0x73, 0xb8, 0x69, 0x07, 0xd6, - 0xdb, 0x0a, 0x64, 0xb5, 0xef, 0x3e, 0x50, 0x81, 0x8c, 0x5d, - 0x33, 0xe2, 0x29, 0xf8, 0x96, 0x47, 0x4a, 0x9b, 0xf5, 0x24, - 0x41, 0x90, 0xfe, 0x2f, 0x22, 0xf3, 0x9d, 0x4c, 0x87, 0x56, - 0x38, 0xe9, 0xe4, 0x35, 0x5b, 0x8a, 0xd0, 0x01, 0x6f, 0xbe, - 0xb3, 0x62, 0x0c, 0xdd, 0x16, 0xc7, 0xa9, 0x78, 0x75, 0xa4, - 0xca, 0x1b, 0xfc, 0x2d, 0x43, 0x92, 0x9f, 0x4e, 0x20, 0xf1, - 0x3a, 0xeb, 0x85, 0x54, 0x59, 0x88, 0xe6, 0x37, 0x6d, 0xbc, - 0xd2, 0x03, 0x0e, 0xdf, 0xb1, 0x60, 0xab, 0x7a, 0x14, 0xc5, - 0xc8, 0x19, 0x77, 0xa6, 0xc3, 0x12, 0x7c, 0xad, 0xa0, 0x71, - 0x1f, 0xce, 0x05, 0xd4, 0xba, 0x6b, 0x66, 0xb7, 0xd9, 0x08, - 0x52, 0x83, 0xed, 0x3c, 0x31, 0xe0, 0x8e, 0x5f, 0x94, 0x45, - 0x2b, 0xfa, 0xf7, 0x26, 0x48, 0x99, 0x82, 0x53, 0x3d, 0xec, - 0xe1, 0x30, 0x5e, 0x8f, 0x44, 0x95, 0xfb, 0x2a, 0x27, 0xf6, - 0x98, 0x49, 0x13, 0xc2, 0xac, 0x7d, 0x70, 0xa1, 0xcf, 0x1e, - 0xd5, 0x04, 0x6a, 0xbb, 0xb6, 0x67, 0x09, 0xd8, 0xbd, 0x6c, - 0x02, 0xd3, 0xde, 0x0f, 0x61, 0xb0, 0x7b, 0xaa, 0xc4, 0x15, - 0x18, 0xc9, 0xa7, 0x76, 0x2c, 0xfd, 0x93, 0x42, 0x4f, 0x9e, - 0xf0, 0x21, 0xea, 0x3b, 0x55, 0x84, 0x89, 0x58, 0x36, 0xe7, - 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, - 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda, 0xa1, 0x73, 0x18, 0xca, - 0xce, 0x1c, 0x77, 0xa5, 0x7f, 0xad, 0xc6, 0x14, 0x10, 0xc2, - 0xa9, 0x7b, 0x5f, 0x8d, 0xe6, 0x34, 0x30, 0xe2, 0x89, 0x5b, - 0x81, 0x53, 0x38, 0xea, 0xee, 0x3c, 0x57, 0x85, 0xfe, 0x2c, - 0x47, 0x95, 0x91, 0x43, 0x28, 0xfa, 0x20, 0xf2, 0x99, 0x4b, - 0x4f, 0x9d, 0xf6, 0x24, 0xbe, 0x6c, 0x07, 0xd5, 0xd1, 0x03, - 0x68, 0xba, 0x60, 0xb2, 0xd9, 0x0b, 0x0f, 0xdd, 0xb6, 0x64, - 0x1f, 0xcd, 0xa6, 0x74, 0x70, 0xa2, 0xc9, 0x1b, 0xc1, 0x13, - 0x78, 0xaa, 0xae, 0x7c, 0x17, 0xc5, 0xe1, 0x33, 0x58, 0x8a, - 0x8e, 0x5c, 0x37, 0xe5, 0x3f, 0xed, 0x86, 0x54, 0x50, 0x82, - 0xe9, 0x3b, 0x40, 0x92, 0xf9, 0x2b, 0x2f, 0xfd, 0x96, 0x44, - 0x9e, 0x4c, 0x27, 0xf5, 0xf1, 0x23, 0x48, 0x9a, 0x61, 0xb3, - 0xd8, 0x0a, 0x0e, 0xdc, 0xb7, 0x65, 0xbf, 0x6d, 0x06, 0xd4, - 0xd0, 0x02, 0x69, 0xbb, 0xc0, 0x12, 0x79, 0xab, 0xaf, 0x7d, - 0x16, 0xc4, 0x1e, 0xcc, 0xa7, 0x75, 0x71, 0xa3, 0xc8, 0x1a, - 0x3e, 0xec, 0x87, 0x55, 0x51, 0x83, 0xe8, 0x3a, 0xe0, 0x32, - 0x59, 0x8b, 0x8f, 0x5d, 0x36, 0xe4, 0x9f, 0x4d, 0x26, 0xf4, - 0xf0, 0x22, 0x49, 0x9b, 0x41, 0x93, 0xf8, 0x2a, 0x2e, 0xfc, - 0x97, 0x45, 0xdf, 0x0d, 0x66, 0xb4, 0xb0, 0x62, 0x09, 0xdb, - 0x01, 0xd3, 0xb8, 0x6a, 0x6e, 0xbc, 0xd7, 0x05, 0x7e, 0xac, - 0xc7, 0x15, 0x11, 0xc3, 0xa8, 0x7a, 0xa0, 0x72, 0x19, 0xcb, - 0xcf, 0x1d, 0x76, 0xa4, 0x80, 0x52, 0x39, 0xeb, 0xef, 0x3d, - 0x56, 0x84, 0x5e, 0x8c, 0xe7, 0x35, 0x31, 0xe3, 0x88, 0x5a, - 0x21, 0xf3, 0x98, 0x4a, 0x4e, 0x9c, 0xf7, 0x25, 0xff, 0x2d, - 0x46, 0x94, 0x90, 0x42, 0x29, 0xfb, 0x00, 0xd3, 0xbb, 0x68, - 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, - 0x06, 0xd5, 0xb1, 0x62, 0x0a, 0xd9, 0xda, 0x09, 0x61, 0xb2, - 0x67, 0xb4, 0xdc, 0x0f, 0x0c, 0xdf, 0xb7, 0x64, 0x7f, 0xac, - 0xc4, 0x17, 0x14, 0xc7, 0xaf, 0x7c, 0xa9, 0x7a, 0x12, 0xc1, - 0xc2, 0x11, 0x79, 0xaa, 0xce, 0x1d, 0x75, 0xa6, 0xa5, 0x76, - 0x1e, 0xcd, 0x18, 0xcb, 0xa3, 0x70, 0x73, 0xa0, 0xc8, 0x1b, - 0xfe, 0x2d, 0x45, 0x96, 0x95, 0x46, 0x2e, 0xfd, 0x28, 0xfb, - 0x93, 0x40, 0x43, 0x90, 0xf8, 0x2b, 0x4f, 0x9c, 0xf4, 0x27, - 0x24, 0xf7, 0x9f, 0x4c, 0x99, 0x4a, 0x22, 0xf1, 0xf2, 0x21, - 0x49, 0x9a, 0x81, 0x52, 0x3a, 0xe9, 0xea, 0x39, 0x51, 0x82, - 0x57, 0x84, 0xec, 0x3f, 0x3c, 0xef, 0x87, 0x54, 0x30, 0xe3, - 0x8b, 0x58, 0x5b, 0x88, 0xe0, 0x33, 0xe6, 0x35, 0x5d, 0x8e, - 0x8d, 0x5e, 0x36, 0xe5, 0xe1, 0x32, 0x5a, 0x89, 0x8a, 0x59, - 0x31, 0xe2, 0x37, 0xe4, 0x8c, 0x5f, 0x5c, 0x8f, 0xe7, 0x34, - 0x50, 0x83, 0xeb, 0x38, 0x3b, 0xe8, 0x80, 0x53, 0x86, 0x55, - 0x3d, 0xee, 0xed, 0x3e, 0x56, 0x85, 0x9e, 0x4d, 0x25, 0xf6, - 0xf5, 0x26, 0x4e, 0x9d, 0x48, 0x9b, 0xf3, 0x20, 0x23, 0xf0, - 0x98, 0x4b, 0x2f, 0xfc, 0x94, 0x47, 0x44, 0x97, 0xff, 0x2c, - 0xf9, 0x2a, 0x42, 0x91, 0x92, 0x41, 0x29, 0xfa, 0x1f, 0xcc, - 0xa4, 0x77, 0x74, 0xa7, 0xcf, 0x1c, 0xc9, 0x1a, 0x72, 0xa1, - 0xa2, 0x71, 0x19, 0xca, 0xae, 0x7d, 0x15, 0xc6, 0xc5, 0x16, - 0x7e, 0xad, 0x78, 0xab, 0xc3, 0x10, 0x13, 0xc0, 0xa8, 0x7b, - 0x60, 0xb3, 0xdb, 0x08, 0x0b, 0xd8, 0xb0, 0x63, 0xb6, 0x65, - 0x0d, 0xde, 0xdd, 0x0e, 0x66, 0xb5, 0xd1, 0x02, 0x6a, 0xb9, - 0xba, 0x69, 0x01, 0xd2, 0x07, 0xd4, 0xbc, 0x6f, 0x6c, 0xbf, - 0xd7, 0x04, 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, - 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8, 0xc1, 0x15, - 0x74, 0xa0, 0xb6, 0x62, 0x03, 0xd7, 0x2f, 0xfb, 0x9a, 0x4e, - 0x58, 0x8c, 0xed, 0x39, 0x9f, 0x4b, 0x2a, 0xfe, 0xe8, 0x3c, - 0x5d, 0x89, 0x71, 0xa5, 0xc4, 0x10, 0x06, 0xd2, 0xb3, 0x67, - 0x5e, 0x8a, 0xeb, 0x3f, 0x29, 0xfd, 0x9c, 0x48, 0xb0, 0x64, - 0x05, 0xd1, 0xc7, 0x13, 0x72, 0xa6, 0x23, 0xf7, 0x96, 0x42, - 0x54, 0x80, 0xe1, 0x35, 0xcd, 0x19, 0x78, 0xac, 0xba, 0x6e, - 0x0f, 0xdb, 0xe2, 0x36, 0x57, 0x83, 0x95, 0x41, 0x20, 0xf4, - 0x0c, 0xd8, 0xb9, 0x6d, 0x7b, 0xaf, 0xce, 0x1a, 0xbc, 0x68, - 0x09, 0xdd, 0xcb, 0x1f, 0x7e, 0xaa, 0x52, 0x86, 0xe7, 0x33, - 0x25, 0xf1, 0x90, 0x44, 0x7d, 0xa9, 0xc8, 0x1c, 0x0a, 0xde, - 0xbf, 0x6b, 0x93, 0x47, 0x26, 0xf2, 0xe4, 0x30, 0x51, 0x85, - 0x46, 0x92, 0xf3, 0x27, 0x31, 0xe5, 0x84, 0x50, 0xa8, 0x7c, - 0x1d, 0xc9, 0xdf, 0x0b, 0x6a, 0xbe, 0x87, 0x53, 0x32, 0xe6, - 0xf0, 0x24, 0x45, 0x91, 0x69, 0xbd, 0xdc, 0x08, 0x1e, 0xca, - 0xab, 0x7f, 0xd9, 0x0d, 0x6c, 0xb8, 0xae, 0x7a, 0x1b, 0xcf, - 0x37, 0xe3, 0x82, 0x56, 0x40, 0x94, 0xf5, 0x21, 0x18, 0xcc, - 0xad, 0x79, 0x6f, 0xbb, 0xda, 0x0e, 0xf6, 0x22, 0x43, 0x97, - 0x81, 0x55, 0x34, 0xe0, 0x65, 0xb1, 0xd0, 0x04, 0x12, 0xc6, - 0xa7, 0x73, 0x8b, 0x5f, 0x3e, 0xea, 0xfc, 0x28, 0x49, 0x9d, - 0xa4, 0x70, 0x11, 0xc5, 0xd3, 0x07, 0x66, 0xb2, 0x4a, 0x9e, - 0xff, 0x2b, 0x3d, 0xe9, 0x88, 0x5c, 0xfa, 0x2e, 0x4f, 0x9b, - 0x8d, 0x59, 0x38, 0xec, 0x14, 0xc0, 0xa1, 0x75, 0x63, 0xb7, - 0xd6, 0x02, 0x3b, 0xef, 0x8e, 0x5a, 0x4c, 0x98, 0xf9, 0x2d, - 0xd5, 0x01, 0x60, 0xb4, 0xa2, 0x76, 0x17, 0xc3, 0x00, 0xd5, - 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, - 0x95, 0x40, 0x22, 0xf7, 0xd1, 0x04, 0x66, 0xb3, 0xa2, 0x77, - 0x15, 0xc0, 0x37, 0xe2, 0x80, 0x55, 0x44, 0x91, 0xf3, 0x26, - 0xbf, 0x6a, 0x08, 0xdd, 0xcc, 0x19, 0x7b, 0xae, 0x59, 0x8c, - 0xee, 0x3b, 0x2a, 0xff, 0x9d, 0x48, 0x6e, 0xbb, 0xd9, 0x0c, - 0x1d, 0xc8, 0xaa, 0x7f, 0x88, 0x5d, 0x3f, 0xea, 0xfb, 0x2e, - 0x4c, 0x99, 0x63, 0xb6, 0xd4, 0x01, 0x10, 0xc5, 0xa7, 0x72, - 0x85, 0x50, 0x32, 0xe7, 0xf6, 0x23, 0x41, 0x94, 0xb2, 0x67, - 0x05, 0xd0, 0xc1, 0x14, 0x76, 0xa3, 0x54, 0x81, 0xe3, 0x36, - 0x27, 0xf2, 0x90, 0x45, 0xdc, 0x09, 0x6b, 0xbe, 0xaf, 0x7a, - 0x18, 0xcd, 0x3a, 0xef, 0x8d, 0x58, 0x49, 0x9c, 0xfe, 0x2b, - 0x0d, 0xd8, 0xba, 0x6f, 0x7e, 0xab, 0xc9, 0x1c, 0xeb, 0x3e, - 0x5c, 0x89, 0x98, 0x4d, 0x2f, 0xfa, 0xc6, 0x13, 0x71, 0xa4, - 0xb5, 0x60, 0x02, 0xd7, 0x20, 0xf5, 0x97, 0x42, 0x53, 0x86, - 0xe4, 0x31, 0x17, 0xc2, 0xa0, 0x75, 0x64, 0xb1, 0xd3, 0x06, - 0xf1, 0x24, 0x46, 0x93, 0x82, 0x57, 0x35, 0xe0, 0x79, 0xac, - 0xce, 0x1b, 0x0a, 0xdf, 0xbd, 0x68, 0x9f, 0x4a, 0x28, 0xfd, - 0xec, 0x39, 0x5b, 0x8e, 0xa8, 0x7d, 0x1f, 0xca, 0xdb, 0x0e, - 0x6c, 0xb9, 0x4e, 0x9b, 0xf9, 0x2c, 0x3d, 0xe8, 0x8a, 0x5f, - 0xa5, 0x70, 0x12, 0xc7, 0xd6, 0x03, 0x61, 0xb4, 0x43, 0x96, - 0xf4, 0x21, 0x30, 0xe5, 0x87, 0x52, 0x74, 0xa1, 0xc3, 0x16, - 0x07, 0xd2, 0xb0, 0x65, 0x92, 0x47, 0x25, 0xf0, 0xe1, 0x34, - 0x56, 0x83, 0x1a, 0xcf, 0xad, 0x78, 0x69, 0xbc, 0xde, 0x0b, - 0xfc, 0x29, 0x4b, 0x9e, 0x8f, 0x5a, 0x38, 0xed, 0xcb, 0x1e, - 0x7c, 0xa9, 0xb8, 0x6d, 0x0f, 0xda, 0x2d, 0xf8, 0x9a, 0x4f, - 0x5e, 0x8b, 0xe9, 0x3c, 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, - 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6, - 0xe1, 0x37, 0x50, 0x86, 0x9e, 0x48, 0x2f, 0xf9, 0x1f, 0xc9, - 0xae, 0x78, 0x60, 0xb6, 0xd1, 0x07, 0xdf, 0x09, 0x6e, 0xb8, - 0xa0, 0x76, 0x11, 0xc7, 0x21, 0xf7, 0x90, 0x46, 0x5e, 0x88, - 0xef, 0x39, 0x3e, 0xe8, 0x8f, 0x59, 0x41, 0x97, 0xf0, 0x26, - 0xc0, 0x16, 0x71, 0xa7, 0xbf, 0x69, 0x0e, 0xd8, 0xa3, 0x75, - 0x12, 0xc4, 0xdc, 0x0a, 0x6d, 0xbb, 0x5d, 0x8b, 0xec, 0x3a, - 0x22, 0xf4, 0x93, 0x45, 0x42, 0x94, 0xf3, 0x25, 0x3d, 0xeb, - 0x8c, 0x5a, 0xbc, 0x6a, 0x0d, 0xdb, 0xc3, 0x15, 0x72, 0xa4, - 0x7c, 0xaa, 0xcd, 0x1b, 0x03, 0xd5, 0xb2, 0x64, 0x82, 0x54, - 0x33, 0xe5, 0xfd, 0x2b, 0x4c, 0x9a, 0x9d, 0x4b, 0x2c, 0xfa, - 0xe2, 0x34, 0x53, 0x85, 0x63, 0xb5, 0xd2, 0x04, 0x1c, 0xca, - 0xad, 0x7b, 0x5b, 0x8d, 0xea, 0x3c, 0x24, 0xf2, 0x95, 0x43, - 0xa5, 0x73, 0x14, 0xc2, 0xda, 0x0c, 0x6b, 0xbd, 0xba, 0x6c, - 0x0b, 0xdd, 0xc5, 0x13, 0x74, 0xa2, 0x44, 0x92, 0xf5, 0x23, - 0x3b, 0xed, 0x8a, 0x5c, 0x84, 0x52, 0x35, 0xe3, 0xfb, 0x2d, - 0x4a, 0x9c, 0x7a, 0xac, 0xcb, 0x1d, 0x05, 0xd3, 0xb4, 0x62, - 0x65, 0xb3, 0xd4, 0x02, 0x1a, 0xcc, 0xab, 0x7d, 0x9b, 0x4d, - 0x2a, 0xfc, 0xe4, 0x32, 0x55, 0x83, 0xf8, 0x2e, 0x49, 0x9f, - 0x87, 0x51, 0x36, 0xe0, 0x06, 0xd0, 0xb7, 0x61, 0x79, 0xaf, - 0xc8, 0x1e, 0x19, 0xcf, 0xa8, 0x7e, 0x66, 0xb0, 0xd7, 0x01, - 0xe7, 0x31, 0x56, 0x80, 0x98, 0x4e, 0x29, 0xff, 0x27, 0xf1, - 0x96, 0x40, 0x58, 0x8e, 0xe9, 0x3f, 0xd9, 0x0f, 0x68, 0xbe, - 0xa6, 0x70, 0x17, 0xc1, 0xc6, 0x10, 0x77, 0xa1, 0xb9, 0x6f, - 0x08, 0xde, 0x38, 0xee, 0x89, 0x5f, 0x47, 0x91, 0xf6, 0x20, - 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, - 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9, 0xf1, 0x26, 0x42, 0x95, - 0x8a, 0x5d, 0x39, 0xee, 0x07, 0xd0, 0xb4, 0x63, 0x7c, 0xab, - 0xcf, 0x18, 0xff, 0x28, 0x4c, 0x9b, 0x84, 0x53, 0x37, 0xe0, - 0x09, 0xde, 0xba, 0x6d, 0x72, 0xa5, 0xc1, 0x16, 0x0e, 0xd9, - 0xbd, 0x6a, 0x75, 0xa2, 0xc6, 0x11, 0xf8, 0x2f, 0x4b, 0x9c, - 0x83, 0x54, 0x30, 0xe7, 0xe3, 0x34, 0x50, 0x87, 0x98, 0x4f, - 0x2b, 0xfc, 0x15, 0xc2, 0xa6, 0x71, 0x6e, 0xb9, 0xdd, 0x0a, - 0x12, 0xc5, 0xa1, 0x76, 0x69, 0xbe, 0xda, 0x0d, 0xe4, 0x33, - 0x57, 0x80, 0x9f, 0x48, 0x2c, 0xfb, 0x1c, 0xcb, 0xaf, 0x78, - 0x67, 0xb0, 0xd4, 0x03, 0xea, 0x3d, 0x59, 0x8e, 0x91, 0x46, - 0x22, 0xf5, 0xed, 0x3a, 0x5e, 0x89, 0x96, 0x41, 0x25, 0xf2, - 0x1b, 0xcc, 0xa8, 0x7f, 0x60, 0xb7, 0xd3, 0x04, 0xdb, 0x0c, - 0x68, 0xbf, 0xa0, 0x77, 0x13, 0xc4, 0x2d, 0xfa, 0x9e, 0x49, - 0x56, 0x81, 0xe5, 0x32, 0x2a, 0xfd, 0x99, 0x4e, 0x51, 0x86, - 0xe2, 0x35, 0xdc, 0x0b, 0x6f, 0xb8, 0xa7, 0x70, 0x14, 0xc3, - 0x24, 0xf3, 0x97, 0x40, 0x5f, 0x88, 0xec, 0x3b, 0xd2, 0x05, - 0x61, 0xb6, 0xa9, 0x7e, 0x1a, 0xcd, 0xd5, 0x02, 0x66, 0xb1, - 0xae, 0x79, 0x1d, 0xca, 0x23, 0xf4, 0x90, 0x47, 0x58, 0x8f, - 0xeb, 0x3c, 0x38, 0xef, 0x8b, 0x5c, 0x43, 0x94, 0xf0, 0x27, - 0xce, 0x19, 0x7d, 0xaa, 0xb5, 0x62, 0x06, 0xd1, 0xc9, 0x1e, - 0x7a, 0xad, 0xb2, 0x65, 0x01, 0xd6, 0x3f, 0xe8, 0x8c, 0x5b, - 0x44, 0x93, 0xf7, 0x20, 0xc7, 0x10, 0x74, 0xa3, 0xbc, 0x6b, - 0x0f, 0xd8, 0x31, 0xe6, 0x82, 0x55, 0x4a, 0x9d, 0xf9, 0x2e, - 0x36, 0xe1, 0x85, 0x52, 0x4d, 0x9a, 0xfe, 0x29, 0xc0, 0x17, - 0x73, 0xa4, 0xbb, 0x6c, 0x08, 0xdf, 0x00, 0xd8, 0xad, 0x75, - 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, - 0x64, 0xbc, 0x01, 0xd9, 0xac, 0x74, 0x46, 0x9e, 0xeb, 0x33, - 0x8f, 0x57, 0x22, 0xfa, 0xc8, 0x10, 0x65, 0xbd, 0x02, 0xda, - 0xaf, 0x77, 0x45, 0x9d, 0xe8, 0x30, 0x8c, 0x54, 0x21, 0xf9, - 0xcb, 0x13, 0x66, 0xbe, 0x03, 0xdb, 0xae, 0x76, 0x44, 0x9c, - 0xe9, 0x31, 0x8d, 0x55, 0x20, 0xf8, 0xca, 0x12, 0x67, 0xbf, - 0x04, 0xdc, 0xa9, 0x71, 0x43, 0x9b, 0xee, 0x36, 0x8a, 0x52, - 0x27, 0xff, 0xcd, 0x15, 0x60, 0xb8, 0x05, 0xdd, 0xa8, 0x70, - 0x42, 0x9a, 0xef, 0x37, 0x8b, 0x53, 0x26, 0xfe, 0xcc, 0x14, - 0x61, 0xb9, 0x06, 0xde, 0xab, 0x73, 0x41, 0x99, 0xec, 0x34, - 0x88, 0x50, 0x25, 0xfd, 0xcf, 0x17, 0x62, 0xba, 0x07, 0xdf, - 0xaa, 0x72, 0x40, 0x98, 0xed, 0x35, 0x89, 0x51, 0x24, 0xfc, - 0xce, 0x16, 0x63, 0xbb, 0x08, 0xd0, 0xa5, 0x7d, 0x4f, 0x97, - 0xe2, 0x3a, 0x86, 0x5e, 0x2b, 0xf3, 0xc1, 0x19, 0x6c, 0xb4, - 0x09, 0xd1, 0xa4, 0x7c, 0x4e, 0x96, 0xe3, 0x3b, 0x87, 0x5f, - 0x2a, 0xf2, 0xc0, 0x18, 0x6d, 0xb5, 0x0a, 0xd2, 0xa7, 0x7f, - 0x4d, 0x95, 0xe0, 0x38, 0x84, 0x5c, 0x29, 0xf1, 0xc3, 0x1b, - 0x6e, 0xb6, 0x0b, 0xd3, 0xa6, 0x7e, 0x4c, 0x94, 0xe1, 0x39, - 0x85, 0x5d, 0x28, 0xf0, 0xc2, 0x1a, 0x6f, 0xb7, 0x0c, 0xd4, - 0xa1, 0x79, 0x4b, 0x93, 0xe6, 0x3e, 0x82, 0x5a, 0x2f, 0xf7, - 0xc5, 0x1d, 0x68, 0xb0, 0x0d, 0xd5, 0xa0, 0x78, 0x4a, 0x92, - 0xe7, 0x3f, 0x83, 0x5b, 0x2e, 0xf6, 0xc4, 0x1c, 0x69, 0xb1, - 0x0e, 0xd6, 0xa3, 0x7b, 0x49, 0x91, 0xe4, 0x3c, 0x80, 0x58, - 0x2d, 0xf5, 0xc7, 0x1f, 0x6a, 0xb2, 0x0f, 0xd7, 0xa2, 0x7a, - 0x48, 0x90, 0xe5, 0x3d, 0x81, 0x59, 0x2c, 0xf4, 0xc6, 0x1e, - 0x6b, 0xb3, 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, - 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3, 0x11, 0xc8, - 0xbe, 0x67, 0x52, 0x8b, 0xfd, 0x24, 0x97, 0x4e, 0x38, 0xe1, - 0xd4, 0x0d, 0x7b, 0xa2, 0x22, 0xfb, 0x8d, 0x54, 0x61, 0xb8, - 0xce, 0x17, 0xa4, 0x7d, 0x0b, 0xd2, 0xe7, 0x3e, 0x48, 0x91, - 0x33, 0xea, 0x9c, 0x45, 0x70, 0xa9, 0xdf, 0x06, 0xb5, 0x6c, - 0x1a, 0xc3, 0xf6, 0x2f, 0x59, 0x80, 0x44, 0x9d, 0xeb, 0x32, - 0x07, 0xde, 0xa8, 0x71, 0xc2, 0x1b, 0x6d, 0xb4, 0x81, 0x58, - 0x2e, 0xf7, 0x55, 0x8c, 0xfa, 0x23, 0x16, 0xcf, 0xb9, 0x60, - 0xd3, 0x0a, 0x7c, 0xa5, 0x90, 0x49, 0x3f, 0xe6, 0x66, 0xbf, - 0xc9, 0x10, 0x25, 0xfc, 0x8a, 0x53, 0xe0, 0x39, 0x4f, 0x96, - 0xa3, 0x7a, 0x0c, 0xd5, 0x77, 0xae, 0xd8, 0x01, 0x34, 0xed, - 0x9b, 0x42, 0xf1, 0x28, 0x5e, 0x87, 0xb2, 0x6b, 0x1d, 0xc4, - 0x88, 0x51, 0x27, 0xfe, 0xcb, 0x12, 0x64, 0xbd, 0x0e, 0xd7, - 0xa1, 0x78, 0x4d, 0x94, 0xe2, 0x3b, 0x99, 0x40, 0x36, 0xef, - 0xda, 0x03, 0x75, 0xac, 0x1f, 0xc6, 0xb0, 0x69, 0x5c, 0x85, - 0xf3, 0x2a, 0xaa, 0x73, 0x05, 0xdc, 0xe9, 0x30, 0x46, 0x9f, - 0x2c, 0xf5, 0x83, 0x5a, 0x6f, 0xb6, 0xc0, 0x19, 0xbb, 0x62, - 0x14, 0xcd, 0xf8, 0x21, 0x57, 0x8e, 0x3d, 0xe4, 0x92, 0x4b, - 0x7e, 0xa7, 0xd1, 0x08, 0xcc, 0x15, 0x63, 0xba, 0x8f, 0x56, - 0x20, 0xf9, 0x4a, 0x93, 0xe5, 0x3c, 0x09, 0xd0, 0xa6, 0x7f, - 0xdd, 0x04, 0x72, 0xab, 0x9e, 0x47, 0x31, 0xe8, 0x5b, 0x82, - 0xf4, 0x2d, 0x18, 0xc1, 0xb7, 0x6e, 0xee, 0x37, 0x41, 0x98, - 0xad, 0x74, 0x02, 0xdb, 0x68, 0xb1, 0xc7, 0x1e, 0x2b, 0xf2, - 0x84, 0x5d, 0xff, 0x26, 0x50, 0x89, 0xbc, 0x65, 0x13, 0xca, - 0x79, 0xa0, 0xd6, 0x0f, 0x3a, 0xe3, 0x95, 0x4c, 0x00, 0xda, - 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, - 0xd1, 0x0b, 0x78, 0xa2, 0x21, 0xfb, 0x88, 0x52, 0x6e, 0xb4, - 0xc7, 0x1d, 0xbf, 0x65, 0x16, 0xcc, 0xf0, 0x2a, 0x59, 0x83, - 0x42, 0x98, 0xeb, 0x31, 0x0d, 0xd7, 0xa4, 0x7e, 0xdc, 0x06, - 0x75, 0xaf, 0x93, 0x49, 0x3a, 0xe0, 0x63, 0xb9, 0xca, 0x10, - 0x2c, 0xf6, 0x85, 0x5f, 0xfd, 0x27, 0x54, 0x8e, 0xb2, 0x68, - 0x1b, 0xc1, 0x84, 0x5e, 0x2d, 0xf7, 0xcb, 0x11, 0x62, 0xb8, - 0x1a, 0xc0, 0xb3, 0x69, 0x55, 0x8f, 0xfc, 0x26, 0xa5, 0x7f, - 0x0c, 0xd6, 0xea, 0x30, 0x43, 0x99, 0x3b, 0xe1, 0x92, 0x48, - 0x74, 0xae, 0xdd, 0x07, 0xc6, 0x1c, 0x6f, 0xb5, 0x89, 0x53, - 0x20, 0xfa, 0x58, 0x82, 0xf1, 0x2b, 0x17, 0xcd, 0xbe, 0x64, - 0xe7, 0x3d, 0x4e, 0x94, 0xa8, 0x72, 0x01, 0xdb, 0x79, 0xa3, - 0xd0, 0x0a, 0x36, 0xec, 0x9f, 0x45, 0x15, 0xcf, 0xbc, 0x66, - 0x5a, 0x80, 0xf3, 0x29, 0x8b, 0x51, 0x22, 0xf8, 0xc4, 0x1e, - 0x6d, 0xb7, 0x34, 0xee, 0x9d, 0x47, 0x7b, 0xa1, 0xd2, 0x08, - 0xaa, 0x70, 0x03, 0xd9, 0xe5, 0x3f, 0x4c, 0x96, 0x57, 0x8d, - 0xfe, 0x24, 0x18, 0xc2, 0xb1, 0x6b, 0xc9, 0x13, 0x60, 0xba, - 0x86, 0x5c, 0x2f, 0xf5, 0x76, 0xac, 0xdf, 0x05, 0x39, 0xe3, - 0x90, 0x4a, 0xe8, 0x32, 0x41, 0x9b, 0xa7, 0x7d, 0x0e, 0xd4, - 0x91, 0x4b, 0x38, 0xe2, 0xde, 0x04, 0x77, 0xad, 0x0f, 0xd5, - 0xa6, 0x7c, 0x40, 0x9a, 0xe9, 0x33, 0xb0, 0x6a, 0x19, 0xc3, - 0xff, 0x25, 0x56, 0x8c, 0x2e, 0xf4, 0x87, 0x5d, 0x61, 0xbb, - 0xc8, 0x12, 0xd3, 0x09, 0x7a, 0xa0, 0x9c, 0x46, 0x35, 0xef, - 0x4d, 0x97, 0xe4, 0x3e, 0x02, 0xd8, 0xab, 0x71, 0xf2, 0x28, - 0x5b, 0x81, 0xbd, 0x67, 0x14, 0xce, 0x6c, 0xb6, 0xc5, 0x1f, - 0x23, 0xf9, 0x8a, 0x50, 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, - 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad, - 0x31, 0xea, 0x9a, 0x41, 0x7a, 0xa1, 0xd1, 0x0a, 0xa7, 0x7c, - 0x0c, 0xd7, 0xec, 0x37, 0x47, 0x9c, 0x62, 0xb9, 0xc9, 0x12, - 0x29, 0xf2, 0x82, 0x59, 0xf4, 0x2f, 0x5f, 0x84, 0xbf, 0x64, - 0x14, 0xcf, 0x53, 0x88, 0xf8, 0x23, 0x18, 0xc3, 0xb3, 0x68, - 0xc5, 0x1e, 0x6e, 0xb5, 0x8e, 0x55, 0x25, 0xfe, 0xc4, 0x1f, - 0x6f, 0xb4, 0x8f, 0x54, 0x24, 0xff, 0x52, 0x89, 0xf9, 0x22, - 0x19, 0xc2, 0xb2, 0x69, 0xf5, 0x2e, 0x5e, 0x85, 0xbe, 0x65, - 0x15, 0xce, 0x63, 0xb8, 0xc8, 0x13, 0x28, 0xf3, 0x83, 0x58, - 0xa6, 0x7d, 0x0d, 0xd6, 0xed, 0x36, 0x46, 0x9d, 0x30, 0xeb, - 0x9b, 0x40, 0x7b, 0xa0, 0xd0, 0x0b, 0x97, 0x4c, 0x3c, 0xe7, - 0xdc, 0x07, 0x77, 0xac, 0x01, 0xda, 0xaa, 0x71, 0x4a, 0x91, - 0xe1, 0x3a, 0x95, 0x4e, 0x3e, 0xe5, 0xde, 0x05, 0x75, 0xae, - 0x03, 0xd8, 0xa8, 0x73, 0x48, 0x93, 0xe3, 0x38, 0xa4, 0x7f, - 0x0f, 0xd4, 0xef, 0x34, 0x44, 0x9f, 0x32, 0xe9, 0x99, 0x42, - 0x79, 0xa2, 0xd2, 0x09, 0xf7, 0x2c, 0x5c, 0x87, 0xbc, 0x67, - 0x17, 0xcc, 0x61, 0xba, 0xca, 0x11, 0x2a, 0xf1, 0x81, 0x5a, - 0xc6, 0x1d, 0x6d, 0xb6, 0x8d, 0x56, 0x26, 0xfd, 0x50, 0x8b, - 0xfb, 0x20, 0x1b, 0xc0, 0xb0, 0x6b, 0x51, 0x8a, 0xfa, 0x21, - 0x1a, 0xc1, 0xb1, 0x6a, 0xc7, 0x1c, 0x6c, 0xb7, 0x8c, 0x57, - 0x27, 0xfc, 0x60, 0xbb, 0xcb, 0x10, 0x2b, 0xf0, 0x80, 0x5b, - 0xf6, 0x2d, 0x5d, 0x86, 0xbd, 0x66, 0x16, 0xcd, 0x33, 0xe8, - 0x98, 0x43, 0x78, 0xa3, 0xd3, 0x08, 0xa5, 0x7e, 0x0e, 0xd5, - 0xee, 0x35, 0x45, 0x9e, 0x02, 0xd9, 0xa9, 0x72, 0x49, 0x92, - 0xe2, 0x39, 0x94, 0x4f, 0x3f, 0xe4, 0xdf, 0x04, 0x74, 0xaf, - 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, - 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80, 0x41, 0x9d, 0xe4, 0x38, - 0x16, 0xca, 0xb3, 0x6f, 0xef, 0x33, 0x4a, 0x96, 0xb8, 0x64, - 0x1d, 0xc1, 0x82, 0x5e, 0x27, 0xfb, 0xd5, 0x09, 0x70, 0xac, - 0x2c, 0xf0, 0x89, 0x55, 0x7b, 0xa7, 0xde, 0x02, 0xc3, 0x1f, - 0x66, 0xba, 0x94, 0x48, 0x31, 0xed, 0x6d, 0xb1, 0xc8, 0x14, - 0x3a, 0xe6, 0x9f, 0x43, 0x19, 0xc5, 0xbc, 0x60, 0x4e, 0x92, - 0xeb, 0x37, 0xb7, 0x6b, 0x12, 0xce, 0xe0, 0x3c, 0x45, 0x99, - 0x58, 0x84, 0xfd, 0x21, 0x0f, 0xd3, 0xaa, 0x76, 0xf6, 0x2a, - 0x53, 0x8f, 0xa1, 0x7d, 0x04, 0xd8, 0x9b, 0x47, 0x3e, 0xe2, - 0xcc, 0x10, 0x69, 0xb5, 0x35, 0xe9, 0x90, 0x4c, 0x62, 0xbe, - 0xc7, 0x1b, 0xda, 0x06, 0x7f, 0xa3, 0x8d, 0x51, 0x28, 0xf4, - 0x74, 0xa8, 0xd1, 0x0d, 0x23, 0xff, 0x86, 0x5a, 0x32, 0xee, - 0x97, 0x4b, 0x65, 0xb9, 0xc0, 0x1c, 0x9c, 0x40, 0x39, 0xe5, - 0xcb, 0x17, 0x6e, 0xb2, 0x73, 0xaf, 0xd6, 0x0a, 0x24, 0xf8, - 0x81, 0x5d, 0xdd, 0x01, 0x78, 0xa4, 0x8a, 0x56, 0x2f, 0xf3, - 0xb0, 0x6c, 0x15, 0xc9, 0xe7, 0x3b, 0x42, 0x9e, 0x1e, 0xc2, - 0xbb, 0x67, 0x49, 0x95, 0xec, 0x30, 0xf1, 0x2d, 0x54, 0x88, - 0xa6, 0x7a, 0x03, 0xdf, 0x5f, 0x83, 0xfa, 0x26, 0x08, 0xd4, - 0xad, 0x71, 0x2b, 0xf7, 0x8e, 0x52, 0x7c, 0xa0, 0xd9, 0x05, - 0x85, 0x59, 0x20, 0xfc, 0xd2, 0x0e, 0x77, 0xab, 0x6a, 0xb6, - 0xcf, 0x13, 0x3d, 0xe1, 0x98, 0x44, 0xc4, 0x18, 0x61, 0xbd, - 0x93, 0x4f, 0x36, 0xea, 0xa9, 0x75, 0x0c, 0xd0, 0xfe, 0x22, - 0x5b, 0x87, 0x07, 0xdb, 0xa2, 0x7e, 0x50, 0x8c, 0xf5, 0x29, - 0xe8, 0x34, 0x4d, 0x91, 0xbf, 0x63, 0x1a, 0xc6, 0x46, 0x9a, - 0xe3, 0x3f, 0x11, 0xcd, 0xb4, 0x68, 0x00, 0xdd, 0xa7, 0x7a, - 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, - 0x52, 0x8f, 0x51, 0x8c, 0xf6, 0x2b, 0x02, 0xdf, 0xa5, 0x78, - 0xf7, 0x2a, 0x50, 0x8d, 0xa4, 0x79, 0x03, 0xde, 0xa2, 0x7f, - 0x05, 0xd8, 0xf1, 0x2c, 0x56, 0x8b, 0x04, 0xd9, 0xa3, 0x7e, - 0x57, 0x8a, 0xf0, 0x2d, 0xf3, 0x2e, 0x54, 0x89, 0xa0, 0x7d, - 0x07, 0xda, 0x55, 0x88, 0xf2, 0x2f, 0x06, 0xdb, 0xa1, 0x7c, - 0x59, 0x84, 0xfe, 0x23, 0x0a, 0xd7, 0xad, 0x70, 0xff, 0x22, - 0x58, 0x85, 0xac, 0x71, 0x0b, 0xd6, 0x08, 0xd5, 0xaf, 0x72, - 0x5b, 0x86, 0xfc, 0x21, 0xae, 0x73, 0x09, 0xd4, 0xfd, 0x20, - 0x5a, 0x87, 0xfb, 0x26, 0x5c, 0x81, 0xa8, 0x75, 0x0f, 0xd2, - 0x5d, 0x80, 0xfa, 0x27, 0x0e, 0xd3, 0xa9, 0x74, 0xaa, 0x77, - 0x0d, 0xd0, 0xf9, 0x24, 0x5e, 0x83, 0x0c, 0xd1, 0xab, 0x76, - 0x5f, 0x82, 0xf8, 0x25, 0xb2, 0x6f, 0x15, 0xc8, 0xe1, 0x3c, - 0x46, 0x9b, 0x14, 0xc9, 0xb3, 0x6e, 0x47, 0x9a, 0xe0, 0x3d, - 0xe3, 0x3e, 0x44, 0x99, 0xb0, 0x6d, 0x17, 0xca, 0x45, 0x98, - 0xe2, 0x3f, 0x16, 0xcb, 0xb1, 0x6c, 0x10, 0xcd, 0xb7, 0x6a, - 0x43, 0x9e, 0xe4, 0x39, 0xb6, 0x6b, 0x11, 0xcc, 0xe5, 0x38, - 0x42, 0x9f, 0x41, 0x9c, 0xe6, 0x3b, 0x12, 0xcf, 0xb5, 0x68, - 0xe7, 0x3a, 0x40, 0x9d, 0xb4, 0x69, 0x13, 0xce, 0xeb, 0x36, - 0x4c, 0x91, 0xb8, 0x65, 0x1f, 0xc2, 0x4d, 0x90, 0xea, 0x37, - 0x1e, 0xc3, 0xb9, 0x64, 0xba, 0x67, 0x1d, 0xc0, 0xe9, 0x34, - 0x4e, 0x93, 0x1c, 0xc1, 0xbb, 0x66, 0x4f, 0x92, 0xe8, 0x35, - 0x49, 0x94, 0xee, 0x33, 0x1a, 0xc7, 0xbd, 0x60, 0xef, 0x32, - 0x48, 0x95, 0xbc, 0x61, 0x1b, 0xc6, 0x18, 0xc5, 0xbf, 0x62, - 0x4b, 0x96, 0xec, 0x31, 0xbe, 0x63, 0x19, 0xc4, 0xed, 0x30, - 0x4a, 0x97, 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, - 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e, 0x61, 0xbf, - 0xc0, 0x1e, 0x3e, 0xe0, 0x9f, 0x41, 0xdf, 0x01, 0x7e, 0xa0, - 0x80, 0x5e, 0x21, 0xff, 0xc2, 0x1c, 0x63, 0xbd, 0x9d, 0x43, - 0x3c, 0xe2, 0x7c, 0xa2, 0xdd, 0x03, 0x23, 0xfd, 0x82, 0x5c, - 0xa3, 0x7d, 0x02, 0xdc, 0xfc, 0x22, 0x5d, 0x83, 0x1d, 0xc3, - 0xbc, 0x62, 0x42, 0x9c, 0xe3, 0x3d, 0x99, 0x47, 0x38, 0xe6, - 0xc6, 0x18, 0x67, 0xb9, 0x27, 0xf9, 0x86, 0x58, 0x78, 0xa6, - 0xd9, 0x07, 0xf8, 0x26, 0x59, 0x87, 0xa7, 0x79, 0x06, 0xd8, - 0x46, 0x98, 0xe7, 0x39, 0x19, 0xc7, 0xb8, 0x66, 0x5b, 0x85, - 0xfa, 0x24, 0x04, 0xda, 0xa5, 0x7b, 0xe5, 0x3b, 0x44, 0x9a, - 0xba, 0x64, 0x1b, 0xc5, 0x3a, 0xe4, 0x9b, 0x45, 0x65, 0xbb, - 0xc4, 0x1a, 0x84, 0x5a, 0x25, 0xfb, 0xdb, 0x05, 0x7a, 0xa4, - 0x2f, 0xf1, 0x8e, 0x50, 0x70, 0xae, 0xd1, 0x0f, 0x91, 0x4f, - 0x30, 0xee, 0xce, 0x10, 0x6f, 0xb1, 0x4e, 0x90, 0xef, 0x31, - 0x11, 0xcf, 0xb0, 0x6e, 0xf0, 0x2e, 0x51, 0x8f, 0xaf, 0x71, - 0x0e, 0xd0, 0xed, 0x33, 0x4c, 0x92, 0xb2, 0x6c, 0x13, 0xcd, - 0x53, 0x8d, 0xf2, 0x2c, 0x0c, 0xd2, 0xad, 0x73, 0x8c, 0x52, - 0x2d, 0xf3, 0xd3, 0x0d, 0x72, 0xac, 0x32, 0xec, 0x93, 0x4d, - 0x6d, 0xb3, 0xcc, 0x12, 0xb6, 0x68, 0x17, 0xc9, 0xe9, 0x37, - 0x48, 0x96, 0x08, 0xd6, 0xa9, 0x77, 0x57, 0x89, 0xf6, 0x28, - 0xd7, 0x09, 0x76, 0xa8, 0x88, 0x56, 0x29, 0xf7, 0x69, 0xb7, - 0xc8, 0x16, 0x36, 0xe8, 0x97, 0x49, 0x74, 0xaa, 0xd5, 0x0b, - 0x2b, 0xf5, 0x8a, 0x54, 0xca, 0x14, 0x6b, 0xb5, 0x95, 0x4b, - 0x34, 0xea, 0x15, 0xcb, 0xb4, 0x6a, 0x4a, 0x94, 0xeb, 0x35, - 0xab, 0x75, 0x0a, 0xd4, 0xf4, 0x2a, 0x55, 0x8b, 0x00, 0xdf, - 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, - 0xed, 0x32, 0x4e, 0x91, 0x71, 0xae, 0xd2, 0x0d, 0x2a, 0xf5, - 0x89, 0x56, 0xc7, 0x18, 0x64, 0xbb, 0x9c, 0x43, 0x3f, 0xe0, - 0xe2, 0x3d, 0x41, 0x9e, 0xb9, 0x66, 0x1a, 0xc5, 0x54, 0x8b, - 0xf7, 0x28, 0x0f, 0xd0, 0xac, 0x73, 0x93, 0x4c, 0x30, 0xef, - 0xc8, 0x17, 0x6b, 0xb4, 0x25, 0xfa, 0x86, 0x59, 0x7e, 0xa1, - 0xdd, 0x02, 0xd9, 0x06, 0x7a, 0xa5, 0x82, 0x5d, 0x21, 0xfe, - 0x6f, 0xb0, 0xcc, 0x13, 0x34, 0xeb, 0x97, 0x48, 0xa8, 0x77, - 0x0b, 0xd4, 0xf3, 0x2c, 0x50, 0x8f, 0x1e, 0xc1, 0xbd, 0x62, - 0x45, 0x9a, 0xe6, 0x39, 0x3b, 0xe4, 0x98, 0x47, 0x60, 0xbf, - 0xc3, 0x1c, 0x8d, 0x52, 0x2e, 0xf1, 0xd6, 0x09, 0x75, 0xaa, - 0x4a, 0x95, 0xe9, 0x36, 0x11, 0xce, 0xb2, 0x6d, 0xfc, 0x23, - 0x5f, 0x80, 0xa7, 0x78, 0x04, 0xdb, 0xaf, 0x70, 0x0c, 0xd3, - 0xf4, 0x2b, 0x57, 0x88, 0x19, 0xc6, 0xba, 0x65, 0x42, 0x9d, - 0xe1, 0x3e, 0xde, 0x01, 0x7d, 0xa2, 0x85, 0x5a, 0x26, 0xf9, - 0x68, 0xb7, 0xcb, 0x14, 0x33, 0xec, 0x90, 0x4f, 0x4d, 0x92, - 0xee, 0x31, 0x16, 0xc9, 0xb5, 0x6a, 0xfb, 0x24, 0x58, 0x87, - 0xa0, 0x7f, 0x03, 0xdc, 0x3c, 0xe3, 0x9f, 0x40, 0x67, 0xb8, - 0xc4, 0x1b, 0x8a, 0x55, 0x29, 0xf6, 0xd1, 0x0e, 0x72, 0xad, - 0x76, 0xa9, 0xd5, 0x0a, 0x2d, 0xf2, 0x8e, 0x51, 0xc0, 0x1f, - 0x63, 0xbc, 0x9b, 0x44, 0x38, 0xe7, 0x07, 0xd8, 0xa4, 0x7b, - 0x5c, 0x83, 0xff, 0x20, 0xb1, 0x6e, 0x12, 0xcd, 0xea, 0x35, - 0x49, 0x96, 0x94, 0x4b, 0x37, 0xe8, 0xcf, 0x10, 0x6c, 0xb3, - 0x22, 0xfd, 0x81, 0x5e, 0x79, 0xa6, 0xda, 0x05, 0xe5, 0x3a, - 0x46, 0x99, 0xbe, 0x61, 0x1d, 0xc2, 0x53, 0x8c, 0xf0, 0x2f, - 0x08, 0xd7, 0xab, 0x74, 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, - 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9, - 0xa6, 0x46, 0x7b, 0x9b, 0x01, 0xe1, 0xdc, 0x3c, 0xf5, 0x15, - 0x28, 0xc8, 0x52, 0xb2, 0x8f, 0x6f, 0x51, 0xb1, 0x8c, 0x6c, - 0xf6, 0x16, 0x2b, 0xcb, 0x02, 0xe2, 0xdf, 0x3f, 0xa5, 0x45, - 0x78, 0x98, 0xf7, 0x17, 0x2a, 0xca, 0x50, 0xb0, 0x8d, 0x6d, - 0xa4, 0x44, 0x79, 0x99, 0x03, 0xe3, 0xde, 0x3e, 0xa2, 0x42, - 0x7f, 0x9f, 0x05, 0xe5, 0xd8, 0x38, 0xf1, 0x11, 0x2c, 0xcc, - 0x56, 0xb6, 0x8b, 0x6b, 0x04, 0xe4, 0xd9, 0x39, 0xa3, 0x43, - 0x7e, 0x9e, 0x57, 0xb7, 0x8a, 0x6a, 0xf0, 0x10, 0x2d, 0xcd, - 0xf3, 0x13, 0x2e, 0xce, 0x54, 0xb4, 0x89, 0x69, 0xa0, 0x40, - 0x7d, 0x9d, 0x07, 0xe7, 0xda, 0x3a, 0x55, 0xb5, 0x88, 0x68, - 0xf2, 0x12, 0x2f, 0xcf, 0x06, 0xe6, 0xdb, 0x3b, 0xa1, 0x41, - 0x7c, 0x9c, 0x59, 0xb9, 0x84, 0x64, 0xfe, 0x1e, 0x23, 0xc3, - 0x0a, 0xea, 0xd7, 0x37, 0xad, 0x4d, 0x70, 0x90, 0xff, 0x1f, - 0x22, 0xc2, 0x58, 0xb8, 0x85, 0x65, 0xac, 0x4c, 0x71, 0x91, - 0x0b, 0xeb, 0xd6, 0x36, 0x08, 0xe8, 0xd5, 0x35, 0xaf, 0x4f, - 0x72, 0x92, 0x5b, 0xbb, 0x86, 0x66, 0xfc, 0x1c, 0x21, 0xc1, - 0xae, 0x4e, 0x73, 0x93, 0x09, 0xe9, 0xd4, 0x34, 0xfd, 0x1d, - 0x20, 0xc0, 0x5a, 0xba, 0x87, 0x67, 0xfb, 0x1b, 0x26, 0xc6, - 0x5c, 0xbc, 0x81, 0x61, 0xa8, 0x48, 0x75, 0x95, 0x0f, 0xef, - 0xd2, 0x32, 0x5d, 0xbd, 0x80, 0x60, 0xfa, 0x1a, 0x27, 0xc7, - 0x0e, 0xee, 0xd3, 0x33, 0xa9, 0x49, 0x74, 0x94, 0xaa, 0x4a, - 0x77, 0x97, 0x0d, 0xed, 0xd0, 0x30, 0xf9, 0x19, 0x24, 0xc4, - 0x5e, 0xbe, 0x83, 0x63, 0x0c, 0xec, 0xd1, 0x31, 0xab, 0x4b, - 0x76, 0x96, 0x5f, 0xbf, 0x82, 0x62, 0xf8, 0x18, 0x25, 0xc5, - 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, - 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6, 0xb6, 0x57, 0x69, 0x88, - 0x15, 0xf4, 0xca, 0x2b, 0xed, 0x0c, 0x32, 0xd3, 0x4e, 0xaf, - 0x91, 0x70, 0x71, 0x90, 0xae, 0x4f, 0xd2, 0x33, 0x0d, 0xec, - 0x2a, 0xcb, 0xf5, 0x14, 0x89, 0x68, 0x56, 0xb7, 0xc7, 0x26, - 0x18, 0xf9, 0x64, 0x85, 0xbb, 0x5a, 0x9c, 0x7d, 0x43, 0xa2, - 0x3f, 0xde, 0xe0, 0x01, 0xe2, 0x03, 0x3d, 0xdc, 0x41, 0xa0, - 0x9e, 0x7f, 0xb9, 0x58, 0x66, 0x87, 0x1a, 0xfb, 0xc5, 0x24, - 0x54, 0xb5, 0x8b, 0x6a, 0xf7, 0x16, 0x28, 0xc9, 0x0f, 0xee, - 0xd0, 0x31, 0xac, 0x4d, 0x73, 0x92, 0x93, 0x72, 0x4c, 0xad, - 0x30, 0xd1, 0xef, 0x0e, 0xc8, 0x29, 0x17, 0xf6, 0x6b, 0x8a, - 0xb4, 0x55, 0x25, 0xc4, 0xfa, 0x1b, 0x86, 0x67, 0x59, 0xb8, - 0x7e, 0x9f, 0xa1, 0x40, 0xdd, 0x3c, 0x02, 0xe3, 0xd9, 0x38, - 0x06, 0xe7, 0x7a, 0x9b, 0xa5, 0x44, 0x82, 0x63, 0x5d, 0xbc, - 0x21, 0xc0, 0xfe, 0x1f, 0x6f, 0x8e, 0xb0, 0x51, 0xcc, 0x2d, - 0x13, 0xf2, 0x34, 0xd5, 0xeb, 0x0a, 0x97, 0x76, 0x48, 0xa9, - 0xa8, 0x49, 0x77, 0x96, 0x0b, 0xea, 0xd4, 0x35, 0xf3, 0x12, - 0x2c, 0xcd, 0x50, 0xb1, 0x8f, 0x6e, 0x1e, 0xff, 0xc1, 0x20, - 0xbd, 0x5c, 0x62, 0x83, 0x45, 0xa4, 0x9a, 0x7b, 0xe6, 0x07, - 0x39, 0xd8, 0x3b, 0xda, 0xe4, 0x05, 0x98, 0x79, 0x47, 0xa6, - 0x60, 0x81, 0xbf, 0x5e, 0xc3, 0x22, 0x1c, 0xfd, 0x8d, 0x6c, - 0x52, 0xb3, 0x2e, 0xcf, 0xf1, 0x10, 0xd6, 0x37, 0x09, 0xe8, - 0x75, 0x94, 0xaa, 0x4b, 0x4a, 0xab, 0x95, 0x74, 0xe9, 0x08, - 0x36, 0xd7, 0x11, 0xf0, 0xce, 0x2f, 0xb2, 0x53, 0x6d, 0x8c, - 0xfc, 0x1d, 0x23, 0xc2, 0x5f, 0xbe, 0x80, 0x61, 0xa7, 0x46, - 0x78, 0x99, 0x04, 0xe5, 0xdb, 0x3a, 0x00, 0xe2, 0xd9, 0x3b, - 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, - 0x35, 0xd7, 0x86, 0x64, 0x5f, 0xbd, 0x29, 0xcb, 0xf0, 0x12, - 0xc5, 0x27, 0x1c, 0xfe, 0x6a, 0x88, 0xb3, 0x51, 0x11, 0xf3, - 0xc8, 0x2a, 0xbe, 0x5c, 0x67, 0x85, 0x52, 0xb0, 0x8b, 0x69, - 0xfd, 0x1f, 0x24, 0xc6, 0x97, 0x75, 0x4e, 0xac, 0x38, 0xda, - 0xe1, 0x03, 0xd4, 0x36, 0x0d, 0xef, 0x7b, 0x99, 0xa2, 0x40, - 0x22, 0xc0, 0xfb, 0x19, 0x8d, 0x6f, 0x54, 0xb6, 0x61, 0x83, - 0xb8, 0x5a, 0xce, 0x2c, 0x17, 0xf5, 0xa4, 0x46, 0x7d, 0x9f, - 0x0b, 0xe9, 0xd2, 0x30, 0xe7, 0x05, 0x3e, 0xdc, 0x48, 0xaa, - 0x91, 0x73, 0x33, 0xd1, 0xea, 0x08, 0x9c, 0x7e, 0x45, 0xa7, - 0x70, 0x92, 0xa9, 0x4b, 0xdf, 0x3d, 0x06, 0xe4, 0xb5, 0x57, - 0x6c, 0x8e, 0x1a, 0xf8, 0xc3, 0x21, 0xf6, 0x14, 0x2f, 0xcd, - 0x59, 0xbb, 0x80, 0x62, 0x44, 0xa6, 0x9d, 0x7f, 0xeb, 0x09, - 0x32, 0xd0, 0x07, 0xe5, 0xde, 0x3c, 0xa8, 0x4a, 0x71, 0x93, - 0xc2, 0x20, 0x1b, 0xf9, 0x6d, 0x8f, 0xb4, 0x56, 0x81, 0x63, - 0x58, 0xba, 0x2e, 0xcc, 0xf7, 0x15, 0x55, 0xb7, 0x8c, 0x6e, - 0xfa, 0x18, 0x23, 0xc1, 0x16, 0xf4, 0xcf, 0x2d, 0xb9, 0x5b, - 0x60, 0x82, 0xd3, 0x31, 0x0a, 0xe8, 0x7c, 0x9e, 0xa5, 0x47, - 0x90, 0x72, 0x49, 0xab, 0x3f, 0xdd, 0xe6, 0x04, 0x66, 0x84, - 0xbf, 0x5d, 0xc9, 0x2b, 0x10, 0xf2, 0x25, 0xc7, 0xfc, 0x1e, - 0x8a, 0x68, 0x53, 0xb1, 0xe0, 0x02, 0x39, 0xdb, 0x4f, 0xad, - 0x96, 0x74, 0xa3, 0x41, 0x7a, 0x98, 0x0c, 0xee, 0xd5, 0x37, - 0x77, 0x95, 0xae, 0x4c, 0xd8, 0x3a, 0x01, 0xe3, 0x34, 0xd6, - 0xed, 0x0f, 0x9b, 0x79, 0x42, 0xa0, 0xf1, 0x13, 0x28, 0xca, - 0x5e, 0xbc, 0x87, 0x65, 0xb2, 0x50, 0x6b, 0x89, 0x1d, 0xff, - 0xc4, 0x26, 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, - 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8, 0x96, 0x75, - 0x4d, 0xae, 0x3d, 0xde, 0xe6, 0x05, 0xdd, 0x3e, 0x06, 0xe5, - 0x76, 0x95, 0xad, 0x4e, 0x31, 0xd2, 0xea, 0x09, 0x9a, 0x79, - 0x41, 0xa2, 0x7a, 0x99, 0xa1, 0x42, 0xd1, 0x32, 0x0a, 0xe9, - 0xa7, 0x44, 0x7c, 0x9f, 0x0c, 0xef, 0xd7, 0x34, 0xec, 0x0f, - 0x37, 0xd4, 0x47, 0xa4, 0x9c, 0x7f, 0x62, 0x81, 0xb9, 0x5a, - 0xc9, 0x2a, 0x12, 0xf1, 0x29, 0xca, 0xf2, 0x11, 0x82, 0x61, - 0x59, 0xba, 0xf4, 0x17, 0x2f, 0xcc, 0x5f, 0xbc, 0x84, 0x67, - 0xbf, 0x5c, 0x64, 0x87, 0x14, 0xf7, 0xcf, 0x2c, 0x53, 0xb0, - 0x88, 0x6b, 0xf8, 0x1b, 0x23, 0xc0, 0x18, 0xfb, 0xc3, 0x20, - 0xb3, 0x50, 0x68, 0x8b, 0xc5, 0x26, 0x1e, 0xfd, 0x6e, 0x8d, - 0xb5, 0x56, 0x8e, 0x6d, 0x55, 0xb6, 0x25, 0xc6, 0xfe, 0x1d, - 0xc4, 0x27, 0x1f, 0xfc, 0x6f, 0x8c, 0xb4, 0x57, 0x8f, 0x6c, - 0x54, 0xb7, 0x24, 0xc7, 0xff, 0x1c, 0x52, 0xb1, 0x89, 0x6a, - 0xf9, 0x1a, 0x22, 0xc1, 0x19, 0xfa, 0xc2, 0x21, 0xb2, 0x51, - 0x69, 0x8a, 0xf5, 0x16, 0x2e, 0xcd, 0x5e, 0xbd, 0x85, 0x66, - 0xbe, 0x5d, 0x65, 0x86, 0x15, 0xf6, 0xce, 0x2d, 0x63, 0x80, - 0xb8, 0x5b, 0xc8, 0x2b, 0x13, 0xf0, 0x28, 0xcb, 0xf3, 0x10, - 0x83, 0x60, 0x58, 0xbb, 0xa6, 0x45, 0x7d, 0x9e, 0x0d, 0xee, - 0xd6, 0x35, 0xed, 0x0e, 0x36, 0xd5, 0x46, 0xa5, 0x9d, 0x7e, - 0x30, 0xd3, 0xeb, 0x08, 0x9b, 0x78, 0x40, 0xa3, 0x7b, 0x98, - 0xa0, 0x43, 0xd0, 0x33, 0x0b, 0xe8, 0x97, 0x74, 0x4c, 0xaf, - 0x3c, 0xdf, 0xe7, 0x04, 0xdc, 0x3f, 0x07, 0xe4, 0x77, 0x94, - 0xac, 0x4f, 0x01, 0xe2, 0xda, 0x39, 0xaa, 0x49, 0x71, 0x92, - 0x4a, 0xa9, 0x91, 0x72, 0xe1, 0x02, 0x3a, 0xd9, 0x00, 0xe4, - 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, - 0xc4, 0x20, 0x11, 0xf5, 0xe6, 0x02, 0x33, 0xd7, 0x51, 0xb5, - 0x84, 0x60, 0x95, 0x71, 0x40, 0xa4, 0x22, 0xc6, 0xf7, 0x13, - 0xd1, 0x35, 0x04, 0xe0, 0x66, 0x82, 0xb3, 0x57, 0xa2, 0x46, - 0x77, 0x93, 0x15, 0xf1, 0xc0, 0x24, 0x37, 0xd3, 0xe2, 0x06, - 0x80, 0x64, 0x55, 0xb1, 0x44, 0xa0, 0x91, 0x75, 0xf3, 0x17, - 0x26, 0xc2, 0xbf, 0x5b, 0x6a, 0x8e, 0x08, 0xec, 0xdd, 0x39, - 0xcc, 0x28, 0x19, 0xfd, 0x7b, 0x9f, 0xae, 0x4a, 0x59, 0xbd, - 0x8c, 0x68, 0xee, 0x0a, 0x3b, 0xdf, 0x2a, 0xce, 0xff, 0x1b, - 0x9d, 0x79, 0x48, 0xac, 0x6e, 0x8a, 0xbb, 0x5f, 0xd9, 0x3d, - 0x0c, 0xe8, 0x1d, 0xf9, 0xc8, 0x2c, 0xaa, 0x4e, 0x7f, 0x9b, - 0x88, 0x6c, 0x5d, 0xb9, 0x3f, 0xdb, 0xea, 0x0e, 0xfb, 0x1f, - 0x2e, 0xca, 0x4c, 0xa8, 0x99, 0x7d, 0x63, 0x87, 0xb6, 0x52, - 0xd4, 0x30, 0x01, 0xe5, 0x10, 0xf4, 0xc5, 0x21, 0xa7, 0x43, - 0x72, 0x96, 0x85, 0x61, 0x50, 0xb4, 0x32, 0xd6, 0xe7, 0x03, - 0xf6, 0x12, 0x23, 0xc7, 0x41, 0xa5, 0x94, 0x70, 0xb2, 0x56, - 0x67, 0x83, 0x05, 0xe1, 0xd0, 0x34, 0xc1, 0x25, 0x14, 0xf0, - 0x76, 0x92, 0xa3, 0x47, 0x54, 0xb0, 0x81, 0x65, 0xe3, 0x07, - 0x36, 0xd2, 0x27, 0xc3, 0xf2, 0x16, 0x90, 0x74, 0x45, 0xa1, - 0xdc, 0x38, 0x09, 0xed, 0x6b, 0x8f, 0xbe, 0x5a, 0xaf, 0x4b, - 0x7a, 0x9e, 0x18, 0xfc, 0xcd, 0x29, 0x3a, 0xde, 0xef, 0x0b, - 0x8d, 0x69, 0x58, 0xbc, 0x49, 0xad, 0x9c, 0x78, 0xfe, 0x1a, - 0x2b, 0xcf, 0x0d, 0xe9, 0xd8, 0x3c, 0xba, 0x5e, 0x6f, 0x8b, - 0x7e, 0x9a, 0xab, 0x4f, 0xc9, 0x2d, 0x1c, 0xf8, 0xeb, 0x0f, - 0x3e, 0xda, 0x5c, 0xb8, 0x89, 0x6d, 0x98, 0x7c, 0x4d, 0xa9, - 0x2f, 0xcb, 0xfa, 0x1e, 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, - 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa, - 0xf6, 0x13, 0x21, 0xc4, 0x45, 0xa0, 0x92, 0x77, 0x8d, 0x68, - 0x5a, 0xbf, 0x3e, 0xdb, 0xe9, 0x0c, 0xf1, 0x14, 0x26, 0xc3, - 0x42, 0xa7, 0x95, 0x70, 0x8a, 0x6f, 0x5d, 0xb8, 0x39, 0xdc, - 0xee, 0x0b, 0x07, 0xe2, 0xd0, 0x35, 0xb4, 0x51, 0x63, 0x86, - 0x7c, 0x99, 0xab, 0x4e, 0xcf, 0x2a, 0x18, 0xfd, 0xff, 0x1a, - 0x28, 0xcd, 0x4c, 0xa9, 0x9b, 0x7e, 0x84, 0x61, 0x53, 0xb6, - 0x37, 0xd2, 0xe0, 0x05, 0x09, 0xec, 0xde, 0x3b, 0xba, 0x5f, - 0x6d, 0x88, 0x72, 0x97, 0xa5, 0x40, 0xc1, 0x24, 0x16, 0xf3, - 0x0e, 0xeb, 0xd9, 0x3c, 0xbd, 0x58, 0x6a, 0x8f, 0x75, 0x90, - 0xa2, 0x47, 0xc6, 0x23, 0x11, 0xf4, 0xf8, 0x1d, 0x2f, 0xca, - 0x4b, 0xae, 0x9c, 0x79, 0x83, 0x66, 0x54, 0xb1, 0x30, 0xd5, - 0xe7, 0x02, 0xe3, 0x06, 0x34, 0xd1, 0x50, 0xb5, 0x87, 0x62, - 0x98, 0x7d, 0x4f, 0xaa, 0x2b, 0xce, 0xfc, 0x19, 0x15, 0xf0, - 0xc2, 0x27, 0xa6, 0x43, 0x71, 0x94, 0x6e, 0x8b, 0xb9, 0x5c, - 0xdd, 0x38, 0x0a, 0xef, 0x12, 0xf7, 0xc5, 0x20, 0xa1, 0x44, - 0x76, 0x93, 0x69, 0x8c, 0xbe, 0x5b, 0xda, 0x3f, 0x0d, 0xe8, - 0xe4, 0x01, 0x33, 0xd6, 0x57, 0xb2, 0x80, 0x65, 0x9f, 0x7a, - 0x48, 0xad, 0x2c, 0xc9, 0xfb, 0x1e, 0x1c, 0xf9, 0xcb, 0x2e, - 0xaf, 0x4a, 0x78, 0x9d, 0x67, 0x82, 0xb0, 0x55, 0xd4, 0x31, - 0x03, 0xe6, 0xea, 0x0f, 0x3d, 0xd8, 0x59, 0xbc, 0x8e, 0x6b, - 0x91, 0x74, 0x46, 0xa3, 0x22, 0xc7, 0xf5, 0x10, 0xed, 0x08, - 0x3a, 0xdf, 0x5e, 0xbb, 0x89, 0x6c, 0x96, 0x73, 0x41, 0xa4, - 0x25, 0xc0, 0xf2, 0x17, 0x1b, 0xfe, 0xcc, 0x29, 0xa8, 0x4d, - 0x7f, 0x9a, 0x60, 0x85, 0xb7, 0x52, 0xd3, 0x36, 0x04, 0xe1, - 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, - 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb, 0xc6, 0x20, 0x17, 0xf1, - 0x79, 0x9f, 0xa8, 0x4e, 0xa5, 0x43, 0x74, 0x92, 0x1a, 0xfc, - 0xcb, 0x2d, 0x91, 0x77, 0x40, 0xa6, 0x2e, 0xc8, 0xff, 0x19, - 0xf2, 0x14, 0x23, 0xc5, 0x4d, 0xab, 0x9c, 0x7a, 0x57, 0xb1, - 0x86, 0x60, 0xe8, 0x0e, 0x39, 0xdf, 0x34, 0xd2, 0xe5, 0x03, - 0x8b, 0x6d, 0x5a, 0xbc, 0x3f, 0xd9, 0xee, 0x08, 0x80, 0x66, - 0x51, 0xb7, 0x5c, 0xba, 0x8d, 0x6b, 0xe3, 0x05, 0x32, 0xd4, - 0xf9, 0x1f, 0x28, 0xce, 0x46, 0xa0, 0x97, 0x71, 0x9a, 0x7c, - 0x4b, 0xad, 0x25, 0xc3, 0xf4, 0x12, 0xae, 0x48, 0x7f, 0x99, - 0x11, 0xf7, 0xc0, 0x26, 0xcd, 0x2b, 0x1c, 0xfa, 0x72, 0x94, - 0xa3, 0x45, 0x68, 0x8e, 0xb9, 0x5f, 0xd7, 0x31, 0x06, 0xe0, - 0x0b, 0xed, 0xda, 0x3c, 0xb4, 0x52, 0x65, 0x83, 0x7e, 0x98, - 0xaf, 0x49, 0xc1, 0x27, 0x10, 0xf6, 0x1d, 0xfb, 0xcc, 0x2a, - 0xa2, 0x44, 0x73, 0x95, 0xb8, 0x5e, 0x69, 0x8f, 0x07, 0xe1, - 0xd6, 0x30, 0xdb, 0x3d, 0x0a, 0xec, 0x64, 0x82, 0xb5, 0x53, - 0xef, 0x09, 0x3e, 0xd8, 0x50, 0xb6, 0x81, 0x67, 0x8c, 0x6a, - 0x5d, 0xbb, 0x33, 0xd5, 0xe2, 0x04, 0x29, 0xcf, 0xf8, 0x1e, - 0x96, 0x70, 0x47, 0xa1, 0x4a, 0xac, 0x9b, 0x7d, 0xf5, 0x13, - 0x24, 0xc2, 0x41, 0xa7, 0x90, 0x76, 0xfe, 0x18, 0x2f, 0xc9, - 0x22, 0xc4, 0xf3, 0x15, 0x9d, 0x7b, 0x4c, 0xaa, 0x87, 0x61, - 0x56, 0xb0, 0x38, 0xde, 0xe9, 0x0f, 0xe4, 0x02, 0x35, 0xd3, - 0x5b, 0xbd, 0x8a, 0x6c, 0xd0, 0x36, 0x01, 0xe7, 0x6f, 0x89, - 0xbe, 0x58, 0xb3, 0x55, 0x62, 0x84, 0x0c, 0xea, 0xdd, 0x3b, - 0x16, 0xf0, 0xc7, 0x21, 0xa9, 0x4f, 0x78, 0x9e, 0x75, 0x93, - 0xa4, 0x42, 0xca, 0x2c, 0x1b, 0xfd, 0x00, 0xe7, 0xd3, 0x34, - 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, - 0x03, 0xe4, 0xd6, 0x31, 0x05, 0xe2, 0x6d, 0x8a, 0xbe, 0x59, - 0xbd, 0x5a, 0x6e, 0x89, 0x06, 0xe1, 0xd5, 0x32, 0xb1, 0x56, - 0x62, 0x85, 0x0a, 0xed, 0xd9, 0x3e, 0xda, 0x3d, 0x09, 0xee, - 0x61, 0x86, 0xb2, 0x55, 0x67, 0x80, 0xb4, 0x53, 0xdc, 0x3b, - 0x0f, 0xe8, 0x0c, 0xeb, 0xdf, 0x38, 0xb7, 0x50, 0x64, 0x83, - 0x7f, 0x98, 0xac, 0x4b, 0xc4, 0x23, 0x17, 0xf0, 0x14, 0xf3, - 0xc7, 0x20, 0xaf, 0x48, 0x7c, 0x9b, 0xa9, 0x4e, 0x7a, 0x9d, - 0x12, 0xf5, 0xc1, 0x26, 0xc2, 0x25, 0x11, 0xf6, 0x79, 0x9e, - 0xaa, 0x4d, 0xce, 0x29, 0x1d, 0xfa, 0x75, 0x92, 0xa6, 0x41, - 0xa5, 0x42, 0x76, 0x91, 0x1e, 0xf9, 0xcd, 0x2a, 0x18, 0xff, - 0xcb, 0x2c, 0xa3, 0x44, 0x70, 0x97, 0x73, 0x94, 0xa0, 0x47, - 0xc8, 0x2f, 0x1b, 0xfc, 0xfe, 0x19, 0x2d, 0xca, 0x45, 0xa2, - 0x96, 0x71, 0x95, 0x72, 0x46, 0xa1, 0x2e, 0xc9, 0xfd, 0x1a, - 0x28, 0xcf, 0xfb, 0x1c, 0x93, 0x74, 0x40, 0xa7, 0x43, 0xa4, - 0x90, 0x77, 0xf8, 0x1f, 0x2b, 0xcc, 0x4f, 0xa8, 0x9c, 0x7b, - 0xf4, 0x13, 0x27, 0xc0, 0x24, 0xc3, 0xf7, 0x10, 0x9f, 0x78, - 0x4c, 0xab, 0x99, 0x7e, 0x4a, 0xad, 0x22, 0xc5, 0xf1, 0x16, - 0xf2, 0x15, 0x21, 0xc6, 0x49, 0xae, 0x9a, 0x7d, 0x81, 0x66, - 0x52, 0xb5, 0x3a, 0xdd, 0xe9, 0x0e, 0xea, 0x0d, 0x39, 0xde, - 0x51, 0xb6, 0x82, 0x65, 0x57, 0xb0, 0x84, 0x63, 0xec, 0x0b, - 0x3f, 0xd8, 0x3c, 0xdb, 0xef, 0x08, 0x87, 0x60, 0x54, 0xb3, - 0x30, 0xd7, 0xe3, 0x04, 0x8b, 0x6c, 0x58, 0xbf, 0x5b, 0xbc, - 0x88, 0x6f, 0xe0, 0x07, 0x33, 0xd4, 0xe6, 0x01, 0x35, 0xd2, - 0x5d, 0xba, 0x8e, 0x69, 0x8d, 0x6a, 0x5e, 0xb9, 0x36, 0xd1, - 0xe5, 0x02, 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, - 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1, 0x26, 0xce, - 0xeb, 0x03, 0xa1, 0x49, 0x6c, 0x84, 0x35, 0xdd, 0xf8, 0x10, - 0xb2, 0x5a, 0x7f, 0x97, 0x4c, 0xa4, 0x81, 0x69, 0xcb, 0x23, - 0x06, 0xee, 0x5f, 0xb7, 0x92, 0x7a, 0xd8, 0x30, 0x15, 0xfd, - 0x6a, 0x82, 0xa7, 0x4f, 0xed, 0x05, 0x20, 0xc8, 0x79, 0x91, - 0xb4, 0x5c, 0xfe, 0x16, 0x33, 0xdb, 0x98, 0x70, 0x55, 0xbd, - 0x1f, 0xf7, 0xd2, 0x3a, 0x8b, 0x63, 0x46, 0xae, 0x0c, 0xe4, - 0xc1, 0x29, 0xbe, 0x56, 0x73, 0x9b, 0x39, 0xd1, 0xf4, 0x1c, - 0xad, 0x45, 0x60, 0x88, 0x2a, 0xc2, 0xe7, 0x0f, 0xd4, 0x3c, - 0x19, 0xf1, 0x53, 0xbb, 0x9e, 0x76, 0xc7, 0x2f, 0x0a, 0xe2, - 0x40, 0xa8, 0x8d, 0x65, 0xf2, 0x1a, 0x3f, 0xd7, 0x75, 0x9d, - 0xb8, 0x50, 0xe1, 0x09, 0x2c, 0xc4, 0x66, 0x8e, 0xab, 0x43, - 0x2d, 0xc5, 0xe0, 0x08, 0xaa, 0x42, 0x67, 0x8f, 0x3e, 0xd6, - 0xf3, 0x1b, 0xb9, 0x51, 0x74, 0x9c, 0x0b, 0xe3, 0xc6, 0x2e, - 0x8c, 0x64, 0x41, 0xa9, 0x18, 0xf0, 0xd5, 0x3d, 0x9f, 0x77, - 0x52, 0xba, 0x61, 0x89, 0xac, 0x44, 0xe6, 0x0e, 0x2b, 0xc3, - 0x72, 0x9a, 0xbf, 0x57, 0xf5, 0x1d, 0x38, 0xd0, 0x47, 0xaf, - 0x8a, 0x62, 0xc0, 0x28, 0x0d, 0xe5, 0x54, 0xbc, 0x99, 0x71, - 0xd3, 0x3b, 0x1e, 0xf6, 0xb5, 0x5d, 0x78, 0x90, 0x32, 0xda, - 0xff, 0x17, 0xa6, 0x4e, 0x6b, 0x83, 0x21, 0xc9, 0xec, 0x04, - 0x93, 0x7b, 0x5e, 0xb6, 0x14, 0xfc, 0xd9, 0x31, 0x80, 0x68, - 0x4d, 0xa5, 0x07, 0xef, 0xca, 0x22, 0xf9, 0x11, 0x34, 0xdc, - 0x7e, 0x96, 0xb3, 0x5b, 0xea, 0x02, 0x27, 0xcf, 0x6d, 0x85, - 0xa0, 0x48, 0xdf, 0x37, 0x12, 0xfa, 0x58, 0xb0, 0x95, 0x7d, - 0xcc, 0x24, 0x01, 0xe9, 0x4b, 0xa3, 0x86, 0x6e, 0x00, 0xe9, - 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, - 0x98, 0x71, 0x57, 0xbe, 0x36, 0xdf, 0xf9, 0x10, 0xb5, 0x5c, - 0x7a, 0x93, 0x2d, 0xc4, 0xe2, 0x0b, 0xae, 0x47, 0x61, 0x88, - 0x6c, 0x85, 0xa3, 0x4a, 0xef, 0x06, 0x20, 0xc9, 0x77, 0x9e, - 0xb8, 0x51, 0xf4, 0x1d, 0x3b, 0xd2, 0x5a, 0xb3, 0x95, 0x7c, - 0xd9, 0x30, 0x16, 0xff, 0x41, 0xa8, 0x8e, 0x67, 0xc2, 0x2b, - 0x0d, 0xe4, 0xd8, 0x31, 0x17, 0xfe, 0x5b, 0xb2, 0x94, 0x7d, - 0xc3, 0x2a, 0x0c, 0xe5, 0x40, 0xa9, 0x8f, 0x66, 0xee, 0x07, - 0x21, 0xc8, 0x6d, 0x84, 0xa2, 0x4b, 0xf5, 0x1c, 0x3a, 0xd3, - 0x76, 0x9f, 0xb9, 0x50, 0xb4, 0x5d, 0x7b, 0x92, 0x37, 0xde, - 0xf8, 0x11, 0xaf, 0x46, 0x60, 0x89, 0x2c, 0xc5, 0xe3, 0x0a, - 0x82, 0x6b, 0x4d, 0xa4, 0x01, 0xe8, 0xce, 0x27, 0x99, 0x70, - 0x56, 0xbf, 0x1a, 0xf3, 0xd5, 0x3c, 0xad, 0x44, 0x62, 0x8b, - 0x2e, 0xc7, 0xe1, 0x08, 0xb6, 0x5f, 0x79, 0x90, 0x35, 0xdc, - 0xfa, 0x13, 0x9b, 0x72, 0x54, 0xbd, 0x18, 0xf1, 0xd7, 0x3e, - 0x80, 0x69, 0x4f, 0xa6, 0x03, 0xea, 0xcc, 0x25, 0xc1, 0x28, - 0x0e, 0xe7, 0x42, 0xab, 0x8d, 0x64, 0xda, 0x33, 0x15, 0xfc, - 0x59, 0xb0, 0x96, 0x7f, 0xf7, 0x1e, 0x38, 0xd1, 0x74, 0x9d, - 0xbb, 0x52, 0xec, 0x05, 0x23, 0xca, 0x6f, 0x86, 0xa0, 0x49, - 0x75, 0x9c, 0xba, 0x53, 0xf6, 0x1f, 0x39, 0xd0, 0x6e, 0x87, - 0xa1, 0x48, 0xed, 0x04, 0x22, 0xcb, 0x43, 0xaa, 0x8c, 0x65, - 0xc0, 0x29, 0x0f, 0xe6, 0x58, 0xb1, 0x97, 0x7e, 0xdb, 0x32, - 0x14, 0xfd, 0x19, 0xf0, 0xd6, 0x3f, 0x9a, 0x73, 0x55, 0xbc, - 0x02, 0xeb, 0xcd, 0x24, 0x81, 0x68, 0x4e, 0xa7, 0x2f, 0xc6, - 0xe0, 0x09, 0xac, 0x45, 0x63, 0x8a, 0x34, 0xdd, 0xfb, 0x12, - 0xb7, 0x5e, 0x78, 0x91, 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, - 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf, - 0x06, 0xec, 0xcf, 0x25, 0x89, 0x63, 0x40, 0xaa, 0x05, 0xef, - 0xcc, 0x26, 0x8a, 0x60, 0x43, 0xa9, 0x0c, 0xe6, 0xc5, 0x2f, - 0x83, 0x69, 0x4a, 0xa0, 0x0f, 0xe5, 0xc6, 0x2c, 0x80, 0x6a, - 0x49, 0xa3, 0x0a, 0xe0, 0xc3, 0x29, 0x85, 0x6f, 0x4c, 0xa6, - 0x09, 0xe3, 0xc0, 0x2a, 0x86, 0x6c, 0x4f, 0xa5, 0x18, 0xf2, - 0xd1, 0x3b, 0x97, 0x7d, 0x5e, 0xb4, 0x1b, 0xf1, 0xd2, 0x38, - 0x94, 0x7e, 0x5d, 0xb7, 0x1e, 0xf4, 0xd7, 0x3d, 0x91, 0x7b, - 0x58, 0xb2, 0x1d, 0xf7, 0xd4, 0x3e, 0x92, 0x78, 0x5b, 0xb1, - 0x14, 0xfe, 0xdd, 0x37, 0x9b, 0x71, 0x52, 0xb8, 0x17, 0xfd, - 0xde, 0x34, 0x98, 0x72, 0x51, 0xbb, 0x12, 0xf8, 0xdb, 0x31, - 0x9d, 0x77, 0x54, 0xbe, 0x11, 0xfb, 0xd8, 0x32, 0x9e, 0x74, - 0x57, 0xbd, 0x30, 0xda, 0xf9, 0x13, 0xbf, 0x55, 0x76, 0x9c, - 0x33, 0xd9, 0xfa, 0x10, 0xbc, 0x56, 0x75, 0x9f, 0x36, 0xdc, - 0xff, 0x15, 0xb9, 0x53, 0x70, 0x9a, 0x35, 0xdf, 0xfc, 0x16, - 0xba, 0x50, 0x73, 0x99, 0x3c, 0xd6, 0xf5, 0x1f, 0xb3, 0x59, - 0x7a, 0x90, 0x3f, 0xd5, 0xf6, 0x1c, 0xb0, 0x5a, 0x79, 0x93, - 0x3a, 0xd0, 0xf3, 0x19, 0xb5, 0x5f, 0x7c, 0x96, 0x39, 0xd3, - 0xf0, 0x1a, 0xb6, 0x5c, 0x7f, 0x95, 0x28, 0xc2, 0xe1, 0x0b, - 0xa7, 0x4d, 0x6e, 0x84, 0x2b, 0xc1, 0xe2, 0x08, 0xa4, 0x4e, - 0x6d, 0x87, 0x2e, 0xc4, 0xe7, 0x0d, 0xa1, 0x4b, 0x68, 0x82, - 0x2d, 0xc7, 0xe4, 0x0e, 0xa2, 0x48, 0x6b, 0x81, 0x24, 0xce, - 0xed, 0x07, 0xab, 0x41, 0x62, 0x88, 0x27, 0xcd, 0xee, 0x04, - 0xa8, 0x42, 0x61, 0x8b, 0x22, 0xc8, 0xeb, 0x01, 0xad, 0x47, - 0x64, 0x8e, 0x21, 0xcb, 0xe8, 0x02, 0xae, 0x44, 0x67, 0x8d, - 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, - 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0, 0x16, 0xfd, 0xdd, 0x36, - 0x9d, 0x76, 0x56, 0xbd, 0x1d, 0xf6, 0xd6, 0x3d, 0x96, 0x7d, - 0x5d, 0xb6, 0x2c, 0xc7, 0xe7, 0x0c, 0xa7, 0x4c, 0x6c, 0x87, - 0x27, 0xcc, 0xec, 0x07, 0xac, 0x47, 0x67, 0x8c, 0x3a, 0xd1, - 0xf1, 0x1a, 0xb1, 0x5a, 0x7a, 0x91, 0x31, 0xda, 0xfa, 0x11, - 0xba, 0x51, 0x71, 0x9a, 0x58, 0xb3, 0x93, 0x78, 0xd3, 0x38, - 0x18, 0xf3, 0x53, 0xb8, 0x98, 0x73, 0xd8, 0x33, 0x13, 0xf8, - 0x4e, 0xa5, 0x85, 0x6e, 0xc5, 0x2e, 0x0e, 0xe5, 0x45, 0xae, - 0x8e, 0x65, 0xce, 0x25, 0x05, 0xee, 0x74, 0x9f, 0xbf, 0x54, - 0xff, 0x14, 0x34, 0xdf, 0x7f, 0x94, 0xb4, 0x5f, 0xf4, 0x1f, - 0x3f, 0xd4, 0x62, 0x89, 0xa9, 0x42, 0xe9, 0x02, 0x22, 0xc9, - 0x69, 0x82, 0xa2, 0x49, 0xe2, 0x09, 0x29, 0xc2, 0xb0, 0x5b, - 0x7b, 0x90, 0x3b, 0xd0, 0xf0, 0x1b, 0xbb, 0x50, 0x70, 0x9b, - 0x30, 0xdb, 0xfb, 0x10, 0xa6, 0x4d, 0x6d, 0x86, 0x2d, 0xc6, - 0xe6, 0x0d, 0xad, 0x46, 0x66, 0x8d, 0x26, 0xcd, 0xed, 0x06, - 0x9c, 0x77, 0x57, 0xbc, 0x17, 0xfc, 0xdc, 0x37, 0x97, 0x7c, - 0x5c, 0xb7, 0x1c, 0xf7, 0xd7, 0x3c, 0x8a, 0x61, 0x41, 0xaa, - 0x01, 0xea, 0xca, 0x21, 0x81, 0x6a, 0x4a, 0xa1, 0x0a, 0xe1, - 0xc1, 0x2a, 0xe8, 0x03, 0x23, 0xc8, 0x63, 0x88, 0xa8, 0x43, - 0xe3, 0x08, 0x28, 0xc3, 0x68, 0x83, 0xa3, 0x48, 0xfe, 0x15, - 0x35, 0xde, 0x75, 0x9e, 0xbe, 0x55, 0xf5, 0x1e, 0x3e, 0xd5, - 0x7e, 0x95, 0xb5, 0x5e, 0xc4, 0x2f, 0x0f, 0xe4, 0x4f, 0xa4, - 0x84, 0x6f, 0xcf, 0x24, 0x04, 0xef, 0x44, 0xaf, 0x8f, 0x64, - 0xd2, 0x39, 0x19, 0xf2, 0x59, 0xb2, 0x92, 0x79, 0xd9, 0x32, - 0x12, 0xf9, 0x52, 0xb9, 0x99, 0x72, 0x00, 0xec, 0xc5, 0x29, - 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, - 0x61, 0x8d, 0x66, 0x8a, 0xa3, 0x4f, 0xf1, 0x1d, 0x34, 0xd8, - 0x55, 0xb9, 0x90, 0x7c, 0xc2, 0x2e, 0x07, 0xeb, 0xcc, 0x20, - 0x09, 0xe5, 0x5b, 0xb7, 0x9e, 0x72, 0xff, 0x13, 0x3a, 0xd6, - 0x68, 0x84, 0xad, 0x41, 0xaa, 0x46, 0x6f, 0x83, 0x3d, 0xd1, - 0xf8, 0x14, 0x99, 0x75, 0x5c, 0xb0, 0x0e, 0xe2, 0xcb, 0x27, - 0x85, 0x69, 0x40, 0xac, 0x12, 0xfe, 0xd7, 0x3b, 0xb6, 0x5a, - 0x73, 0x9f, 0x21, 0xcd, 0xe4, 0x08, 0xe3, 0x0f, 0x26, 0xca, - 0x74, 0x98, 0xb1, 0x5d, 0xd0, 0x3c, 0x15, 0xf9, 0x47, 0xab, - 0x82, 0x6e, 0x49, 0xa5, 0x8c, 0x60, 0xde, 0x32, 0x1b, 0xf7, - 0x7a, 0x96, 0xbf, 0x53, 0xed, 0x01, 0x28, 0xc4, 0x2f, 0xc3, - 0xea, 0x06, 0xb8, 0x54, 0x7d, 0x91, 0x1c, 0xf0, 0xd9, 0x35, - 0x8b, 0x67, 0x4e, 0xa2, 0x17, 0xfb, 0xd2, 0x3e, 0x80, 0x6c, - 0x45, 0xa9, 0x24, 0xc8, 0xe1, 0x0d, 0xb3, 0x5f, 0x76, 0x9a, - 0x71, 0x9d, 0xb4, 0x58, 0xe6, 0x0a, 0x23, 0xcf, 0x42, 0xae, - 0x87, 0x6b, 0xd5, 0x39, 0x10, 0xfc, 0xdb, 0x37, 0x1e, 0xf2, - 0x4c, 0xa0, 0x89, 0x65, 0xe8, 0x04, 0x2d, 0xc1, 0x7f, 0x93, - 0xba, 0x56, 0xbd, 0x51, 0x78, 0x94, 0x2a, 0xc6, 0xef, 0x03, - 0x8e, 0x62, 0x4b, 0xa7, 0x19, 0xf5, 0xdc, 0x30, 0x92, 0x7e, - 0x57, 0xbb, 0x05, 0xe9, 0xc0, 0x2c, 0xa1, 0x4d, 0x64, 0x88, - 0x36, 0xda, 0xf3, 0x1f, 0xf4, 0x18, 0x31, 0xdd, 0x63, 0x8f, - 0xa6, 0x4a, 0xc7, 0x2b, 0x02, 0xee, 0x50, 0xbc, 0x95, 0x79, - 0x5e, 0xb2, 0x9b, 0x77, 0xc9, 0x25, 0x0c, 0xe0, 0x6d, 0x81, - 0xa8, 0x44, 0xfa, 0x16, 0x3f, 0xd3, 0x38, 0xd4, 0xfd, 0x11, - 0xaf, 0x43, 0x6a, 0x86, 0x0b, 0xe7, 0xce, 0x22, 0x9c, 0x70, - 0x59, 0xb5, 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, - 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82, 0x76, 0x9b, - 0xb1, 0x5c, 0xe5, 0x08, 0x22, 0xcf, 0x4d, 0xa0, 0x8a, 0x67, - 0xde, 0x33, 0x19, 0xf4, 0xec, 0x01, 0x2b, 0xc6, 0x7f, 0x92, - 0xb8, 0x55, 0xd7, 0x3a, 0x10, 0xfd, 0x44, 0xa9, 0x83, 0x6e, - 0x9a, 0x77, 0x5d, 0xb0, 0x09, 0xe4, 0xce, 0x23, 0xa1, 0x4c, - 0x66, 0x8b, 0x32, 0xdf, 0xf5, 0x18, 0xc5, 0x28, 0x02, 0xef, - 0x56, 0xbb, 0x91, 0x7c, 0xfe, 0x13, 0x39, 0xd4, 0x6d, 0x80, - 0xaa, 0x47, 0xb3, 0x5e, 0x74, 0x99, 0x20, 0xcd, 0xe7, 0x0a, - 0x88, 0x65, 0x4f, 0xa2, 0x1b, 0xf6, 0xdc, 0x31, 0x29, 0xc4, - 0xee, 0x03, 0xba, 0x57, 0x7d, 0x90, 0x12, 0xff, 0xd5, 0x38, - 0x81, 0x6c, 0x46, 0xab, 0x5f, 0xb2, 0x98, 0x75, 0xcc, 0x21, - 0x0b, 0xe6, 0x64, 0x89, 0xa3, 0x4e, 0xf7, 0x1a, 0x30, 0xdd, - 0x97, 0x7a, 0x50, 0xbd, 0x04, 0xe9, 0xc3, 0x2e, 0xac, 0x41, - 0x6b, 0x86, 0x3f, 0xd2, 0xf8, 0x15, 0xe1, 0x0c, 0x26, 0xcb, - 0x72, 0x9f, 0xb5, 0x58, 0xda, 0x37, 0x1d, 0xf0, 0x49, 0xa4, - 0x8e, 0x63, 0x7b, 0x96, 0xbc, 0x51, 0xe8, 0x05, 0x2f, 0xc2, - 0x40, 0xad, 0x87, 0x6a, 0xd3, 0x3e, 0x14, 0xf9, 0x0d, 0xe0, - 0xca, 0x27, 0x9e, 0x73, 0x59, 0xb4, 0x36, 0xdb, 0xf1, 0x1c, - 0xa5, 0x48, 0x62, 0x8f, 0x52, 0xbf, 0x95, 0x78, 0xc1, 0x2c, - 0x06, 0xeb, 0x69, 0x84, 0xae, 0x43, 0xfa, 0x17, 0x3d, 0xd0, - 0x24, 0xc9, 0xe3, 0x0e, 0xb7, 0x5a, 0x70, 0x9d, 0x1f, 0xf2, - 0xd8, 0x35, 0x8c, 0x61, 0x4b, 0xa6, 0xbe, 0x53, 0x79, 0x94, - 0x2d, 0xc0, 0xea, 0x07, 0x85, 0x68, 0x42, 0xaf, 0x16, 0xfb, - 0xd1, 0x3c, 0xc8, 0x25, 0x0f, 0xe2, 0x5b, 0xb6, 0x9c, 0x71, - 0xf3, 0x1e, 0x34, 0xd9, 0x60, 0x8d, 0xa7, 0x4a, 0x00, 0xee, - 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, - 0xbc, 0x52, 0x7d, 0x93, 0x46, 0xa8, 0x87, 0x69, 0xd9, 0x37, - 0x18, 0xf6, 0x65, 0x8b, 0xa4, 0x4a, 0xfa, 0x14, 0x3b, 0xd5, - 0x8c, 0x62, 0x4d, 0xa3, 0x13, 0xfd, 0xd2, 0x3c, 0xaf, 0x41, - 0x6e, 0x80, 0x30, 0xde, 0xf1, 0x1f, 0xca, 0x24, 0x0b, 0xe5, - 0x55, 0xbb, 0x94, 0x7a, 0xe9, 0x07, 0x28, 0xc6, 0x76, 0x98, - 0xb7, 0x59, 0x05, 0xeb, 0xc4, 0x2a, 0x9a, 0x74, 0x5b, 0xb5, - 0x26, 0xc8, 0xe7, 0x09, 0xb9, 0x57, 0x78, 0x96, 0x43, 0xad, - 0x82, 0x6c, 0xdc, 0x32, 0x1d, 0xf3, 0x60, 0x8e, 0xa1, 0x4f, - 0xff, 0x11, 0x3e, 0xd0, 0x89, 0x67, 0x48, 0xa6, 0x16, 0xf8, - 0xd7, 0x39, 0xaa, 0x44, 0x6b, 0x85, 0x35, 0xdb, 0xf4, 0x1a, - 0xcf, 0x21, 0x0e, 0xe0, 0x50, 0xbe, 0x91, 0x7f, 0xec, 0x02, - 0x2d, 0xc3, 0x73, 0x9d, 0xb2, 0x5c, 0x0a, 0xe4, 0xcb, 0x25, - 0x95, 0x7b, 0x54, 0xba, 0x29, 0xc7, 0xe8, 0x06, 0xb6, 0x58, - 0x77, 0x99, 0x4c, 0xa2, 0x8d, 0x63, 0xd3, 0x3d, 0x12, 0xfc, - 0x6f, 0x81, 0xae, 0x40, 0xf0, 0x1e, 0x31, 0xdf, 0x86, 0x68, - 0x47, 0xa9, 0x19, 0xf7, 0xd8, 0x36, 0xa5, 0x4b, 0x64, 0x8a, - 0x3a, 0xd4, 0xfb, 0x15, 0xc0, 0x2e, 0x01, 0xef, 0x5f, 0xb1, - 0x9e, 0x70, 0xe3, 0x0d, 0x22, 0xcc, 0x7c, 0x92, 0xbd, 0x53, - 0x0f, 0xe1, 0xce, 0x20, 0x90, 0x7e, 0x51, 0xbf, 0x2c, 0xc2, - 0xed, 0x03, 0xb3, 0x5d, 0x72, 0x9c, 0x49, 0xa7, 0x88, 0x66, - 0xd6, 0x38, 0x17, 0xf9, 0x6a, 0x84, 0xab, 0x45, 0xf5, 0x1b, - 0x34, 0xda, 0x83, 0x6d, 0x42, 0xac, 0x1c, 0xf2, 0xdd, 0x33, - 0xa0, 0x4e, 0x61, 0x8f, 0x3f, 0xd1, 0xfe, 0x10, 0xc5, 0x2b, - 0x04, 0xea, 0x5a, 0xb4, 0x9b, 0x75, 0xe6, 0x08, 0x27, 0xc9, - 0x79, 0x97, 0xb8, 0x56, 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, - 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c, - 0x56, 0xb9, 0x95, 0x7a, 0xcd, 0x22, 0x0e, 0xe1, 0x7d, 0x92, - 0xbe, 0x51, 0xe6, 0x09, 0x25, 0xca, 0xac, 0x43, 0x6f, 0x80, - 0x37, 0xd8, 0xf4, 0x1b, 0x87, 0x68, 0x44, 0xab, 0x1c, 0xf3, - 0xdf, 0x30, 0xfa, 0x15, 0x39, 0xd6, 0x61, 0x8e, 0xa2, 0x4d, - 0xd1, 0x3e, 0x12, 0xfd, 0x4a, 0xa5, 0x89, 0x66, 0x45, 0xaa, - 0x86, 0x69, 0xde, 0x31, 0x1d, 0xf2, 0x6e, 0x81, 0xad, 0x42, - 0xf5, 0x1a, 0x36, 0xd9, 0x13, 0xfc, 0xd0, 0x3f, 0x88, 0x67, - 0x4b, 0xa4, 0x38, 0xd7, 0xfb, 0x14, 0xa3, 0x4c, 0x60, 0x8f, - 0xe9, 0x06, 0x2a, 0xc5, 0x72, 0x9d, 0xb1, 0x5e, 0xc2, 0x2d, - 0x01, 0xee, 0x59, 0xb6, 0x9a, 0x75, 0xbf, 0x50, 0x7c, 0x93, - 0x24, 0xcb, 0xe7, 0x08, 0x94, 0x7b, 0x57, 0xb8, 0x0f, 0xe0, - 0xcc, 0x23, 0x8a, 0x65, 0x49, 0xa6, 0x11, 0xfe, 0xd2, 0x3d, - 0xa1, 0x4e, 0x62, 0x8d, 0x3a, 0xd5, 0xf9, 0x16, 0xdc, 0x33, - 0x1f, 0xf0, 0x47, 0xa8, 0x84, 0x6b, 0xf7, 0x18, 0x34, 0xdb, - 0x6c, 0x83, 0xaf, 0x40, 0x26, 0xc9, 0xe5, 0x0a, 0xbd, 0x52, - 0x7e, 0x91, 0x0d, 0xe2, 0xce, 0x21, 0x96, 0x79, 0x55, 0xba, - 0x70, 0x9f, 0xb3, 0x5c, 0xeb, 0x04, 0x28, 0xc7, 0x5b, 0xb4, - 0x98, 0x77, 0xc0, 0x2f, 0x03, 0xec, 0xcf, 0x20, 0x0c, 0xe3, - 0x54, 0xbb, 0x97, 0x78, 0xe4, 0x0b, 0x27, 0xc8, 0x7f, 0x90, - 0xbc, 0x53, 0x99, 0x76, 0x5a, 0xb5, 0x02, 0xed, 0xc1, 0x2e, - 0xb2, 0x5d, 0x71, 0x9e, 0x29, 0xc6, 0xea, 0x05, 0x63, 0x8c, - 0xa0, 0x4f, 0xf8, 0x17, 0x3b, 0xd4, 0x48, 0xa7, 0x8b, 0x64, - 0xd3, 0x3c, 0x10, 0xff, 0x35, 0xda, 0xf6, 0x19, 0xae, 0x41, - 0x6d, 0x82, 0x1e, 0xf1, 0xdd, 0x32, 0x85, 0x6a, 0x46, 0xa9, - 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, - 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39, 0xbb, 0x4b, 0x46, 0xb6, - 0x5c, 0xac, 0xa1, 0x51, 0x68, 0x98, 0x95, 0x65, 0x8f, 0x7f, - 0x72, 0x82, 0x6b, 0x9b, 0x96, 0x66, 0x8c, 0x7c, 0x71, 0x81, - 0xb8, 0x48, 0x45, 0xb5, 0x5f, 0xaf, 0xa2, 0x52, 0xd0, 0x20, - 0x2d, 0xdd, 0x37, 0xc7, 0xca, 0x3a, 0x03, 0xf3, 0xfe, 0x0e, - 0xe4, 0x14, 0x19, 0xe9, 0xd6, 0x26, 0x2b, 0xdb, 0x31, 0xc1, - 0xcc, 0x3c, 0x05, 0xf5, 0xf8, 0x08, 0xe2, 0x12, 0x1f, 0xef, - 0x6d, 0x9d, 0x90, 0x60, 0x8a, 0x7a, 0x77, 0x87, 0xbe, 0x4e, - 0x43, 0xb3, 0x59, 0xa9, 0xa4, 0x54, 0xbd, 0x4d, 0x40, 0xb0, - 0x5a, 0xaa, 0xa7, 0x57, 0x6e, 0x9e, 0x93, 0x63, 0x89, 0x79, - 0x74, 0x84, 0x06, 0xf6, 0xfb, 0x0b, 0xe1, 0x11, 0x1c, 0xec, - 0xd5, 0x25, 0x28, 0xd8, 0x32, 0xc2, 0xcf, 0x3f, 0xb1, 0x41, - 0x4c, 0xbc, 0x56, 0xa6, 0xab, 0x5b, 0x62, 0x92, 0x9f, 0x6f, - 0x85, 0x75, 0x78, 0x88, 0x0a, 0xfa, 0xf7, 0x07, 0xed, 0x1d, - 0x10, 0xe0, 0xd9, 0x29, 0x24, 0xd4, 0x3e, 0xce, 0xc3, 0x33, - 0xda, 0x2a, 0x27, 0xd7, 0x3d, 0xcd, 0xc0, 0x30, 0x09, 0xf9, - 0xf4, 0x04, 0xee, 0x1e, 0x13, 0xe3, 0x61, 0x91, 0x9c, 0x6c, - 0x86, 0x76, 0x7b, 0x8b, 0xb2, 0x42, 0x4f, 0xbf, 0x55, 0xa5, - 0xa8, 0x58, 0x67, 0x97, 0x9a, 0x6a, 0x80, 0x70, 0x7d, 0x8d, - 0xb4, 0x44, 0x49, 0xb9, 0x53, 0xa3, 0xae, 0x5e, 0xdc, 0x2c, - 0x21, 0xd1, 0x3b, 0xcb, 0xc6, 0x36, 0x0f, 0xff, 0xf2, 0x02, - 0xe8, 0x18, 0x15, 0xe5, 0x0c, 0xfc, 0xf1, 0x01, 0xeb, 0x1b, - 0x16, 0xe6, 0xdf, 0x2f, 0x22, 0xd2, 0x38, 0xc8, 0xc5, 0x35, - 0xb7, 0x47, 0x4a, 0xba, 0x50, 0xa0, 0xad, 0x5d, 0x64, 0x94, - 0x99, 0x69, 0x83, 0x73, 0x7e, 0x8e, 0x00, 0xf1, 0xff, 0x0e, - 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, - 0xc7, 0x36, 0xab, 0x5a, 0x54, 0xa5, 0x48, 0xb9, 0xb7, 0x46, - 0x70, 0x81, 0x8f, 0x7e, 0x93, 0x62, 0x6c, 0x9d, 0x4b, 0xba, - 0xb4, 0x45, 0xa8, 0x59, 0x57, 0xa6, 0x90, 0x61, 0x6f, 0x9e, - 0x73, 0x82, 0x8c, 0x7d, 0xe0, 0x11, 0x1f, 0xee, 0x03, 0xf2, - 0xfc, 0x0d, 0x3b, 0xca, 0xc4, 0x35, 0xd8, 0x29, 0x27, 0xd6, - 0x96, 0x67, 0x69, 0x98, 0x75, 0x84, 0x8a, 0x7b, 0x4d, 0xbc, - 0xb2, 0x43, 0xae, 0x5f, 0x51, 0xa0, 0x3d, 0xcc, 0xc2, 0x33, - 0xde, 0x2f, 0x21, 0xd0, 0xe6, 0x17, 0x19, 0xe8, 0x05, 0xf4, - 0xfa, 0x0b, 0xdd, 0x2c, 0x22, 0xd3, 0x3e, 0xcf, 0xc1, 0x30, - 0x06, 0xf7, 0xf9, 0x08, 0xe5, 0x14, 0x1a, 0xeb, 0x76, 0x87, - 0x89, 0x78, 0x95, 0x64, 0x6a, 0x9b, 0xad, 0x5c, 0x52, 0xa3, - 0x4e, 0xbf, 0xb1, 0x40, 0x31, 0xc0, 0xce, 0x3f, 0xd2, 0x23, - 0x2d, 0xdc, 0xea, 0x1b, 0x15, 0xe4, 0x09, 0xf8, 0xf6, 0x07, - 0x9a, 0x6b, 0x65, 0x94, 0x79, 0x88, 0x86, 0x77, 0x41, 0xb0, - 0xbe, 0x4f, 0xa2, 0x53, 0x5d, 0xac, 0x7a, 0x8b, 0x85, 0x74, - 0x99, 0x68, 0x66, 0x97, 0xa1, 0x50, 0x5e, 0xaf, 0x42, 0xb3, - 0xbd, 0x4c, 0xd1, 0x20, 0x2e, 0xdf, 0x32, 0xc3, 0xcd, 0x3c, - 0x0a, 0xfb, 0xf5, 0x04, 0xe9, 0x18, 0x16, 0xe7, 0xa7, 0x56, - 0x58, 0xa9, 0x44, 0xb5, 0xbb, 0x4a, 0x7c, 0x8d, 0x83, 0x72, - 0x9f, 0x6e, 0x60, 0x91, 0x0c, 0xfd, 0xf3, 0x02, 0xef, 0x1e, - 0x10, 0xe1, 0xd7, 0x26, 0x28, 0xd9, 0x34, 0xc5, 0xcb, 0x3a, - 0xec, 0x1d, 0x13, 0xe2, 0x0f, 0xfe, 0xf0, 0x01, 0x37, 0xc6, - 0xc8, 0x39, 0xd4, 0x25, 0x2b, 0xda, 0x47, 0xb6, 0xb8, 0x49, - 0xa4, 0x55, 0x5b, 0xaa, 0x9c, 0x6d, 0x63, 0x92, 0x7f, 0x8e, - 0x80, 0x71, 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, - 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27, 0x9b, 0x69, - 0x62, 0x90, 0x74, 0x86, 0x8d, 0x7f, 0x58, 0xaa, 0xa1, 0x53, - 0xb7, 0x45, 0x4e, 0xbc, 0x2b, 0xd9, 0xd2, 0x20, 0xc4, 0x36, - 0x3d, 0xcf, 0xe8, 0x1a, 0x11, 0xe3, 0x07, 0xf5, 0xfe, 0x0c, - 0xb0, 0x42, 0x49, 0xbb, 0x5f, 0xad, 0xa6, 0x54, 0x73, 0x81, - 0x8a, 0x78, 0x9c, 0x6e, 0x65, 0x97, 0x56, 0xa4, 0xaf, 0x5d, - 0xb9, 0x4b, 0x40, 0xb2, 0x95, 0x67, 0x6c, 0x9e, 0x7a, 0x88, - 0x83, 0x71, 0xcd, 0x3f, 0x34, 0xc6, 0x22, 0xd0, 0xdb, 0x29, - 0x0e, 0xfc, 0xf7, 0x05, 0xe1, 0x13, 0x18, 0xea, 0x7d, 0x8f, - 0x84, 0x76, 0x92, 0x60, 0x6b, 0x99, 0xbe, 0x4c, 0x47, 0xb5, - 0x51, 0xa3, 0xa8, 0x5a, 0xe6, 0x14, 0x1f, 0xed, 0x09, 0xfb, - 0xf0, 0x02, 0x25, 0xd7, 0xdc, 0x2e, 0xca, 0x38, 0x33, 0xc1, - 0xac, 0x5e, 0x55, 0xa7, 0x43, 0xb1, 0xba, 0x48, 0x6f, 0x9d, - 0x96, 0x64, 0x80, 0x72, 0x79, 0x8b, 0x37, 0xc5, 0xce, 0x3c, - 0xd8, 0x2a, 0x21, 0xd3, 0xf4, 0x06, 0x0d, 0xff, 0x1b, 0xe9, - 0xe2, 0x10, 0x87, 0x75, 0x7e, 0x8c, 0x68, 0x9a, 0x91, 0x63, - 0x44, 0xb6, 0xbd, 0x4f, 0xab, 0x59, 0x52, 0xa0, 0x1c, 0xee, - 0xe5, 0x17, 0xf3, 0x01, 0x0a, 0xf8, 0xdf, 0x2d, 0x26, 0xd4, - 0x30, 0xc2, 0xc9, 0x3b, 0xfa, 0x08, 0x03, 0xf1, 0x15, 0xe7, - 0xec, 0x1e, 0x39, 0xcb, 0xc0, 0x32, 0xd6, 0x24, 0x2f, 0xdd, - 0x61, 0x93, 0x98, 0x6a, 0x8e, 0x7c, 0x77, 0x85, 0xa2, 0x50, - 0x5b, 0xa9, 0x4d, 0xbf, 0xb4, 0x46, 0xd1, 0x23, 0x28, 0xda, - 0x3e, 0xcc, 0xc7, 0x35, 0x12, 0xe0, 0xeb, 0x19, 0xfd, 0x0f, - 0x04, 0xf6, 0x4a, 0xb8, 0xb3, 0x41, 0xa5, 0x57, 0x5c, 0xae, - 0x89, 0x7b, 0x70, 0x82, 0x66, 0x94, 0x9f, 0x6d, 0x00, 0xf3, - 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, - 0x20, 0xd3, 0xdb, 0x28, 0x8b, 0x78, 0x70, 0x83, 0x60, 0x93, - 0x9b, 0x68, 0x40, 0xb3, 0xbb, 0x48, 0xab, 0x58, 0x50, 0xa3, - 0x0b, 0xf8, 0xf0, 0x03, 0xe0, 0x13, 0x1b, 0xe8, 0xc0, 0x33, - 0x3b, 0xc8, 0x2b, 0xd8, 0xd0, 0x23, 0x80, 0x73, 0x7b, 0x88, - 0x6b, 0x98, 0x90, 0x63, 0x4b, 0xb8, 0xb0, 0x43, 0xa0, 0x53, - 0x5b, 0xa8, 0x16, 0xe5, 0xed, 0x1e, 0xfd, 0x0e, 0x06, 0xf5, - 0xdd, 0x2e, 0x26, 0xd5, 0x36, 0xc5, 0xcd, 0x3e, 0x9d, 0x6e, - 0x66, 0x95, 0x76, 0x85, 0x8d, 0x7e, 0x56, 0xa5, 0xad, 0x5e, - 0xbd, 0x4e, 0x46, 0xb5, 0x1d, 0xee, 0xe6, 0x15, 0xf6, 0x05, - 0x0d, 0xfe, 0xd6, 0x25, 0x2d, 0xde, 0x3d, 0xce, 0xc6, 0x35, - 0x96, 0x65, 0x6d, 0x9e, 0x7d, 0x8e, 0x86, 0x75, 0x5d, 0xae, - 0xa6, 0x55, 0xb6, 0x45, 0x4d, 0xbe, 0x2c, 0xdf, 0xd7, 0x24, - 0xc7, 0x34, 0x3c, 0xcf, 0xe7, 0x14, 0x1c, 0xef, 0x0c, 0xff, - 0xf7, 0x04, 0xa7, 0x54, 0x5c, 0xaf, 0x4c, 0xbf, 0xb7, 0x44, - 0x6c, 0x9f, 0x97, 0x64, 0x87, 0x74, 0x7c, 0x8f, 0x27, 0xd4, - 0xdc, 0x2f, 0xcc, 0x3f, 0x37, 0xc4, 0xec, 0x1f, 0x17, 0xe4, - 0x07, 0xf4, 0xfc, 0x0f, 0xac, 0x5f, 0x57, 0xa4, 0x47, 0xb4, - 0xbc, 0x4f, 0x67, 0x94, 0x9c, 0x6f, 0x8c, 0x7f, 0x77, 0x84, - 0x3a, 0xc9, 0xc1, 0x32, 0xd1, 0x22, 0x2a, 0xd9, 0xf1, 0x02, - 0x0a, 0xf9, 0x1a, 0xe9, 0xe1, 0x12, 0xb1, 0x42, 0x4a, 0xb9, - 0x5a, 0xa9, 0xa1, 0x52, 0x7a, 0x89, 0x81, 0x72, 0x91, 0x62, - 0x6a, 0x99, 0x31, 0xc2, 0xca, 0x39, 0xda, 0x29, 0x21, 0xd2, - 0xfa, 0x09, 0x01, 0xf2, 0x11, 0xe2, 0xea, 0x19, 0xba, 0x49, - 0x41, 0xb2, 0x51, 0xa2, 0xaa, 0x59, 0x71, 0x82, 0x8a, 0x79, - 0x9a, 0x69, 0x61, 0x92, 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, - 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05, - 0xfb, 0x0f, 0x0e, 0xfa, 0x0c, 0xf8, 0xf9, 0x0d, 0x08, 0xfc, - 0xfd, 0x09, 0xff, 0x0b, 0x0a, 0xfe, 0xeb, 0x1f, 0x1e, 0xea, - 0x1c, 0xe8, 0xe9, 0x1d, 0x18, 0xec, 0xed, 0x19, 0xef, 0x1b, - 0x1a, 0xee, 0x10, 0xe4, 0xe5, 0x11, 0xe7, 0x13, 0x12, 0xe6, - 0xe3, 0x17, 0x16, 0xe2, 0x14, 0xe0, 0xe1, 0x15, 0xcb, 0x3f, - 0x3e, 0xca, 0x3c, 0xc8, 0xc9, 0x3d, 0x38, 0xcc, 0xcd, 0x39, - 0xcf, 0x3b, 0x3a, 0xce, 0x30, 0xc4, 0xc5, 0x31, 0xc7, 0x33, - 0x32, 0xc6, 0xc3, 0x37, 0x36, 0xc2, 0x34, 0xc0, 0xc1, 0x35, - 0x20, 0xd4, 0xd5, 0x21, 0xd7, 0x23, 0x22, 0xd6, 0xd3, 0x27, - 0x26, 0xd2, 0x24, 0xd0, 0xd1, 0x25, 0xdb, 0x2f, 0x2e, 0xda, - 0x2c, 0xd8, 0xd9, 0x2d, 0x28, 0xdc, 0xdd, 0x29, 0xdf, 0x2b, - 0x2a, 0xde, 0x8b, 0x7f, 0x7e, 0x8a, 0x7c, 0x88, 0x89, 0x7d, - 0x78, 0x8c, 0x8d, 0x79, 0x8f, 0x7b, 0x7a, 0x8e, 0x70, 0x84, - 0x85, 0x71, 0x87, 0x73, 0x72, 0x86, 0x83, 0x77, 0x76, 0x82, - 0x74, 0x80, 0x81, 0x75, 0x60, 0x94, 0x95, 0x61, 0x97, 0x63, - 0x62, 0x96, 0x93, 0x67, 0x66, 0x92, 0x64, 0x90, 0x91, 0x65, - 0x9b, 0x6f, 0x6e, 0x9a, 0x6c, 0x98, 0x99, 0x6d, 0x68, 0x9c, - 0x9d, 0x69, 0x9f, 0x6b, 0x6a, 0x9e, 0x40, 0xb4, 0xb5, 0x41, - 0xb7, 0x43, 0x42, 0xb6, 0xb3, 0x47, 0x46, 0xb2, 0x44, 0xb0, - 0xb1, 0x45, 0xbb, 0x4f, 0x4e, 0xba, 0x4c, 0xb8, 0xb9, 0x4d, - 0x48, 0xbc, 0xbd, 0x49, 0xbf, 0x4b, 0x4a, 0xbe, 0xab, 0x5f, - 0x5e, 0xaa, 0x5c, 0xa8, 0xa9, 0x5d, 0x58, 0xac, 0xad, 0x59, - 0xaf, 0x5b, 0x5a, 0xae, 0x50, 0xa4, 0xa5, 0x51, 0xa7, 0x53, - 0x52, 0xa6, 0xa3, 0x57, 0x56, 0xa2, 0x54, 0xa0, 0xa1, 0x55, - 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, - 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a, 0xeb, 0x1e, 0x1c, 0xe9, - 0x18, 0xed, 0xef, 0x1a, 0x10, 0xe5, 0xe7, 0x12, 0xe3, 0x16, - 0x14, 0xe1, 0xcb, 0x3e, 0x3c, 0xc9, 0x38, 0xcd, 0xcf, 0x3a, - 0x30, 0xc5, 0xc7, 0x32, 0xc3, 0x36, 0x34, 0xc1, 0x20, 0xd5, - 0xd7, 0x22, 0xd3, 0x26, 0x24, 0xd1, 0xdb, 0x2e, 0x2c, 0xd9, - 0x28, 0xdd, 0xdf, 0x2a, 0x8b, 0x7e, 0x7c, 0x89, 0x78, 0x8d, - 0x8f, 0x7a, 0x70, 0x85, 0x87, 0x72, 0x83, 0x76, 0x74, 0x81, - 0x60, 0x95, 0x97, 0x62, 0x93, 0x66, 0x64, 0x91, 0x9b, 0x6e, - 0x6c, 0x99, 0x68, 0x9d, 0x9f, 0x6a, 0x40, 0xb5, 0xb7, 0x42, - 0xb3, 0x46, 0x44, 0xb1, 0xbb, 0x4e, 0x4c, 0xb9, 0x48, 0xbd, - 0xbf, 0x4a, 0xab, 0x5e, 0x5c, 0xa9, 0x58, 0xad, 0xaf, 0x5a, - 0x50, 0xa5, 0xa7, 0x52, 0xa3, 0x56, 0x54, 0xa1, 0x0b, 0xfe, - 0xfc, 0x09, 0xf8, 0x0d, 0x0f, 0xfa, 0xf0, 0x05, 0x07, 0xf2, - 0x03, 0xf6, 0xf4, 0x01, 0xe0, 0x15, 0x17, 0xe2, 0x13, 0xe6, - 0xe4, 0x11, 0x1b, 0xee, 0xec, 0x19, 0xe8, 0x1d, 0x1f, 0xea, - 0xc0, 0x35, 0x37, 0xc2, 0x33, 0xc6, 0xc4, 0x31, 0x3b, 0xce, - 0xcc, 0x39, 0xc8, 0x3d, 0x3f, 0xca, 0x2b, 0xde, 0xdc, 0x29, - 0xd8, 0x2d, 0x2f, 0xda, 0xd0, 0x25, 0x27, 0xd2, 0x23, 0xd6, - 0xd4, 0x21, 0x80, 0x75, 0x77, 0x82, 0x73, 0x86, 0x84, 0x71, - 0x7b, 0x8e, 0x8c, 0x79, 0x88, 0x7d, 0x7f, 0x8a, 0x6b, 0x9e, - 0x9c, 0x69, 0x98, 0x6d, 0x6f, 0x9a, 0x90, 0x65, 0x67, 0x92, - 0x63, 0x96, 0x94, 0x61, 0x4b, 0xbe, 0xbc, 0x49, 0xb8, 0x4d, - 0x4f, 0xba, 0xb0, 0x45, 0x47, 0xb2, 0x43, 0xb6, 0xb4, 0x41, - 0xa0, 0x55, 0x57, 0xa2, 0x53, 0xa6, 0xa4, 0x51, 0x5b, 0xae, - 0xac, 0x59, 0xa8, 0x5d, 0x5f, 0xaa, 0x00, 0xf6, 0xf1, 0x07, - 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, - 0xed, 0x1b, 0xdb, 0x2d, 0x2a, 0xdc, 0x24, 0xd2, 0xd5, 0x23, - 0x38, 0xce, 0xc9, 0x3f, 0xc7, 0x31, 0x36, 0xc0, 0xab, 0x5d, - 0x5a, 0xac, 0x54, 0xa2, 0xa5, 0x53, 0x48, 0xbe, 0xb9, 0x4f, - 0xb7, 0x41, 0x46, 0xb0, 0x70, 0x86, 0x81, 0x77, 0x8f, 0x79, - 0x7e, 0x88, 0x93, 0x65, 0x62, 0x94, 0x6c, 0x9a, 0x9d, 0x6b, - 0x4b, 0xbd, 0xba, 0x4c, 0xb4, 0x42, 0x45, 0xb3, 0xa8, 0x5e, - 0x59, 0xaf, 0x57, 0xa1, 0xa6, 0x50, 0x90, 0x66, 0x61, 0x97, - 0x6f, 0x99, 0x9e, 0x68, 0x73, 0x85, 0x82, 0x74, 0x8c, 0x7a, - 0x7d, 0x8b, 0xe0, 0x16, 0x11, 0xe7, 0x1f, 0xe9, 0xee, 0x18, - 0x03, 0xf5, 0xf2, 0x04, 0xfc, 0x0a, 0x0d, 0xfb, 0x3b, 0xcd, - 0xca, 0x3c, 0xc4, 0x32, 0x35, 0xc3, 0xd8, 0x2e, 0x29, 0xdf, - 0x27, 0xd1, 0xd6, 0x20, 0x96, 0x60, 0x67, 0x91, 0x69, 0x9f, - 0x98, 0x6e, 0x75, 0x83, 0x84, 0x72, 0x8a, 0x7c, 0x7b, 0x8d, - 0x4d, 0xbb, 0xbc, 0x4a, 0xb2, 0x44, 0x43, 0xb5, 0xae, 0x58, - 0x5f, 0xa9, 0x51, 0xa7, 0xa0, 0x56, 0x3d, 0xcb, 0xcc, 0x3a, - 0xc2, 0x34, 0x33, 0xc5, 0xde, 0x28, 0x2f, 0xd9, 0x21, 0xd7, - 0xd0, 0x26, 0xe6, 0x10, 0x17, 0xe1, 0x19, 0xef, 0xe8, 0x1e, - 0x05, 0xf3, 0xf4, 0x02, 0xfa, 0x0c, 0x0b, 0xfd, 0xdd, 0x2b, - 0x2c, 0xda, 0x22, 0xd4, 0xd3, 0x25, 0x3e, 0xc8, 0xcf, 0x39, - 0xc1, 0x37, 0x30, 0xc6, 0x06, 0xf0, 0xf7, 0x01, 0xf9, 0x0f, - 0x08, 0xfe, 0xe5, 0x13, 0x14, 0xe2, 0x1a, 0xec, 0xeb, 0x1d, - 0x76, 0x80, 0x87, 0x71, 0x89, 0x7f, 0x78, 0x8e, 0x95, 0x63, - 0x64, 0x92, 0x6a, 0x9c, 0x9b, 0x6d, 0xad, 0x5b, 0x5c, 0xaa, - 0x52, 0xa4, 0xa3, 0x55, 0x4e, 0xb8, 0xbf, 0x49, 0xb1, 0x47, - 0x40, 0xb6, 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, - 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14, 0xcb, 0x3c, - 0x38, 0xcf, 0x30, 0xc7, 0xc3, 0x34, 0x20, 0xd7, 0xd3, 0x24, - 0xdb, 0x2c, 0x28, 0xdf, 0x8b, 0x7c, 0x78, 0x8f, 0x70, 0x87, - 0x83, 0x74, 0x60, 0x97, 0x93, 0x64, 0x9b, 0x6c, 0x68, 0x9f, - 0x40, 0xb7, 0xb3, 0x44, 0xbb, 0x4c, 0x48, 0xbf, 0xab, 0x5c, - 0x58, 0xaf, 0x50, 0xa7, 0xa3, 0x54, 0x0b, 0xfc, 0xf8, 0x0f, - 0xf0, 0x07, 0x03, 0xf4, 0xe0, 0x17, 0x13, 0xe4, 0x1b, 0xec, - 0xe8, 0x1f, 0xc0, 0x37, 0x33, 0xc4, 0x3b, 0xcc, 0xc8, 0x3f, - 0x2b, 0xdc, 0xd8, 0x2f, 0xd0, 0x27, 0x23, 0xd4, 0x80, 0x77, - 0x73, 0x84, 0x7b, 0x8c, 0x88, 0x7f, 0x6b, 0x9c, 0x98, 0x6f, - 0x90, 0x67, 0x63, 0x94, 0x4b, 0xbc, 0xb8, 0x4f, 0xb0, 0x47, - 0x43, 0xb4, 0xa0, 0x57, 0x53, 0xa4, 0x5b, 0xac, 0xa8, 0x5f, - 0x16, 0xe1, 0xe5, 0x12, 0xed, 0x1a, 0x1e, 0xe9, 0xfd, 0x0a, - 0x0e, 0xf9, 0x06, 0xf1, 0xf5, 0x02, 0xdd, 0x2a, 0x2e, 0xd9, - 0x26, 0xd1, 0xd5, 0x22, 0x36, 0xc1, 0xc5, 0x32, 0xcd, 0x3a, - 0x3e, 0xc9, 0x9d, 0x6a, 0x6e, 0x99, 0x66, 0x91, 0x95, 0x62, - 0x76, 0x81, 0x85, 0x72, 0x8d, 0x7a, 0x7e, 0x89, 0x56, 0xa1, - 0xa5, 0x52, 0xad, 0x5a, 0x5e, 0xa9, 0xbd, 0x4a, 0x4e, 0xb9, - 0x46, 0xb1, 0xb5, 0x42, 0x1d, 0xea, 0xee, 0x19, 0xe6, 0x11, - 0x15, 0xe2, 0xf6, 0x01, 0x05, 0xf2, 0x0d, 0xfa, 0xfe, 0x09, - 0xd6, 0x21, 0x25, 0xd2, 0x2d, 0xda, 0xde, 0x29, 0x3d, 0xca, - 0xce, 0x39, 0xc6, 0x31, 0x35, 0xc2, 0x96, 0x61, 0x65, 0x92, - 0x6d, 0x9a, 0x9e, 0x69, 0x7d, 0x8a, 0x8e, 0x79, 0x86, 0x71, - 0x75, 0x82, 0x5d, 0xaa, 0xae, 0x59, 0xa6, 0x51, 0x55, 0xa2, - 0xb6, 0x41, 0x45, 0xb2, 0x4d, 0xba, 0xbe, 0x49, 0x00, 0xf8, - 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, - 0x54, 0xac, 0xb9, 0x41, 0x3b, 0xc3, 0xd6, 0x2e, 0xfc, 0x04, - 0x11, 0xe9, 0xa8, 0x50, 0x45, 0xbd, 0x6f, 0x97, 0x82, 0x7a, - 0x76, 0x8e, 0x9b, 0x63, 0xb1, 0x49, 0x5c, 0xa4, 0xe5, 0x1d, - 0x08, 0xf0, 0x22, 0xda, 0xcf, 0x37, 0x4d, 0xb5, 0xa0, 0x58, - 0x8a, 0x72, 0x67, 0x9f, 0xde, 0x26, 0x33, 0xcb, 0x19, 0xe1, - 0xf4, 0x0c, 0xec, 0x14, 0x01, 0xf9, 0x2b, 0xd3, 0xc6, 0x3e, - 0x7f, 0x87, 0x92, 0x6a, 0xb8, 0x40, 0x55, 0xad, 0xd7, 0x2f, - 0x3a, 0xc2, 0x10, 0xe8, 0xfd, 0x05, 0x44, 0xbc, 0xa9, 0x51, - 0x83, 0x7b, 0x6e, 0x96, 0x9a, 0x62, 0x77, 0x8f, 0x5d, 0xa5, - 0xb0, 0x48, 0x09, 0xf1, 0xe4, 0x1c, 0xce, 0x36, 0x23, 0xdb, - 0xa1, 0x59, 0x4c, 0xb4, 0x66, 0x9e, 0x8b, 0x73, 0x32, 0xca, - 0xdf, 0x27, 0xf5, 0x0d, 0x18, 0xe0, 0xc5, 0x3d, 0x28, 0xd0, - 0x02, 0xfa, 0xef, 0x17, 0x56, 0xae, 0xbb, 0x43, 0x91, 0x69, - 0x7c, 0x84, 0xfe, 0x06, 0x13, 0xeb, 0x39, 0xc1, 0xd4, 0x2c, - 0x6d, 0x95, 0x80, 0x78, 0xaa, 0x52, 0x47, 0xbf, 0xb3, 0x4b, - 0x5e, 0xa6, 0x74, 0x8c, 0x99, 0x61, 0x20, 0xd8, 0xcd, 0x35, - 0xe7, 0x1f, 0x0a, 0xf2, 0x88, 0x70, 0x65, 0x9d, 0x4f, 0xb7, - 0xa2, 0x5a, 0x1b, 0xe3, 0xf6, 0x0e, 0xdc, 0x24, 0x31, 0xc9, - 0x29, 0xd1, 0xc4, 0x3c, 0xee, 0x16, 0x03, 0xfb, 0xba, 0x42, - 0x57, 0xaf, 0x7d, 0x85, 0x90, 0x68, 0x12, 0xea, 0xff, 0x07, - 0xd5, 0x2d, 0x38, 0xc0, 0x81, 0x79, 0x6c, 0x94, 0x46, 0xbe, - 0xab, 0x53, 0x5f, 0xa7, 0xb2, 0x4a, 0x98, 0x60, 0x75, 0x8d, - 0xcc, 0x34, 0x21, 0xd9, 0x0b, 0xf3, 0xe6, 0x1e, 0x64, 0x9c, - 0x89, 0x71, 0xa3, 0x5b, 0x4e, 0xb6, 0xf7, 0x0f, 0x1a, 0xe2, - 0x30, 0xc8, 0xdd, 0x25, 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, - 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e, - 0x2b, 0xd2, 0xc4, 0x3d, 0xe8, 0x11, 0x07, 0xfe, 0xb0, 0x49, - 0x5f, 0xa6, 0x73, 0x8a, 0x9c, 0x65, 0x56, 0xaf, 0xb9, 0x40, - 0x95, 0x6c, 0x7a, 0x83, 0xcd, 0x34, 0x22, 0xdb, 0x0e, 0xf7, - 0xe1, 0x18, 0x7d, 0x84, 0x92, 0x6b, 0xbe, 0x47, 0x51, 0xa8, - 0xe6, 0x1f, 0x09, 0xf0, 0x25, 0xdc, 0xca, 0x33, 0xac, 0x55, - 0x43, 0xba, 0x6f, 0x96, 0x80, 0x79, 0x37, 0xce, 0xd8, 0x21, - 0xf4, 0x0d, 0x1b, 0xe2, 0x87, 0x7e, 0x68, 0x91, 0x44, 0xbd, - 0xab, 0x52, 0x1c, 0xe5, 0xf3, 0x0a, 0xdf, 0x26, 0x30, 0xc9, - 0xfa, 0x03, 0x15, 0xec, 0x39, 0xc0, 0xd6, 0x2f, 0x61, 0x98, - 0x8e, 0x77, 0xa2, 0x5b, 0x4d, 0xb4, 0xd1, 0x28, 0x3e, 0xc7, - 0x12, 0xeb, 0xfd, 0x04, 0x4a, 0xb3, 0xa5, 0x5c, 0x89, 0x70, - 0x66, 0x9f, 0x45, 0xbc, 0xaa, 0x53, 0x86, 0x7f, 0x69, 0x90, - 0xde, 0x27, 0x31, 0xc8, 0x1d, 0xe4, 0xf2, 0x0b, 0x6e, 0x97, - 0x81, 0x78, 0xad, 0x54, 0x42, 0xbb, 0xf5, 0x0c, 0x1a, 0xe3, - 0x36, 0xcf, 0xd9, 0x20, 0x13, 0xea, 0xfc, 0x05, 0xd0, 0x29, - 0x3f, 0xc6, 0x88, 0x71, 0x67, 0x9e, 0x4b, 0xb2, 0xa4, 0x5d, - 0x38, 0xc1, 0xd7, 0x2e, 0xfb, 0x02, 0x14, 0xed, 0xa3, 0x5a, - 0x4c, 0xb5, 0x60, 0x99, 0x8f, 0x76, 0xe9, 0x10, 0x06, 0xff, - 0x2a, 0xd3, 0xc5, 0x3c, 0x72, 0x8b, 0x9d, 0x64, 0xb1, 0x48, - 0x5e, 0xa7, 0xc2, 0x3b, 0x2d, 0xd4, 0x01, 0xf8, 0xee, 0x17, - 0x59, 0xa0, 0xb6, 0x4f, 0x9a, 0x63, 0x75, 0x8c, 0xbf, 0x46, - 0x50, 0xa9, 0x7c, 0x85, 0x93, 0x6a, 0x24, 0xdd, 0xcb, 0x32, - 0xe7, 0x1e, 0x08, 0xf1, 0x94, 0x6d, 0x7b, 0x82, 0x57, 0xae, - 0xb8, 0x41, 0x0f, 0xf6, 0xe0, 0x19, 0xcc, 0x35, 0x23, 0xda, - 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, - 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f, 0x1b, 0xe1, 0xf2, 0x08, - 0xd4, 0x2e, 0x3d, 0xc7, 0x98, 0x62, 0x71, 0x8b, 0x57, 0xad, - 0xbe, 0x44, 0x36, 0xcc, 0xdf, 0x25, 0xf9, 0x03, 0x10, 0xea, - 0xb5, 0x4f, 0x5c, 0xa6, 0x7a, 0x80, 0x93, 0x69, 0x2d, 0xd7, - 0xc4, 0x3e, 0xe2, 0x18, 0x0b, 0xf1, 0xae, 0x54, 0x47, 0xbd, - 0x61, 0x9b, 0x88, 0x72, 0x6c, 0x96, 0x85, 0x7f, 0xa3, 0x59, - 0x4a, 0xb0, 0xef, 0x15, 0x06, 0xfc, 0x20, 0xda, 0xc9, 0x33, - 0x77, 0x8d, 0x9e, 0x64, 0xb8, 0x42, 0x51, 0xab, 0xf4, 0x0e, - 0x1d, 0xe7, 0x3b, 0xc1, 0xd2, 0x28, 0x5a, 0xa0, 0xb3, 0x49, - 0x95, 0x6f, 0x7c, 0x86, 0xd9, 0x23, 0x30, 0xca, 0x16, 0xec, - 0xff, 0x05, 0x41, 0xbb, 0xa8, 0x52, 0x8e, 0x74, 0x67, 0x9d, - 0xc2, 0x38, 0x2b, 0xd1, 0x0d, 0xf7, 0xe4, 0x1e, 0xd8, 0x22, - 0x31, 0xcb, 0x17, 0xed, 0xfe, 0x04, 0x5b, 0xa1, 0xb2, 0x48, - 0x94, 0x6e, 0x7d, 0x87, 0xc3, 0x39, 0x2a, 0xd0, 0x0c, 0xf6, - 0xe5, 0x1f, 0x40, 0xba, 0xa9, 0x53, 0x8f, 0x75, 0x66, 0x9c, - 0xee, 0x14, 0x07, 0xfd, 0x21, 0xdb, 0xc8, 0x32, 0x6d, 0x97, - 0x84, 0x7e, 0xa2, 0x58, 0x4b, 0xb1, 0xf5, 0x0f, 0x1c, 0xe6, - 0x3a, 0xc0, 0xd3, 0x29, 0x76, 0x8c, 0x9f, 0x65, 0xb9, 0x43, - 0x50, 0xaa, 0xb4, 0x4e, 0x5d, 0xa7, 0x7b, 0x81, 0x92, 0x68, - 0x37, 0xcd, 0xde, 0x24, 0xf8, 0x02, 0x11, 0xeb, 0xaf, 0x55, - 0x46, 0xbc, 0x60, 0x9a, 0x89, 0x73, 0x2c, 0xd6, 0xc5, 0x3f, - 0xe3, 0x19, 0x0a, 0xf0, 0x82, 0x78, 0x6b, 0x91, 0x4d, 0xb7, - 0xa4, 0x5e, 0x01, 0xfb, 0xe8, 0x12, 0xce, 0x34, 0x27, 0xdd, - 0x99, 0x63, 0x70, 0x8a, 0x56, 0xac, 0xbf, 0x45, 0x1a, 0xe0, - 0xf3, 0x09, 0xd5, 0x2f, 0x3c, 0xc6, 0x00, 0xfb, 0xeb, 0x10, - 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, - 0xab, 0x50, 0x0b, 0xf0, 0xe0, 0x1b, 0xc0, 0x3b, 0x2b, 0xd0, - 0x80, 0x7b, 0x6b, 0x90, 0x4b, 0xb0, 0xa0, 0x5b, 0x16, 0xed, - 0xfd, 0x06, 0xdd, 0x26, 0x36, 0xcd, 0x9d, 0x66, 0x76, 0x8d, - 0x56, 0xad, 0xbd, 0x46, 0x1d, 0xe6, 0xf6, 0x0d, 0xd6, 0x2d, - 0x3d, 0xc6, 0x96, 0x6d, 0x7d, 0x86, 0x5d, 0xa6, 0xb6, 0x4d, - 0x2c, 0xd7, 0xc7, 0x3c, 0xe7, 0x1c, 0x0c, 0xf7, 0xa7, 0x5c, - 0x4c, 0xb7, 0x6c, 0x97, 0x87, 0x7c, 0x27, 0xdc, 0xcc, 0x37, - 0xec, 0x17, 0x07, 0xfc, 0xac, 0x57, 0x47, 0xbc, 0x67, 0x9c, - 0x8c, 0x77, 0x3a, 0xc1, 0xd1, 0x2a, 0xf1, 0x0a, 0x1a, 0xe1, - 0xb1, 0x4a, 0x5a, 0xa1, 0x7a, 0x81, 0x91, 0x6a, 0x31, 0xca, - 0xda, 0x21, 0xfa, 0x01, 0x11, 0xea, 0xba, 0x41, 0x51, 0xaa, - 0x71, 0x8a, 0x9a, 0x61, 0x58, 0xa3, 0xb3, 0x48, 0x93, 0x68, - 0x78, 0x83, 0xd3, 0x28, 0x38, 0xc3, 0x18, 0xe3, 0xf3, 0x08, - 0x53, 0xa8, 0xb8, 0x43, 0x98, 0x63, 0x73, 0x88, 0xd8, 0x23, - 0x33, 0xc8, 0x13, 0xe8, 0xf8, 0x03, 0x4e, 0xb5, 0xa5, 0x5e, - 0x85, 0x7e, 0x6e, 0x95, 0xc5, 0x3e, 0x2e, 0xd5, 0x0e, 0xf5, - 0xe5, 0x1e, 0x45, 0xbe, 0xae, 0x55, 0x8e, 0x75, 0x65, 0x9e, - 0xce, 0x35, 0x25, 0xde, 0x05, 0xfe, 0xee, 0x15, 0x74, 0x8f, - 0x9f, 0x64, 0xbf, 0x44, 0x54, 0xaf, 0xff, 0x04, 0x14, 0xef, - 0x34, 0xcf, 0xdf, 0x24, 0x7f, 0x84, 0x94, 0x6f, 0xb4, 0x4f, - 0x5f, 0xa4, 0xf4, 0x0f, 0x1f, 0xe4, 0x3f, 0xc4, 0xd4, 0x2f, - 0x62, 0x99, 0x89, 0x72, 0xa9, 0x52, 0x42, 0xb9, 0xe9, 0x12, - 0x02, 0xf9, 0x22, 0xd9, 0xc9, 0x32, 0x69, 0x92, 0x82, 0x79, - 0xa2, 0x59, 0x49, 0xb2, 0xe2, 0x19, 0x09, 0xf2, 0x29, 0xd2, - 0xc2, 0x39, 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, - 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d, 0x7b, 0x87, - 0x9e, 0x62, 0xac, 0x50, 0x49, 0xb5, 0xc8, 0x34, 0x2d, 0xd1, - 0x1f, 0xe3, 0xfa, 0x06, 0xf6, 0x0a, 0x13, 0xef, 0x21, 0xdd, - 0xc4, 0x38, 0x45, 0xb9, 0xa0, 0x5c, 0x92, 0x6e, 0x77, 0x8b, - 0x8d, 0x71, 0x68, 0x94, 0x5a, 0xa6, 0xbf, 0x43, 0x3e, 0xc2, - 0xdb, 0x27, 0xe9, 0x15, 0x0c, 0xf0, 0xf1, 0x0d, 0x14, 0xe8, - 0x26, 0xda, 0xc3, 0x3f, 0x42, 0xbe, 0xa7, 0x5b, 0x95, 0x69, - 0x70, 0x8c, 0x8a, 0x76, 0x6f, 0x93, 0x5d, 0xa1, 0xb8, 0x44, - 0x39, 0xc5, 0xdc, 0x20, 0xee, 0x12, 0x0b, 0xf7, 0x07, 0xfb, - 0xe2, 0x1e, 0xd0, 0x2c, 0x35, 0xc9, 0xb4, 0x48, 0x51, 0xad, - 0x63, 0x9f, 0x86, 0x7a, 0x7c, 0x80, 0x99, 0x65, 0xab, 0x57, - 0x4e, 0xb2, 0xcf, 0x33, 0x2a, 0xd6, 0x18, 0xe4, 0xfd, 0x01, - 0xff, 0x03, 0x1a, 0xe6, 0x28, 0xd4, 0xcd, 0x31, 0x4c, 0xb0, - 0xa9, 0x55, 0x9b, 0x67, 0x7e, 0x82, 0x84, 0x78, 0x61, 0x9d, - 0x53, 0xaf, 0xb6, 0x4a, 0x37, 0xcb, 0xd2, 0x2e, 0xe0, 0x1c, - 0x05, 0xf9, 0x09, 0xf5, 0xec, 0x10, 0xde, 0x22, 0x3b, 0xc7, - 0xba, 0x46, 0x5f, 0xa3, 0x6d, 0x91, 0x88, 0x74, 0x72, 0x8e, - 0x97, 0x6b, 0xa5, 0x59, 0x40, 0xbc, 0xc1, 0x3d, 0x24, 0xd8, - 0x16, 0xea, 0xf3, 0x0f, 0x0e, 0xf2, 0xeb, 0x17, 0xd9, 0x25, - 0x3c, 0xc0, 0xbd, 0x41, 0x58, 0xa4, 0x6a, 0x96, 0x8f, 0x73, - 0x75, 0x89, 0x90, 0x6c, 0xa2, 0x5e, 0x47, 0xbb, 0xc6, 0x3a, - 0x23, 0xdf, 0x11, 0xed, 0xf4, 0x08, 0xf8, 0x04, 0x1d, 0xe1, - 0x2f, 0xd3, 0xca, 0x36, 0x4b, 0xb7, 0xae, 0x52, 0x9c, 0x60, - 0x79, 0x85, 0x83, 0x7f, 0x66, 0x9a, 0x54, 0xa8, 0xb1, 0x4d, - 0x30, 0xcc, 0xd5, 0x29, 0xe7, 0x1b, 0x02, 0xfe, 0x00, 0xfd, - 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, - 0x68, 0x95, 0x8f, 0x72, 0x6b, 0x96, 0x8c, 0x71, 0xb8, 0x45, - 0x5f, 0xa2, 0xd0, 0x2d, 0x37, 0xca, 0x03, 0xfe, 0xe4, 0x19, - 0xd6, 0x2b, 0x31, 0xcc, 0x05, 0xf8, 0xe2, 0x1f, 0x6d, 0x90, - 0x8a, 0x77, 0xbe, 0x43, 0x59, 0xa4, 0xbd, 0x40, 0x5a, 0xa7, - 0x6e, 0x93, 0x89, 0x74, 0x06, 0xfb, 0xe1, 0x1c, 0xd5, 0x28, - 0x32, 0xcf, 0xb1, 0x4c, 0x56, 0xab, 0x62, 0x9f, 0x85, 0x78, - 0x0a, 0xf7, 0xed, 0x10, 0xd9, 0x24, 0x3e, 0xc3, 0xda, 0x27, - 0x3d, 0xc0, 0x09, 0xf4, 0xee, 0x13, 0x61, 0x9c, 0x86, 0x7b, - 0xb2, 0x4f, 0x55, 0xa8, 0x67, 0x9a, 0x80, 0x7d, 0xb4, 0x49, - 0x53, 0xae, 0xdc, 0x21, 0x3b, 0xc6, 0x0f, 0xf2, 0xe8, 0x15, - 0x0c, 0xf1, 0xeb, 0x16, 0xdf, 0x22, 0x38, 0xc5, 0xb7, 0x4a, - 0x50, 0xad, 0x64, 0x99, 0x83, 0x7e, 0x7f, 0x82, 0x98, 0x65, - 0xac, 0x51, 0x4b, 0xb6, 0xc4, 0x39, 0x23, 0xde, 0x17, 0xea, - 0xf0, 0x0d, 0x14, 0xe9, 0xf3, 0x0e, 0xc7, 0x3a, 0x20, 0xdd, - 0xaf, 0x52, 0x48, 0xb5, 0x7c, 0x81, 0x9b, 0x66, 0xa9, 0x54, - 0x4e, 0xb3, 0x7a, 0x87, 0x9d, 0x60, 0x12, 0xef, 0xf5, 0x08, - 0xc1, 0x3c, 0x26, 0xdb, 0xc2, 0x3f, 0x25, 0xd8, 0x11, 0xec, - 0xf6, 0x0b, 0x79, 0x84, 0x9e, 0x63, 0xaa, 0x57, 0x4d, 0xb0, - 0xce, 0x33, 0x29, 0xd4, 0x1d, 0xe0, 0xfa, 0x07, 0x75, 0x88, - 0x92, 0x6f, 0xa6, 0x5b, 0x41, 0xbc, 0xa5, 0x58, 0x42, 0xbf, - 0x76, 0x8b, 0x91, 0x6c, 0x1e, 0xe3, 0xf9, 0x04, 0xcd, 0x30, - 0x2a, 0xd7, 0x18, 0xe5, 0xff, 0x02, 0xcb, 0x36, 0x2c, 0xd1, - 0xa3, 0x5e, 0x44, 0xb9, 0x70, 0x8d, 0x97, 0x6a, 0x73, 0x8e, - 0x94, 0x69, 0xa0, 0x5d, 0x47, 0xba, 0xc8, 0x35, 0x2f, 0xd2, - 0x1b, 0xe6, 0xfc, 0x01, 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, - 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63, - 0x5b, 0xa5, 0xba, 0x44, 0x84, 0x7a, 0x65, 0x9b, 0xf8, 0x06, - 0x19, 0xe7, 0x27, 0xd9, 0xc6, 0x38, 0xb6, 0x48, 0x57, 0xa9, - 0x69, 0x97, 0x88, 0x76, 0x15, 0xeb, 0xf4, 0x0a, 0xca, 0x34, - 0x2b, 0xd5, 0xed, 0x13, 0x0c, 0xf2, 0x32, 0xcc, 0xd3, 0x2d, - 0x4e, 0xb0, 0xaf, 0x51, 0x91, 0x6f, 0x70, 0x8e, 0x71, 0x8f, - 0x90, 0x6e, 0xae, 0x50, 0x4f, 0xb1, 0xd2, 0x2c, 0x33, 0xcd, - 0x0d, 0xf3, 0xec, 0x12, 0x2a, 0xd4, 0xcb, 0x35, 0xf5, 0x0b, - 0x14, 0xea, 0x89, 0x77, 0x68, 0x96, 0x56, 0xa8, 0xb7, 0x49, - 0xc7, 0x39, 0x26, 0xd8, 0x18, 0xe6, 0xf9, 0x07, 0x64, 0x9a, - 0x85, 0x7b, 0xbb, 0x45, 0x5a, 0xa4, 0x9c, 0x62, 0x7d, 0x83, - 0x43, 0xbd, 0xa2, 0x5c, 0x3f, 0xc1, 0xde, 0x20, 0xe0, 0x1e, - 0x01, 0xff, 0xe2, 0x1c, 0x03, 0xfd, 0x3d, 0xc3, 0xdc, 0x22, - 0x41, 0xbf, 0xa0, 0x5e, 0x9e, 0x60, 0x7f, 0x81, 0xb9, 0x47, - 0x58, 0xa6, 0x66, 0x98, 0x87, 0x79, 0x1a, 0xe4, 0xfb, 0x05, - 0xc5, 0x3b, 0x24, 0xda, 0x54, 0xaa, 0xb5, 0x4b, 0x8b, 0x75, - 0x6a, 0x94, 0xf7, 0x09, 0x16, 0xe8, 0x28, 0xd6, 0xc9, 0x37, - 0x0f, 0xf1, 0xee, 0x10, 0xd0, 0x2e, 0x31, 0xcf, 0xac, 0x52, - 0x4d, 0xb3, 0x73, 0x8d, 0x92, 0x6c, 0x93, 0x6d, 0x72, 0x8c, - 0x4c, 0xb2, 0xad, 0x53, 0x30, 0xce, 0xd1, 0x2f, 0xef, 0x11, - 0x0e, 0xf0, 0xc8, 0x36, 0x29, 0xd7, 0x17, 0xe9, 0xf6, 0x08, - 0x6b, 0x95, 0x8a, 0x74, 0xb4, 0x4a, 0x55, 0xab, 0x25, 0xdb, - 0xc4, 0x3a, 0xfa, 0x04, 0x1b, 0xe5, 0x86, 0x78, 0x67, 0x99, - 0x59, 0xa7, 0xb8, 0x46, 0x7e, 0x80, 0x9f, 0x61, 0xa1, 0x5f, - 0x40, 0xbe, 0xdd, 0x23, 0x3c, 0xc2, 0x02, 0xfc, 0xe3, 0x1d, - 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, - 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c, 0x4b, 0xb4, 0xa8, 0x57, - 0x90, 0x6f, 0x73, 0x8c, 0xe0, 0x1f, 0x03, 0xfc, 0x3b, 0xc4, - 0xd8, 0x27, 0x96, 0x69, 0x75, 0x8a, 0x4d, 0xb2, 0xae, 0x51, - 0x3d, 0xc2, 0xde, 0x21, 0xe6, 0x19, 0x05, 0xfa, 0xdd, 0x22, - 0x3e, 0xc1, 0x06, 0xf9, 0xe5, 0x1a, 0x76, 0x89, 0x95, 0x6a, - 0xad, 0x52, 0x4e, 0xb1, 0x31, 0xce, 0xd2, 0x2d, 0xea, 0x15, - 0x09, 0xf6, 0x9a, 0x65, 0x79, 0x86, 0x41, 0xbe, 0xa2, 0x5d, - 0x7a, 0x85, 0x99, 0x66, 0xa1, 0x5e, 0x42, 0xbd, 0xd1, 0x2e, - 0x32, 0xcd, 0x0a, 0xf5, 0xe9, 0x16, 0xa7, 0x58, 0x44, 0xbb, - 0x7c, 0x83, 0x9f, 0x60, 0x0c, 0xf3, 0xef, 0x10, 0xd7, 0x28, - 0x34, 0xcb, 0xec, 0x13, 0x0f, 0xf0, 0x37, 0xc8, 0xd4, 0x2b, - 0x47, 0xb8, 0xa4, 0x5b, 0x9c, 0x63, 0x7f, 0x80, 0x62, 0x9d, - 0x81, 0x7e, 0xb9, 0x46, 0x5a, 0xa5, 0xc9, 0x36, 0x2a, 0xd5, - 0x12, 0xed, 0xf1, 0x0e, 0x29, 0xd6, 0xca, 0x35, 0xf2, 0x0d, - 0x11, 0xee, 0x82, 0x7d, 0x61, 0x9e, 0x59, 0xa6, 0xba, 0x45, - 0xf4, 0x0b, 0x17, 0xe8, 0x2f, 0xd0, 0xcc, 0x33, 0x5f, 0xa0, - 0xbc, 0x43, 0x84, 0x7b, 0x67, 0x98, 0xbf, 0x40, 0x5c, 0xa3, - 0x64, 0x9b, 0x87, 0x78, 0x14, 0xeb, 0xf7, 0x08, 0xcf, 0x30, - 0x2c, 0xd3, 0x53, 0xac, 0xb0, 0x4f, 0x88, 0x77, 0x6b, 0x94, - 0xf8, 0x07, 0x1b, 0xe4, 0x23, 0xdc, 0xc0, 0x3f, 0x18, 0xe7, - 0xfb, 0x04, 0xc3, 0x3c, 0x20, 0xdf, 0xb3, 0x4c, 0x50, 0xaf, - 0x68, 0x97, 0x8b, 0x74, 0xc5, 0x3a, 0x26, 0xd9, 0x1e, 0xe1, - 0xfd, 0x02, 0x6e, 0x91, 0x8d, 0x72, 0xb5, 0x4a, 0x56, 0xa9, - 0x8e, 0x71, 0x6d, 0x92, 0x55, 0xaa, 0xb6, 0x49, 0x25, 0xda, - 0xc6, 0x39, 0xfe, 0x01, 0x1d, 0xe2 -}; - -unsigned char gf_inv_table_base[] = { - 0x00, 0x01, 0x8e, 0xf4, 0x47, 0xa7, 0x7a, 0xba, 0xad, 0x9d, - 0xdd, 0x98, 0x3d, 0xaa, 0x5d, 0x96, 0xd8, 0x72, 0xc0, 0x58, - 0xe0, 0x3e, 0x4c, 0x66, 0x90, 0xde, 0x55, 0x80, 0xa0, 0x83, - 0x4b, 0x2a, 0x6c, 0xed, 0x39, 0x51, 0x60, 0x56, 0x2c, 0x8a, - 0x70, 0xd0, 0x1f, 0x4a, 0x26, 0x8b, 0x33, 0x6e, 0x48, 0x89, - 0x6f, 0x2e, 0xa4, 0xc3, 0x40, 0x5e, 0x50, 0x22, 0xcf, 0xa9, - 0xab, 0x0c, 0x15, 0xe1, 0x36, 0x5f, 0xf8, 0xd5, 0x92, 0x4e, - 0xa6, 0x04, 0x30, 0x88, 0x2b, 0x1e, 0x16, 0x67, 0x45, 0x93, - 0x38, 0x23, 0x68, 0x8c, 0x81, 0x1a, 0x25, 0x61, 0x13, 0xc1, - 0xcb, 0x63, 0x97, 0x0e, 0x37, 0x41, 0x24, 0x57, 0xca, 0x5b, - 0xb9, 0xc4, 0x17, 0x4d, 0x52, 0x8d, 0xef, 0xb3, 0x20, 0xec, - 0x2f, 0x32, 0x28, 0xd1, 0x11, 0xd9, 0xe9, 0xfb, 0xda, 0x79, - 0xdb, 0x77, 0x06, 0xbb, 0x84, 0xcd, 0xfe, 0xfc, 0x1b, 0x54, - 0xa1, 0x1d, 0x7c, 0xcc, 0xe4, 0xb0, 0x49, 0x31, 0x27, 0x2d, - 0x53, 0x69, 0x02, 0xf5, 0x18, 0xdf, 0x44, 0x4f, 0x9b, 0xbc, - 0x0f, 0x5c, 0x0b, 0xdc, 0xbd, 0x94, 0xac, 0x09, 0xc7, 0xa2, - 0x1c, 0x82, 0x9f, 0xc6, 0x34, 0xc2, 0x46, 0x05, 0xce, 0x3b, - 0x0d, 0x3c, 0x9c, 0x08, 0xbe, 0xb7, 0x87, 0xe5, 0xee, 0x6b, - 0xeb, 0xf2, 0xbf, 0xaf, 0xc5, 0x64, 0x07, 0x7b, 0x95, 0x9a, - 0xae, 0xb6, 0x12, 0x59, 0xa5, 0x35, 0x65, 0xb8, 0xa3, 0x9e, - 0xd2, 0xf7, 0x62, 0x5a, 0x85, 0x7d, 0xa8, 0x3a, 0x29, 0x71, - 0xc8, 0xf6, 0xf9, 0x43, 0xd7, 0xd6, 0x10, 0x73, 0x76, 0x78, - 0x99, 0x0a, 0x19, 0x91, 0x14, 0x3f, 0xe6, 0xf0, 0x86, 0xb1, - 0xe2, 0xf1, 0xfa, 0x74, 0xf3, 0xb4, 0x6d, 0x21, 0xb2, 0x6a, - 0xe3, 0xe7, 0xb5, 0xea, 0x03, 0x8f, 0xd3, 0xc9, 0x42, 0xd4, - 0xe8, 0x75, 0x7f, 0xff, 0x7e, 0xfd -}; -#endif // GF_LARGE_TABLES - -#endif //_EC_BASE_H_ diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_highlevel_func.c b/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_highlevel_func.c deleted file mode 100644 index fe2cdc9ca..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_highlevel_func.c +++ /dev/null @@ -1,267 +0,0 @@ -/********************************************************************** - Copyright(c) 2011-2015 Intel Corporation All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************/ -#include -#include "erasure_code.h" -#include "types.h" - -void ec_init_tables(int k, int rows, unsigned char *a, unsigned char *g_tbls) -{ - int i, j; - - for (i = 0; i < rows; i++) { - for (j = 0; j < k; j++) { - gf_vect_mul_init(*a++, g_tbls); - g_tbls += 32; - } - } -} - -void ec_encode_data_sse(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data, - unsigned char **coding) -{ - - if (len < 16) { - ec_encode_data_base(len, k, rows, g_tbls, data, coding); - return; - } - - while (rows >= 4) { - gf_4vect_dot_prod_sse(len, k, g_tbls, data, coding); - g_tbls += 4 * k * 32; - coding += 4; - rows -= 4; - } - switch (rows) { - case 3: - gf_3vect_dot_prod_sse(len, k, g_tbls, data, coding); - break; - case 2: - gf_2vect_dot_prod_sse(len, k, g_tbls, data, coding); - break; - case 1: - gf_vect_dot_prod_sse(len, k, g_tbls, data, *coding); - break; - case 0: - break; - } - -} - -void ec_encode_data_avx(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data, - unsigned char **coding) -{ - if (len < 16) { - ec_encode_data_base(len, k, rows, g_tbls, data, coding); - return; - } - - while (rows >= 4) { - gf_4vect_dot_prod_avx(len, k, g_tbls, data, coding); - g_tbls += 4 * k * 32; - coding += 4; - rows -= 4; - } - switch (rows) { - case 3: - gf_3vect_dot_prod_avx(len, k, g_tbls, data, coding); - break; - case 2: - gf_2vect_dot_prod_avx(len, k, g_tbls, data, coding); - break; - case 1: - gf_vect_dot_prod_avx(len, k, g_tbls, data, *coding); - break; - case 0: - break; - } - -} - -void ec_encode_data_avx2(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data, - unsigned char **coding) -{ - - if (len < 32) { - ec_encode_data_base(len, k, rows, g_tbls, data, coding); - return; - } - - while (rows >= 4) { - gf_4vect_dot_prod_avx2(len, k, g_tbls, data, coding); - g_tbls += 4 * k * 32; - coding += 4; - rows -= 4; - } - switch (rows) { - case 3: - gf_3vect_dot_prod_avx2(len, k, g_tbls, data, coding); - break; - case 2: - gf_2vect_dot_prod_avx2(len, k, g_tbls, data, coding); - break; - case 1: - gf_vect_dot_prod_avx2(len, k, g_tbls, data, *coding); - break; - case 0: - break; - } - -} - -#if __WORDSIZE == 64 || _WIN64 || __x86_64__ - -void ec_encode_data_update_sse(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding) -{ - if (len < 16) { - ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding); - return; - } - - while (rows > 6) { - gf_6vect_mad_sse(len, k, vec_i, g_tbls, data, coding); - g_tbls += 6 * k * 32; - coding += 6; - rows -= 6; - } - switch (rows) { - case 6: - gf_6vect_mad_sse(len, k, vec_i, g_tbls, data, coding); - break; - case 5: - gf_5vect_mad_sse(len, k, vec_i, g_tbls, data, coding); - break; - case 4: - gf_4vect_mad_sse(len, k, vec_i, g_tbls, data, coding); - break; - case 3: - gf_3vect_mad_sse(len, k, vec_i, g_tbls, data, coding); - break; - case 2: - gf_2vect_mad_sse(len, k, vec_i, g_tbls, data, coding); - break; - case 1: - gf_vect_mad_sse(len, k, vec_i, g_tbls, data, *coding); - break; - case 0: - break; - } - -} - -void ec_encode_data_update_avx(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding) -{ - if (len < 16) { - ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding); - return; - } - while (rows > 6) { - gf_6vect_mad_avx(len, k, vec_i, g_tbls, data, coding); - g_tbls += 6 * k * 32; - coding += 6; - rows -= 6; - } - switch (rows) { - case 6: - gf_6vect_mad_avx(len, k, vec_i, g_tbls, data, coding); - break; - case 5: - gf_5vect_mad_avx(len, k, vec_i, g_tbls, data, coding); - break; - case 4: - gf_4vect_mad_avx(len, k, vec_i, g_tbls, data, coding); - break; - case 3: - gf_3vect_mad_avx(len, k, vec_i, g_tbls, data, coding); - break; - case 2: - gf_2vect_mad_avx(len, k, vec_i, g_tbls, data, coding); - break; - case 1: - gf_vect_mad_avx(len, k, vec_i, g_tbls, data, *coding); - break; - case 0: - break; - } - -} - -void ec_encode_data_update_avx2(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding) -{ - if (len < 32) { - ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding); - return; - } - while (rows > 6) { - gf_6vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); - g_tbls += 6 * k * 32; - coding += 6; - rows -= 6; - } - switch (rows) { - case 6: - gf_6vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); - break; - case 5: - gf_5vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); - break; - case 4: - gf_4vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); - break; - case 3: - gf_3vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); - break; - case 2: - gf_2vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); - break; - case 1: - gf_vect_mad_avx2(len, k, vec_i, g_tbls, data, *coding); - break; - case 0: - break; - } - -} - -#endif //__WORDSIZE == 64 || _WIN64 || __x86_64__ - -struct slver { - UINT16 snum; - UINT8 ver; - UINT8 core; -}; - -// Version info -struct slver ec_init_tables_slver_00010068; -struct slver ec_init_tables_slver = { 0x0068, 0x01, 0x00 }; - -struct slver ec_encode_data_sse_slver_00020069; -struct slver ec_encode_data_sse_slver = { 0x0069, 0x02, 0x00 }; diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_multibinary.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_multibinary.asm.s deleted file mode 100644 index 03f501a1b..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/ec_multibinary.asm.s +++ /dev/null @@ -1,395 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -%ifidn __OUTPUT_FORMAT__, elf64 - %define WRT_OPT wrt ..plt -%else - %define WRT_OPT -%endif - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf32 - -[bits 32] - - %define def_wrd dd - %define wrd_sz dword - %define arg1 esi - %define arg2 eax - %define arg3 ebx - %define arg4 ecx - %define arg5 edx - -%else - - default rel - [bits 64] - - %define def_wrd dq - %define wrd_sz qword - %define arg1 rsi - %define arg2 rax - %define arg3 rbx - %define arg4 rcx - %define arg5 rdx - - - extern ec_encode_data_update_sse - extern ec_encode_data_update_avx - extern ec_encode_data_update_avx2 - extern gf_vect_mul_sse - extern gf_vect_mul_avx - - extern gf_vect_mad_sse - extern gf_vect_mad_avx - extern gf_vect_mad_avx2 -%endif - -extern gf_vect_mul_base -extern ec_encode_data_base -extern ec_encode_data_update_base -extern gf_vect_dot_prod_base -extern gf_vect_mad_base - -extern gf_vect_dot_prod_sse -extern gf_vect_dot_prod_avx -extern gf_vect_dot_prod_avx2 -extern ec_encode_data_sse -extern ec_encode_data_avx -extern ec_encode_data_avx2 - - -section .data -;;; *_mbinit are initial values for *_dispatched; is updated on first call. -;;; Therefore, *_dispatch_init is only executed on first call. - -ec_encode_data_dispatched: - def_wrd ec_encode_data_mbinit - -gf_vect_mul_dispatched: - def_wrd gf_vect_mul_mbinit - -gf_vect_dot_prod_dispatched: - def_wrd gf_vect_dot_prod_mbinit - -ec_encode_data_update_dispatched: - def_wrd ec_encode_data_update_mbinit - -gf_vect_mad_dispatched: - def_wrd gf_vect_mad_mbinit - -section .text -;;;; -; ec_encode_data multibinary function -;;;; -global ec_encode_data:function -ec_encode_data_mbinit: - call ec_encode_data_dispatch_init - -ec_encode_data: - jmp wrd_sz [ec_encode_data_dispatched] - -ec_encode_data_dispatch_init: - push arg1 - push arg2 - push arg3 - push arg4 - push arg5 - lea arg1, [ec_encode_data_base WRT_OPT] ; Default - - mov eax, 1 - cpuid - lea arg3, [ec_encode_data_sse WRT_OPT] - test ecx, FLAG_CPUID1_ECX_SSE4_1 - cmovne arg1, arg3 - - and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - lea arg3, [ec_encode_data_avx WRT_OPT] - - jne _done_ec_encode_data_init - mov arg1, arg3 - - ;; Try for AVX2 - xor ecx, ecx - mov eax, 7 - cpuid - test ebx, FLAG_CPUID1_EBX_AVX2 - lea arg3, [ec_encode_data_avx2 WRT_OPT] - cmovne arg1, arg3 - ;; Does it have xmm and ymm support - xor ecx, ecx - xgetbv - and eax, FLAG_XGETBV_EAX_XMM_YMM - cmp eax, FLAG_XGETBV_EAX_XMM_YMM - je _done_ec_encode_data_init - lea arg1, [ec_encode_data_sse WRT_OPT] - -_done_ec_encode_data_init: - pop arg5 - pop arg4 - pop arg3 - pop arg2 - mov [ec_encode_data_dispatched], arg1 - pop arg1 - ret - -;;;; -; gf_vect_mul multibinary function -;;;; -global gf_vect_mul:function -gf_vect_mul_mbinit: - call gf_vect_mul_dispatch_init - -gf_vect_mul: - jmp wrd_sz [gf_vect_mul_dispatched] - -gf_vect_mul_dispatch_init: - push arg1 -%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check - lea arg1, [gf_vect_mul_base] -%else - push rax - push rbx - push rcx - push rdx - lea arg1, [gf_vect_mul_base WRT_OPT] ; Default - - mov eax, 1 - cpuid - test ecx, FLAG_CPUID1_ECX_SSE4_2 - lea rbx, [gf_vect_mul_sse WRT_OPT] - je _done_gf_vect_mul_dispatch_init - mov arg1, rbx - - ;; Try for AVX - and ecx, (FLAG_CPUID1_ECX_OSXSAVE | FLAG_CPUID1_ECX_AVX) - cmp ecx, (FLAG_CPUID1_ECX_OSXSAVE | FLAG_CPUID1_ECX_AVX) - jne _done_gf_vect_mul_dispatch_init - - ;; Does it have xmm and ymm support - xor ecx, ecx - xgetbv - and eax, FLAG_XGETBV_EAX_XMM_YMM - cmp eax, FLAG_XGETBV_EAX_XMM_YMM - jne _done_gf_vect_mul_dispatch_init - lea arg1, [gf_vect_mul_avx WRT_OPT] - -_done_gf_vect_mul_dispatch_init: - pop rdx - pop rcx - pop rbx - pop rax -%endif ;; END 32-bit check - mov [gf_vect_mul_dispatched], arg1 - pop arg1 - ret - -;;;; -; ec_encode_data_update multibinary function -;;;; -global ec_encode_data_update:function -ec_encode_data_update_mbinit: - call ec_encode_data_update_dispatch_init - -ec_encode_data_update: - jmp wrd_sz [ec_encode_data_update_dispatched] - -ec_encode_data_update_dispatch_init: - push arg1 -%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check - lea arg1, [ec_encode_data_update_base] -%else - push rax - push rbx - push rcx - push rdx - lea arg1, [ec_encode_data_update_base WRT_OPT] ; Default - - mov eax, 1 - cpuid - lea rbx, [ec_encode_data_update_sse WRT_OPT] - test ecx, FLAG_CPUID1_ECX_SSE4_1 - cmovne arg1, rbx - - and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - lea rbx, [ec_encode_data_update_avx WRT_OPT] - - jne _done_ec_encode_data_update_init - mov rsi, rbx - - ;; Try for AVX2 - xor ecx, ecx - mov eax, 7 - cpuid - test ebx, FLAG_CPUID1_EBX_AVX2 - lea rbx, [ec_encode_data_update_avx2 WRT_OPT] - cmovne rsi, rbx - - ;; Does it have xmm and ymm support - xor ecx, ecx - xgetbv - and eax, FLAG_XGETBV_EAX_XMM_YMM - cmp eax, FLAG_XGETBV_EAX_XMM_YMM - je _done_ec_encode_data_update_init - lea rsi, [ec_encode_data_update_sse WRT_OPT] - -_done_ec_encode_data_update_init: - pop rdx - pop rcx - pop rbx - pop rax -%endif ;; END 32-bit check - mov [ec_encode_data_update_dispatched], arg1 - pop arg1 - ret - -;;;; -; gf_vect_dot_prod multibinary function -;;;; -global gf_vect_dot_prod:function -gf_vect_dot_prod_mbinit: - call gf_vect_dot_prod_dispatch_init - -gf_vect_dot_prod: - jmp wrd_sz [gf_vect_dot_prod_dispatched] - -gf_vect_dot_prod_dispatch_init: - push arg1 - push arg2 - push arg3 - push arg4 - push arg5 - lea arg1, [gf_vect_dot_prod_base WRT_OPT] ; Default - - mov eax, 1 - cpuid - lea arg3, [gf_vect_dot_prod_sse WRT_OPT] - test ecx, FLAG_CPUID1_ECX_SSE4_1 - cmovne arg1, arg3 - - and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - lea arg3, [gf_vect_dot_prod_avx WRT_OPT] - - jne _done_gf_vect_dot_prod_init - mov arg1, arg3 - - ;; Try for AVX2 - xor ecx, ecx - mov eax, 7 - cpuid - test ebx, FLAG_CPUID1_EBX_AVX2 - lea arg3, [gf_vect_dot_prod_avx2 WRT_OPT] - cmovne arg1, arg3 - ;; Does it have xmm and ymm support - xor ecx, ecx - xgetbv - and eax, FLAG_XGETBV_EAX_XMM_YMM - cmp eax, FLAG_XGETBV_EAX_XMM_YMM - je _done_gf_vect_dot_prod_init - lea arg1, [gf_vect_dot_prod_sse WRT_OPT] - -_done_gf_vect_dot_prod_init: - pop arg5 - pop arg4 - pop arg3 - pop arg2 - mov [gf_vect_dot_prod_dispatched], arg1 - pop arg1 - ret - -;;;; -; gf_vect_mad multibinary function -;;;; -global gf_vect_mad:function -gf_vect_mad_mbinit: - call gf_vect_mad_dispatch_init - -gf_vect_mad: - jmp wrd_sz [gf_vect_mad_dispatched] - -gf_vect_mad_dispatch_init: - push arg1 -%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check - lea arg1, [gf_vect_mad_base] -%else - push rax - push rbx - push rcx - push rdx - lea arg1, [gf_vect_mad_base WRT_OPT] ; Default - - mov eax, 1 - cpuid - lea rbx, [gf_vect_mad_sse WRT_OPT] - test ecx, FLAG_CPUID1_ECX_SSE4_1 - cmovne arg1, rbx - - and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) - lea rbx, [gf_vect_mad_avx WRT_OPT] - - jne _done_gf_vect_mad_init - mov rsi, rbx - - ;; Try for AVX2 - xor ecx, ecx - mov eax, 7 - cpuid - test ebx, FLAG_CPUID1_EBX_AVX2 - lea rbx, [gf_vect_mad_avx2 WRT_OPT] - cmovne rsi, rbx - - ;; Does it have xmm and ymm support - xor ecx, ecx - xgetbv - and eax, FLAG_XGETBV_EAX_XMM_YMM - cmp eax, FLAG_XGETBV_EAX_XMM_YMM - je _done_gf_vect_mad_init - lea rsi, [gf_vect_mad_sse WRT_OPT] - -_done_gf_vect_mad_init: - pop rdx - pop rcx - pop rbx - pop rax -%endif ;; END 32-bit check - mov [gf_vect_mad_dispatched], arg1 - pop arg1 - ret - -;;; func core, ver, snum -slversion ec_encode_data, 00, 04, 0133 -slversion gf_vect_mul, 00, 03, 0134 -slversion ec_encode_data_update, 00, 03, 0212 -slversion gf_vect_dot_prod, 00, 03, 0138 -slversion gf_vect_mad, 00, 02, 0213 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx.asm.s deleted file mode 100644 index db1e1c550..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx.asm.s +++ /dev/null @@ -1,337 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_2vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r9 - %define tmp4 r12 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - %endmacro - %macro FUNC_RESTORE 0 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 3*16 + 3*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_reg r12, 3*16 + 0*8 - save_reg r13, 3*16 + 1*8 - save_reg r14, 3*16 + 2*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - mov r12, [rsp + 3*16 + 0*8] - mov r13, [rsp + 3*16 + 1*8] - mov r14, [rsp + 3*16 + 2*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define tmp edx - %define tmp2 edi - %define tmp3 trans2 - %define tmp4 trans2 - %define tmp4_m var(0) - %define return eax - %macro SLDR 2 ;; stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*1 ;1 local variable - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*1 ;1 local variable - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 - -%define vec_i tmp2 -%define ptr tmp3 -%define dest2 tmp4 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp4_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ; 64-bit code - default rel - [bits 64] -%endif - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f xmm8 - %define xgft1_lo xmm7 - %define xgft1_hi xmm6 - %define xgft2_lo xmm5 - %define xgft2_hi xmm4 - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 -%else ;32-bit code - %define xmask0f xmm4 - %define xgft1_lo xmm7 - %define xgft1_hi xmm6 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 -%endif - -align 16 -global gf_2vect_dot_prod_avx:function - -func(gf_2vect_dot_prod_avx) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop16 - vpxor xp1, xp1 - vpxor xp2, xp2 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect - SLDR src, src_m - mov ptr, [src+vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - %ifidn PS,8 ; 64-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - add tmp, 32 - add vec_i, PS - %endif - XLDR x0, [ptr+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ; 32-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - add tmp, 32 - add vec_i, PS - %endif - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - - SLDR len, len_m - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_2vect_dot_prod_avx, 02, 05, 0191 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx2.asm.s deleted file mode 100644 index 0387893fc..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_avx2.asm.s +++ /dev/null @@ -1,356 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_2vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r9 - %define tmp4 r12 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - %endmacro - %macro FUNC_RESTORE 0 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 3*16 + 3*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - vmovdqa [rsp + 0*16], xmm6 - vmovdqa [rsp + 1*16], xmm7 - vmovdqa [rsp + 2*16], xmm8 - save_reg r12, 3*16 + 0*8 - save_reg r13, 3*16 + 1*8 - save_reg r14, 3*16 + 2*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - mov r12, [rsp + 3*16 + 0*8] - mov r13, [rsp + 3*16 + 1*8] - mov r14, [rsp + 3*16 + 2*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define tmp edx - %define tmp.w edx - %define tmp.b dl - %define tmp2 edi - %define tmp3 trans2 - %define tmp4 trans2 - %define tmp4_m var(0) - %define return eax - %macro SLDR 2 ;stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*1 ;1 local variable - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*1 ;1 local variable - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 - -%define vec_i tmp2 -%define ptr tmp3 -%define dest2 tmp4 -%define pos return - -%ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp4_m -%endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else - -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ;64-bit code - default rel - [bits 64] -%endif - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f ymm8 - %define xmask0fx xmm8 - %define xgft1_lo ymm7 - %define xgft1_hi ymm6 - %define xgft2_lo ymm5 - %define xgft2_hi ymm4 - - %define x0 ymm0 - %define xtmpa ymm1 - %define xp1 ymm2 - %define xp2 ymm3 -%else ;32-bit code - %define xmask0f ymm7 - %define xmask0fx xmm7 - %define xgft1_lo ymm5 - %define xgft1_hi ymm4 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - - %define x0 ymm0 - %define xtmpa ymm1 - %define xp1 ymm2 - %define xp2 ymm3 - -%endif - -align 16 -global gf_2vect_dot_prod_avx2:function - -func(gf_2vect_dot_prod_avx2) - FUNC_SAVE - SLDR len, len_m - sub len, 32 - SSTR len_m, len - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop32 - vpxor xp1, xp1 - vpxor xp2, xp2 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect - SLDR src, src_m - mov ptr, [src+vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo - %ifidn PS,8 ; 64-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - - XLDR x0, [ptr+pos] ;Get next source vector - add tmp, 32 - add vec_i, PS - %else - XLDR x0, [ptr+pos] ;Get next source vector - %endif - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ; 32-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - add tmp, 32 - add vec_i, PS - %endif - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - - SLDR len, len_m - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop32 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_2vect_dot_prod_avx2, 04, 05, 0196 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_sse.asm.s deleted file mode 100644 index 95dd92ad8..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_dot_prod_sse.asm.s +++ /dev/null @@ -1,339 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_2vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r9 - %define tmp4 r12 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - %endmacro - %macro FUNC_RESTORE 0 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 3*16 + 3*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_reg r12, 3*16 + 0*8 - save_reg r13, 3*16 + 1*8 - save_reg r14, 3*16 + 2*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - movdqa xmm6, [rsp + 0*16] - movdqa xmm7, [rsp + 1*16] - movdqa xmm8, [rsp + 2*16] - mov r12, [rsp + 3*16 + 0*8] - mov r13, [rsp + 3*16 + 1*8] - mov r14, [rsp + 3*16 + 2*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define tmp edx - %define tmp2 edi - %define tmp3 trans2 - %define tmp4 trans2 - %define tmp4_m var(0) - %define return eax - %macro SLDR 2 ;; stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*1 ;1 local variable - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*1 ;1 local variable - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 - -%define vec_i tmp2 -%define ptr tmp3 -%define dest2 tmp4 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp4_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -%ifidn PS,8 ;64-bit code - default rel - [bits 64] -%endif - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f xmm8 - %define xgft1_lo xmm7 - %define xgft1_hi xmm6 - %define xgft2_lo xmm5 - %define xgft2_hi xmm4 - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 -%else ;32-bit code - %define xmask0f xmm4 - %define xgft1_lo xmm7 - %define xgft1_hi xmm6 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 -%endif - -align 16 -global gf_2vect_dot_prod_sse:function - -func(gf_2vect_dot_prod_sse) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop16 - pxor xp1, xp1 - pxor xp2, xp2 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect - SLDR src, src_m - mov ptr, [src+vec_i] - - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - %ifidn PS,8 ;64-bit code - movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - add tmp, 32 - add vec_i, PS - %endif - XLDR x0, [ptr+pos] ;Get next source vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ;32-bit code - movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - - add tmp, 32 - add vec_i, PS - %endif - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pxor xp2, xgft2_hi ;xp2 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - - SLDR len, len_m - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_2vect_dot_prod_sse, 00, 04, 0062 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx.asm.s deleted file mode 100644 index e18238130..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx.asm.s +++ /dev/null @@ -1,236 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_2vect_mad_avx(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define return rax - %define return.w eax - %define stack_size 16*9 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - save_reg r12, 9*16 + 0*8 - save_reg r15, 9*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - mov r12, [rsp + 9*16 + 0*8] - mov r15, [rsp + 9*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_2vect_mad_avx(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp2 - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm14 -%define xgft1_lo xmm13 -%define xgft1_hi xmm12 -%define xgft2_lo xmm11 -%define xgft2_hi xmm10 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xd1 xmm6 -%define xd2 xmm7 -%define xtmpd1 xmm8 -%define xtmpd2 xmm9 - - -align 16 -global gf_2vect_mad_avx:function - -func(gf_2vect_mad_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 - lea tmp, [mul_array + vec_i] - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - - mov dest2, [dest1+PS] - mov dest1, [dest1] - - XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest - XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest - -.loop16 - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector -.loop16_overlap: - XLDR x0, [src+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - XSTR [dest1+pos], xd1 - XSTR [dest2+pos], xd2 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - vmovdqa xd1, xtmpd1 ;Restore xd1 - vmovdqa xd2, xtmpd2 ;Restore xd2 - jmp .loop16_overlap ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_2vect_mad_avx, 02, 01, 0204 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx2.asm.s deleted file mode 100644 index 03902f474..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_avx2.asm.s +++ /dev/null @@ -1,247 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_2vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define return rax - %define return.w eax - %define stack_size 16*9 + 3*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - sub rsp, stack_size - vmovdqa [rsp+16*0],xmm6 - vmovdqa [rsp+16*1],xmm7 - vmovdqa [rsp+16*2],xmm8 - vmovdqa [rsp+16*3],xmm9 - vmovdqa [rsp+16*4],xmm10 - vmovdqa [rsp+16*5],xmm11 - vmovdqa [rsp+16*6],xmm12 - vmovdqa [rsp+16*7],xmm13 - vmovdqa [rsp+16*8],xmm14 - save_reg r12, 9*16 + 0*8 - save_reg r15, 9*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp+16*0] - vmovdqa xmm7, [rsp+16*1] - vmovdqa xmm8, [rsp+16*2] - vmovdqa xmm9, [rsp+16*3] - vmovdqa xmm10, [rsp+16*4] - vmovdqa xmm11, [rsp+16*5] - vmovdqa xmm12, [rsp+16*6] - vmovdqa xmm13, [rsp+16*7] - vmovdqa xmm14, [rsp+16*8] - mov r12, [rsp + 9*16 + 0*8] - mov r15, [rsp + 9*16 + 1*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_2vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp2 - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else - -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f ymm14 -%define xmask0fx xmm14 -%define xgft1_lo ymm13 -%define xgft1_hi ymm12 -%define xgft2_lo ymm11 -%define xgft2_hi ymm10 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xtmph1 ymm2 -%define xtmpl1 ymm3 -%define xtmph2 ymm4 -%define xtmpl2 ymm5 -%define xd1 ymm6 -%define xd2 ymm7 -%define xtmpd1 ymm8 -%define xtmpd2 ymm9 - -align 16 -global gf_2vect_mad_avx2:function - -func(gf_2vect_mad_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 - lea tmp, [mul_array + vec_i] - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - mov dest2, [dest1+PS] ; reuse mul_array - mov dest1, [dest1] - - XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest - XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest - -.loop32 - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector -.loop32_overlap: - XLDR x0, [src+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - XSTR [dest1+pos], xd1 - XSTR [dest2+pos], xd2 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-32 - vmovdqa xd1, xtmpd1 ;Restore xd1 - vmovdqa xd2, xtmpd2 ;Restore xd2 - jmp .loop32_overlap ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_2vect_mad_avx2, 04, 01, 0205 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_sse.asm.s deleted file mode 100644 index 2e82c5a66..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_2vect_mad_sse.asm.s +++ /dev/null @@ -1,239 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_2vect_mad_sse(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define return rax - %define return.w eax - %define stack_size 16*9 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - save_reg r12, 9*16 + 0*8 - save_reg r15, 9*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - mov r12, [rsp + 9*16 + 0*8] - mov r15, [rsp + 9*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_2vect_mad_sse(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp2 - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm14 -%define xgft1_lo xmm13 -%define xgft1_hi xmm12 -%define xgft2_lo xmm11 -%define xgft2_hi xmm10 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xd1 xmm6 -%define xd2 xmm7 -%define xtmpd1 xmm8 -%define xtmpd2 xmm9 - - -align 16 -global gf_2vect_mad_sse:function -func(gf_2vect_mad_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 - lea tmp, [mul_array + vec_i] - movdqu xgft1_lo,[tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - mov dest2, [dest1+PS] - mov dest1, [dest1] - - XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest - XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest - -.loop16: - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector -.loop16_overlap: - XLDR x0, [src+pos] ;Get next source vector - movdqa xtmph1, xgft1_hi ;Reload const array registers - movdqa xtmpl1, xgft1_lo - movdqa xtmph2, xgft2_hi ;Reload const array registers - movdqa xtmpl2, xgft2_lo - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pxor xd1, xtmph1 - - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pxor xd2, xtmph2 - - XSTR [dest1+pos], xd1 ;Store result - XSTR [dest2+pos], xd2 ;Store result - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - movdqa xd1, xtmpd1 ;Restore xd1 - movdqa xd2, xtmpd2 ;Restore xd2 - jmp .loop16_overlap ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 - -mask0f: - ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_2vect_mad_sse, 00, 01, 0203 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx.asm.s deleted file mode 100644 index 33fc19837..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx.asm.s +++ /dev/null @@ -1,377 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_3vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - %endmacro - %macro FUNC_RESTORE 0 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 6*16 + 5*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_reg r12, 6*16 + 0*8 - save_reg r13, 6*16 + 1*8 - save_reg r14, 6*16 + 2*8 - save_reg r15, 6*16 + 3*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - mov r12, [rsp + 6*16 + 0*8] - mov r13, [rsp + 6*16 + 1*8] - mov r14, [rsp + 6*16 + 2*8] - mov r15, [rsp + 6*16 + 3*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; var1 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define arg5 trans2 - %define tmp edx - %define tmp2 edi - %define tmp3 trans2 - %define tmp3_m var(0) - %define tmp4 trans2 - %define tmp4_m var(1) - %define return eax - %macro SLDR 2 ;; stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*2 ;2 local variables - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*2 ;2 local variables - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 -%define ptr arg5 - -%define vec_i tmp2 -%define dest2 tmp3 -%define dest3 tmp4 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp3_m - %define dest3_m tmp4_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ; 64-bit code - default rel - [bits 64] -%endif - - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f xmm11 - %define xgft1_lo xmm10 - %define xgft1_hi xmm9 - %define xgft2_lo xmm8 - %define xgft2_hi xmm7 - %define xgft3_lo xmm6 - %define xgft3_hi xmm5 - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 - %define xp3 xmm4 -%else - %define xmask0f xmm7 - %define xgft1_lo xmm6 - %define xgft1_hi xmm5 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - %define xgft3_lo xgft1_lo - %define xgft3_hi xgft1_hi - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 - %define xp3 xmm4 -%endif - -align 16 -global gf_3vect_dot_prod_avx:function -func(gf_3vect_dot_prod_avx) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest3, [dest1+2*PS] - SSTR dest3_m, dest3 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop16: - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - SLDR src, src_m - mov ptr, [src+vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - %ifidn PS,8 ; 64-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - add tmp, 32 - add vec_i, PS - %endif - XLDR x0, [ptr+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ; 32-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - %endif - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - %ifidn PS,4 ; 32-bit code - sal vec, 1 - vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - sar vec, 1 - add tmp, 32 - add vec_i, PS - %endif - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - SLDR dest3, dest3_m - XSTR [dest3+pos], xp3 - - SLDR len, len_m - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_3vect_dot_prod_avx, 02, 05, 0192 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx2.asm.s deleted file mode 100644 index 23c46a798..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_avx2.asm.s +++ /dev/null @@ -1,397 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_3vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - %endmacro - %macro FUNC_RESTORE 0 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 6*16 + 5*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - vmovdqa [rsp + 0*16], xmm6 - vmovdqa [rsp + 1*16], xmm7 - vmovdqa [rsp + 2*16], xmm8 - vmovdqa [rsp + 3*16], xmm9 - vmovdqa [rsp + 4*16], xmm10 - vmovdqa [rsp + 5*16], xmm11 - save_reg r12, 6*16 + 0*8 - save_reg r13, 6*16 + 1*8 - save_reg r14, 6*16 + 2*8 - save_reg r15, 6*16 + 3*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - mov r12, [rsp + 6*16 + 0*8] - mov r13, [rsp + 6*16 + 1*8] - mov r14, [rsp + 6*16 + 2*8] - mov r15, [rsp + 6*16 + 3*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; var1 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define arg5 trans2 - %define tmp edx - %define tmp.w edx - %define tmp.b dl - %define tmp2 edi - %define tmp3 trans2 - %define tmp3_m var(0) - %define tmp4 trans2 - %define tmp4_m var(1) - %define return eax - %macro SLDR 2 ;stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*2 ;2 local variables - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*2 ;2 local variables - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 -%define ptr arg5 - -%define vec_i tmp2 -%define dest2 tmp3 -%define dest3 tmp4 -%define pos return - -%ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp3_m - %define dest3_m tmp4_m -%endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ;64-bit code - default rel - [bits 64] -%endif - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f ymm11 - %define xmask0fx xmm11 - %define xgft1_lo ymm10 - %define xgft1_hi ymm9 - %define xgft2_lo ymm8 - %define xgft2_hi ymm7 - %define xgft3_lo ymm6 - %define xgft3_hi ymm5 - - %define x0 ymm0 - %define xtmpa ymm1 - %define xp1 ymm2 - %define xp2 ymm3 - %define xp3 ymm4 -%else - %define xmask0f ymm7 - %define xmask0fx xmm7 - %define xgft1_lo ymm6 - %define xgft1_hi ymm5 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - %define xgft3_lo xgft1_lo - %define xgft3_hi xgft1_hi - - %define x0 ymm0 - %define xtmpa ymm1 - %define xp1 ymm2 - %define xp2 ymm3 - %define xp3 ymm4 - -%endif - -align 16 -global gf_3vect_dot_prod_avx2:function -func(gf_3vect_dot_prod_avx2) - FUNC_SAVE - SLDR len, len_m - sub len, 32 - SSTR len_m, len - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest3, [dest1+2*PS] - SSTR dest3_m, dest3 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop32: - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - SLDR src, src_m - mov ptr, [src+vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo - %ifidn PS,8 ; 64-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - - vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft3_lo, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo - - add tmp, 32 - add vec_i, PS - %endif - XLDR x0, [ptr+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ; 32-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - %endif - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - %ifidn PS,4 ; 32-bit code - sal vec, 1 - vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft3_lo, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo - sar vec, 1 - add tmp, 32 - add vec_i, PS - %endif - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - SLDR dest3, dest3_m - XSTR [dest3+pos], xp3 - - SLDR len, len_m - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop32 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_3vect_dot_prod_avx2, 04, 05, 0197 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_sse.asm.s deleted file mode 100644 index a082fb851..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_dot_prod_sse.asm.s +++ /dev/null @@ -1,378 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_3vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - %endmacro - %macro FUNC_RESTORE 0 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 6*16 + 5*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_reg r12, 6*16 + 0*8 - save_reg r13, 6*16 + 1*8 - save_reg r14, 6*16 + 2*8 - save_reg r15, 6*16 + 3*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - movdqa xmm6, [rsp + 0*16] - movdqa xmm7, [rsp + 1*16] - movdqa xmm8, [rsp + 2*16] - movdqa xmm9, [rsp + 3*16] - movdqa xmm10, [rsp + 4*16] - movdqa xmm11, [rsp + 5*16] - mov r12, [rsp + 6*16 + 0*8] - mov r13, [rsp + 6*16 + 1*8] - mov r14, [rsp + 6*16 + 2*8] - mov r15, [rsp + 6*16 + 3*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; var1 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define arg5 trans2 - %define tmp edx - %define tmp2 edi - %define tmp3 trans2 - %define tmp3_m var(0) - %define tmp4 trans2 - %define tmp4_m var(1) - %define return eax - %macro SLDR 2 ;; stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*2 ;2 local variables - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*2 ;2 local variables - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 -%define ptr arg5 - -%define vec_i tmp2 -%define dest2 tmp3 -%define dest3 tmp4 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp3_m - %define dest3_m tmp4_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -%ifidn PS,8 ; 64-bit code - default rel - [bits 64] -%endif - - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f xmm11 - %define xgft1_lo xmm2 - %define xgft1_hi xmm3 - %define xgft2_lo xmm4 - %define xgft2_hi xmm7 - %define xgft3_lo xmm6 - %define xgft3_hi xmm5 - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm10 - %define xp2 xmm9 - %define xp3 xmm8 -%else - %define xmask0f xmm7 - %define xgft1_lo xmm6 - %define xgft1_hi xmm5 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - %define xgft3_lo xgft1_lo - %define xgft3_hi xgft1_hi - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 - %define xp3 xmm4 -%endif - -align 16 -global gf_3vect_dot_prod_sse:function -func(gf_3vect_dot_prod_sse) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest3, [dest1+2*PS] - SSTR dest3_m, dest3 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop16: - pxor xp1, xp1 - pxor xp2, xp2 - pxor xp3, xp3 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - SLDR src, src_m - mov ptr, [src+vec_i] - - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - %ifidn PS,8 ;64-bit code - movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - movdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - add tmp, 32 - add vec_i, PS - %endif - XLDR x0, [ptr+pos] ;Get next source vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ;32-bit code - movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - %endif - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pxor xp2, xgft2_hi ;xp2 += partial - - %ifidn PS,4 ;32-bit code - sal vec, 1 - movdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - sar vec, 1 - add tmp, 32 - add vec_i, PS - %endif - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xgft3_lo ;GF add high and low partials - pxor xp3, xgft3_hi ;xp3 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - SLDR dest3, dest3_m - XSTR [dest3+pos], xp3 - - SLDR len, len_m - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_3vect_dot_prod_sse, 00, 06, 0063 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx.asm.s deleted file mode 100644 index ed25d6a67..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx.asm.s +++ /dev/null @@ -1,288 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_3vect_mad_avx(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - vmovdqa [rsp+16*0],xmm6 - vmovdqa [rsp+16*1],xmm7 - vmovdqa [rsp+16*2],xmm8 - vmovdqa [rsp+16*3],xmm9 - vmovdqa [rsp+16*4],xmm10 - vmovdqa [rsp+16*5],xmm11 - vmovdqa [rsp+16*6],xmm12 - vmovdqa [rsp+16*7],xmm13 - vmovdqa [rsp+16*8],xmm14 - vmovdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r15, 10*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp+16*0] - vmovdqa xmm7, [rsp+16*1] - vmovdqa xmm8, [rsp+16*2] - vmovdqa xmm9, [rsp+16*3] - vmovdqa xmm10, [rsp+16*4] - vmovdqa xmm11, [rsp+16*5] - vmovdqa xmm12, [rsp+16*6] - vmovdqa xmm13, [rsp+16*7] - vmovdqa xmm14, [rsp+16*8] - vmovdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r15, [rsp + 10*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_3vect_mad_avx(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft1_lo xmm14 -%define xgft1_hi xmm13 -%define xgft2_lo xmm12 -%define xgft2_hi xmm11 -%define xgft3_lo xmm10 -%define xgft3_hi xmm9 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xd1 xmm8 -%define xd2 xtmpl1 -%define xd3 xtmph1 - -align 16 -global gf_3vect_mad_avx:function -func(gf_3vect_mad_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 - lea tmp, [mul_array + vec_i] - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xgft3_hi, [tmp+2*vec+16]; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - mov dest2, [dest1+PS] ; reuse mul_array - mov dest3, [dest1+2*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - XLDR xd1, [dest1+pos] ;Get next dest vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest vector - - ; dest2 - vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - ; dest3 - vpshufb xtmph3, xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials - vpxor xd3, xd3, xtmph3 ;xd3 += partial - - XSTR [dest1+pos], xd1 - XSTR [dest2+pos], xd2 - XSTR [dest3+pos], xd3 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - mov tmp, len ;Overlapped offset length-16 - XLDR x0, [src+tmp] ;Get next source vector - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest vector - - sub len, pos - - movdqa xtmph3, [constip16] ;Load const of i + 16 - vpinsrb xtmpl3, xtmpl3, len.w, 15 - vpshufb xtmpl3, xtmpl3, xmask0f ;Broadcast len to all bytes - vpcmpgtb xtmpl3, xtmpl3, xtmph3 - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xgft1_hi, xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_hi, xgft1_lo ;GF add high and low partials - vpand xgft1_hi, xgft1_hi, xtmpl3 - vpxor xd1, xd1, xgft1_hi - - ; dest2 - vpshufb xgft2_hi, xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_hi, xgft2_lo ;GF add high and low partials - vpand xgft2_hi, xgft2_hi, xtmpl3 - vpxor xd2, xd2, xgft2_hi - - ; dest3 - vpshufb xgft3_hi, xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_hi, xgft3_lo ;GF add high and low partials - vpand xgft3_hi, xgft3_hi, xtmpl3 - vpxor xd3, xd3, xgft3_hi - - XSTR [dest1+tmp], xd1 - XSTR [dest2+tmp], xd2 - XSTR [dest3+tmp], xd3 - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_3vect_mad_avx, 02, 01, 0207 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx2.asm.s deleted file mode 100644 index d0b9272cd..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_avx2.asm.s +++ /dev/null @@ -1,317 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_3vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - - %macro FUNC_SAVE 0 - sub rsp, stack_size - vmovdqa [rsp+16*0],xmm6 - vmovdqa [rsp+16*1],xmm7 - vmovdqa [rsp+16*2],xmm8 - vmovdqa [rsp+16*3],xmm9 - vmovdqa [rsp+16*4],xmm10 - vmovdqa [rsp+16*5],xmm11 - vmovdqa [rsp+16*6],xmm12 - vmovdqa [rsp+16*7],xmm13 - vmovdqa [rsp+16*8],xmm14 - vmovdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r15, 10*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp+16*0] - vmovdqa xmm7, [rsp+16*1] - vmovdqa xmm8, [rsp+16*2] - vmovdqa xmm9, [rsp+16*3] - vmovdqa xmm10, [rsp+16*4] - vmovdqa xmm11, [rsp+16*5] - vmovdqa xmm12, [rsp+16*6] - vmovdqa xmm13, [rsp+16*7] - vmovdqa xmm14, [rsp+16*8] - vmovdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r15, [rsp + 10*16 + 1*8] - add rsp, stack_size - %endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_3vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f ymm15 -%define xmask0fx xmm15 -%define xgft1_lo ymm14 -%define xgft1_hi ymm13 -%define xgft2_lo ymm12 -%define xgft3_lo ymm11 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xtmph1 ymm2 -%define xtmpl1 ymm3 -%define xtmph2 ymm4 -%define xtmpl2 ymm5 -%define xtmpl2x xmm5 -%define xtmph3 ymm6 -%define xtmpl3 ymm7 -%define xtmpl3x xmm7 -%define xd1 ymm8 -%define xd2 ymm9 -%define xd3 ymm10 - -align 16 -global gf_3vect_mad_avx2:function -func(gf_3vect_mad_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 - lea tmp, [mul_array + vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo - - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - mov dest2, [dest1+PS] ; reuse mul_array - mov dest3, [dest1+2*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop32: - XLDR x0, [src+pos] ;Get next source vector - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - XLDR xd3, [dest3+pos] ;Get next dest vector - vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xtmpl2, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - - vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi - vperm2i128 xtmpl3, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - ; dest2 - vpshufb xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xtmph2 ;xd2 += partial - - ; dest3 - vpshufb xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmpl3 ;GF add high and low partials - vpxor xd3, xtmph3 ;xd3 += partial - - XSTR [dest1+pos], xd1 - XSTR [dest2+pos], xd2 - XSTR [dest3+pos], xd3 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - -.lessthan32: - ;; Tail len - ;; Do one more overlap pass - mov tmp.b, 0x1f - vpinsrb xtmpl2x, xtmpl2x, tmp.w, 0 - vpbroadcastb xtmpl2, xtmpl2x ;Construct mask 0x1f1f1f... - - mov tmp, len ;Overlapped offset length-32 - - XLDR x0, [src+tmp] ;Get next source vector - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - XLDR xd3, [dest3+tmp] ;Get next dest vector - - sub len, pos - - vmovdqa xtmph3, [constip32] ;Load const of i + 32 - vpinsrb xtmpl3x, xtmpl3x, len.w, 15 - vinserti128 xtmpl3, xtmpl3, xtmpl3x, 1 ;swapped to xtmpl3x | xtmpl3x - vpshufb xtmpl3, xtmpl3, xtmpl2 ;Broadcast len to all bytes. xtmpl2=0x1f1f1f... - vpcmpgtb xtmpl3, xtmpl3, xtmph3 - - vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo - - vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft3_lo, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpand xtmph1, xtmph1, xtmpl3 - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xgft2_lo ;GF add high and low partials - vpand xtmph2, xtmph2, xtmpl3 - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - ; dest3 - vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xgft3_lo ;GF add high and low partials - vpand xtmph3, xtmph3, xtmpl3 - vpxor xd3, xd3, xtmph3 ;xd3 += partial - - XSTR [dest1+tmp], xd1 - XSTR [dest2+tmp], xd2 - XSTR [dest3+tmp], xd3 - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 32 -constip32: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef - -;;; func core, ver, snum -slversion gf_3vect_mad_avx2, 04, 01, 0208 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_sse.asm.s deleted file mode 100644 index a06eb3d14..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_3vect_mad_sse.asm.s +++ /dev/null @@ -1,298 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_3vect_mad_sse(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r15, 10*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r15, [rsp + 10*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_3vect_mad_sse(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft1_lo xmm14 -%define xgft1_hi xmm13 -%define xgft2_lo xmm12 -%define xgft2_hi xmm11 -%define xgft3_lo xmm10 -%define xgft3_hi xmm9 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xd1 xmm8 -%define xd2 xtmpl1 -%define xd3 xtmph1 - -align 16 -global gf_3vect_mad_sse:function -func(gf_3vect_mad_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 - lea tmp, [mul_array + vec_i] - - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xgft3_hi, [tmp+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - mov dest2, [dest1+PS] ; reuse mul_array - mov dest3, [dest1+2*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - movdqa xtmph1, xgft1_hi ;Reload const array registers - movdqa xtmpl1, xgft1_lo - movdqa xtmph2, xgft2_hi ;Reload const array registers - movdqa xtmpl2, xgft2_lo - movdqa xtmph3, xgft3_hi ;Reload const array registers - movdqa xtmpl3, xgft3_lo - - XLDR xd1, [dest1+pos] ;Get next dest vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ; dest1 - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pxor xd1, xtmph1 - - XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest vector - - ; dest2 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pxor xd2, xtmph2 - - ; dest3 - pshufb xtmph3, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph3, xtmpl3 ;GF add high and low partials - pxor xd3, xtmph3 - - XSTR [dest1+pos], xd1 ;Store result - XSTR [dest2+pos], xd2 ;Store result - XSTR [dest3+pos], xd3 ;Store result - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - mov tmp, len ;Overlapped offset length-16 - - XLDR x0, [src+tmp] ;Get next source vector - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest vector - - sub len, pos - - movdqa xtmph3, [constip16] ;Load const of i + 16 - pinsrb xtmpl3, len.w, 15 - pshufb xtmpl3, xmask0f ;Broadcast len to all bytes - pcmpgtb xtmpl3, xtmph3 - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ; dest1 - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pand xgft1_hi, xtmpl3 - pxor xd1, xgft1_hi - - ; dest2 - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pand xgft2_hi, xtmpl3 - pxor xd2, xgft2_hi - - ; dest3 - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xgft3_lo ;GF add high and low partials - pand xgft3_hi, xtmpl3 - pxor xd3, xgft3_hi - - XSTR [dest1+tmp], xd1 ;Store result - XSTR [dest2+tmp], xd2 ;Store result - XSTR [dest3+tmp], xd3 ;Store result - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 - -mask0f: - ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_3vect_mad_sse, 00, 01, 0206 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx.asm.s deleted file mode 100644 index 9863012bc..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx.asm.s +++ /dev/null @@ -1,441 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_4vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 9*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_xmm128 xmm12, 6*16 - save_xmm128 xmm13, 7*16 - save_xmm128 xmm14, 8*16 - save_reg r12, 9*16 + 0*8 - save_reg r13, 9*16 + 1*8 - save_reg r14, 9*16 + 2*8 - save_reg r15, 9*16 + 3*8 - save_reg rdi, 9*16 + 4*8 - save_reg rsi, 9*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - vmovdqa xmm12, [rsp + 6*16] - vmovdqa xmm13, [rsp + 7*16] - vmovdqa xmm14, [rsp + 8*16] - mov r12, [rsp + 9*16 + 0*8] - mov r13, [rsp + 9*16 + 1*8] - mov r14, [rsp + 9*16 + 2*8] - mov r15, [rsp + 9*16 + 3*8] - mov rdi, [rsp + 9*16 + 4*8] - mov rsi, [rsp + 9*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; var1 -;;; var2 -;;; var3 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define arg5 trans2 - %define tmp edx - %define tmp2 edi - %define tmp3 trans2 - %define tmp3_m var(0) - %define tmp4 trans2 - %define tmp4_m var(1) - %define tmp5 trans2 - %define tmp5_m var(2) - %define tmp6 trans2 - %define tmp6_m var(3) - %define return eax - %macro SLDR 2 ;stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*4 ;4 local variables - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*4 ;4 local variables - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest2 tmp3 -%define dest3 tmp4 -%define dest4 tmp5 -%define vskip3 tmp6 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp3_m - %define dest3_m tmp4_m - %define dest4_m tmp5_m - %define vskip3_m tmp6_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ; 64-bit code - default rel - [bits 64] -%endif - - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f xmm14 - %define xgft1_lo xmm13 - %define xgft1_hi xmm12 - %define xgft2_lo xmm11 - %define xgft2_hi xmm10 - %define xgft3_lo xmm9 - %define xgft3_hi xmm8 - %define xgft4_lo xmm7 - %define xgft4_hi xmm6 - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 - %define xp3 xmm4 - %define xp4 xmm5 -%else - %define xmm_trans xmm7 ;reuse xmask0f and xgft1_lo - %define xmask0f xmm_trans - %define xgft1_lo xmm_trans - %define xgft1_hi xmm6 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - %define xgft3_lo xgft1_lo - %define xgft3_hi xgft1_hi - %define xgft4_lo xgft1_lo - %define xgft4_hi xgft1_hi - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 - %define xp3 xmm4 - %define xp4 xmm5 -%endif -align 16 -global gf_4vect_dot_prod_avx:function -func(gf_4vect_dot_prod_avx) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov vskip3, vec - imul vskip3, 96 - SSTR vskip3_m, vskip3 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest3, [dest1+2*PS] - SSTR dest3_m, dest3 - mov dest4, [dest1+3*PS] - SSTR dest4_m, dest4 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop16: - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - vpxor xp4, xp4 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - SLDR src, src_m - mov ptr, [src+vec_i] - - %ifidn PS,8 ;64-bit code - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - vmovdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - - XLDR x0, [ptr+pos] ;Get next source vector - add tmp, 32 - add vec_i, PS - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - %else ;32-bit code - XLDR x0, [ptr+pos] ;Get next source vector - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - %endif - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ;32-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - %endif - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - %ifidn PS,4 ;32-bit code - sal vec, 1 - vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - sar vec, 1 - %endif - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - %ifidn PS,4 ;32-bit code - SLDR vskip3, vskip3_m - vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - vmovdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - add tmp, 32 - add vec_i, PS - %endif - vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_lo ;GF add high and low partials - vpxor xp4, xgft4_hi ;xp4 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - SLDR dest3, dest3_m - XSTR [dest3+pos], xp3 - SLDR dest4, dest4_m - XSTR [dest4+pos], xp4 - - SLDR len, len_m - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_4vect_dot_prod_avx, 02, 05, 0193 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx2.asm.s deleted file mode 100644 index 95aa8eb7c..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_avx2.asm.s +++ /dev/null @@ -1,460 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_4vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 9*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - vmovdqa [rsp + 0*16], xmm6 - vmovdqa [rsp + 1*16], xmm7 - vmovdqa [rsp + 2*16], xmm8 - vmovdqa [rsp + 3*16], xmm9 - vmovdqa [rsp + 4*16], xmm10 - vmovdqa [rsp + 5*16], xmm11 - vmovdqa [rsp + 6*16], xmm12 - vmovdqa [rsp + 7*16], xmm13 - vmovdqa [rsp + 8*16], xmm14 - save_reg r12, 9*16 + 0*8 - save_reg r13, 9*16 + 1*8 - save_reg r14, 9*16 + 2*8 - save_reg r15, 9*16 + 3*8 - save_reg rdi, 9*16 + 4*8 - save_reg rsi, 9*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - vmovdqa xmm12, [rsp + 6*16] - vmovdqa xmm13, [rsp + 7*16] - vmovdqa xmm14, [rsp + 8*16] - mov r12, [rsp + 9*16 + 0*8] - mov r13, [rsp + 9*16 + 1*8] - mov r14, [rsp + 9*16 + 2*8] - mov r15, [rsp + 9*16 + 3*8] - mov rdi, [rsp + 9*16 + 4*8] - mov rsi, [rsp + 9*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; var1 -;;; var2 -;;; var3 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define arg5 trans2 - %define tmp edx - %define tmp.w edx - %define tmp.b dl - %define tmp2 edi - %define tmp3 trans2 - %define tmp3_m var(0) - %define tmp4 trans2 - %define tmp4_m var(1) - %define tmp5 trans2 - %define tmp5_m var(2) - %define tmp6 trans2 - %define tmp6_m var(3) - %define return eax - %macro SLDR 2 ;stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*4 ;4 local variables - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*4 ;4 local variables - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest2 tmp3 -%define dest3 tmp4 -%define dest4 tmp5 -%define vskip3 tmp6 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp3_m - %define dest3_m tmp4_m - %define dest4_m tmp5_m - %define vskip3_m tmp6_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ;64-bit code - default rel - [bits 64] -%endif - - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f ymm14 - %define xmask0fx xmm14 - %define xgft1_lo ymm13 - %define xgft1_hi ymm12 - %define xgft2_lo ymm11 - %define xgft2_hi ymm10 - %define xgft3_lo ymm9 - %define xgft3_hi ymm8 - %define xgft4_lo ymm7 - %define xgft4_hi ymm6 - - %define x0 ymm0 - %define xtmpa ymm1 - %define xp1 ymm2 - %define xp2 ymm3 - %define xp3 ymm4 - %define xp4 ymm5 -%else - %define ymm_trans ymm7 ;reuse xmask0f and xgft1_hi - %define xmask0f ymm_trans - %define xmask0fx xmm7 - %define xgft1_lo ymm6 - %define xgft1_hi ymm_trans - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - %define xgft3_lo xgft1_lo - %define xgft3_hi xgft1_hi - %define xgft4_lo xgft1_lo - %define xgft4_hi xgft1_hi - - %define x0 ymm0 - %define xtmpa ymm1 - %define xp1 ymm2 - %define xp2 ymm3 - %define xp3 ymm4 - %define xp4 ymm5 -%endif -align 16 -global gf_4vect_dot_prod_avx2:function -func(gf_4vect_dot_prod_avx2) - FUNC_SAVE - SLDR len, len_m - sub len, 32 - SSTR len_m, len - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - mov vskip3, vec - imul vskip3, 96 - SSTR vskip3_m, vskip3 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest3, [dest1+2*PS] - SSTR dest3_m, dest3 - mov dest4, [dest1+3*PS] - SSTR dest4_m, dest4 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop32: - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - vpxor xp4, xp4 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - SLDR src, src_m - mov ptr, [src+vec_i] - XLDR x0, [ptr+pos] ;Get next source vector - - add vec_i, PS - %ifidn PS,8 ;64-bit code - vpand xgft4_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xgft4_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xgft4_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - ; " Dx{00}, Dx{10}, ..., Dx{f0} - - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft4_hi, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - add tmp, 32 - %else ;32-bit code - mov cl, 0x0f ;use ecx as a temp variable - vpinsrb xmask0fx, xmask0fx, ecx, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - vpand xgft4_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xgft4_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xgft4_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - %endif - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ; 32-bit code - vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - %endif - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - %ifidn PS,4 ; 32-bit code - sal vec, 1 - vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - sar vec, 1 - %endif - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - %ifidn PS,4 ; 32-bit code - SLDR vskip3, vskip3_m - vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - ; " DX{00}, Dx{10}, ..., Dx{f0} - vperm2i128 xgft4_hi, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - add tmp, 32 - %endif - vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_lo ;GF add high and low partials - vpxor xp4, xgft4_hi ;xp4 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - SLDR dest3, dest3_m - XSTR [dest3+pos], xp3 - SLDR dest4, dest4_m - XSTR [dest4+pos], xp4 - - SLDR len, len_m - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-32 - jmp .loop32 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_4vect_dot_prod_avx2, 04, 05, 0198 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_sse.asm.s deleted file mode 100644 index 2867cca0e..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_dot_prod_sse.asm.s +++ /dev/null @@ -1,443 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_4vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define LOG_PS 3 - %define stack_size 9*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_xmm128 xmm12, 6*16 - save_xmm128 xmm13, 7*16 - save_xmm128 xmm14, 8*16 - save_reg r12, 9*16 + 0*8 - save_reg r13, 9*16 + 1*8 - save_reg r14, 9*16 + 2*8 - save_reg r15, 9*16 + 3*8 - save_reg rdi, 9*16 + 4*8 - save_reg rsi, 9*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - movdqa xmm6, [rsp + 0*16] - movdqa xmm7, [rsp + 1*16] - movdqa xmm8, [rsp + 2*16] - movdqa xmm9, [rsp + 3*16] - movdqa xmm10, [rsp + 4*16] - movdqa xmm11, [rsp + 5*16] - movdqa xmm12, [rsp + 6*16] - movdqa xmm13, [rsp + 7*16] - movdqa xmm14, [rsp + 8*16] - mov r12, [rsp + 9*16 + 0*8] - mov r13, [rsp + 9*16 + 1*8] - mov r14, [rsp + 9*16 + 2*8] - mov r15, [rsp + 9*16 + 3*8] - mov rdi, [rsp + 9*16 + 4*8] - mov rsi, [rsp + 9*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; var0 -;;; var1 -;;; var2 -;;; var3 -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - %define var(x) [ebp - PS - PS*x] - - %define trans ecx - %define trans2 esi - %define arg0 trans ;trans and trans2 are for the variables in stack - %define arg0_m arg(0) - %define arg1 ebx - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 trans - %define arg3_m arg(3) - %define arg4 trans - %define arg4_m arg(4) - %define arg5 trans2 - %define tmp edx - %define tmp2 edi - %define tmp3 trans2 - %define tmp3_m var(0) - %define tmp4 trans2 - %define tmp4_m var(1) - %define tmp5 trans2 - %define tmp5_m var(2) - %define tmp6 trans2 - %define tmp6_m var(3) - %define return eax - %macro SLDR 2 ;stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - sub esp, PS*4 ;4 local variables - push esi - push edi - push ebx - mov arg1, arg(1) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - add esp, PS*4 ;4 local variables - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest1 arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest2 tmp3 -%define dest3 tmp4 -%define dest4 tmp5 -%define vskip3 tmp6 -%define pos return - - %ifidn PS,4 ;32-bit code - %define len_m arg0_m - %define src_m arg3_m - %define dest1_m arg4_m - %define dest2_m tmp3_m - %define dest3_m tmp4_m - %define dest4_m tmp5_m - %define vskip3_m tmp6_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -%ifidn PS,8 ; 64-bit code - default rel - [bits 64] -%endif - - -section .text - -%ifidn PS,8 ;64-bit code - %define xmask0f xmm14 - %define xgft1_lo xmm2 - %define xgft1_hi xmm3 - %define xgft2_lo xmm11 - %define xgft2_hi xmm4 - %define xgft3_lo xmm9 - %define xgft3_hi xmm5 - %define xgft4_lo xmm7 - %define xgft4_hi xmm6 - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm8 - %define xp2 xmm10 - %define xp3 xmm12 - %define xp4 xmm13 -%else - %define xmm_trans xmm7 ;reuse xmask0f and xgft1_lo - %define xmask0f xmm_trans - %define xgft1_lo xmm_trans - %define xgft1_hi xmm6 - %define xgft2_lo xgft1_lo - %define xgft2_hi xgft1_hi - %define xgft3_lo xgft1_lo - %define xgft3_hi xgft1_hi - %define xgft4_lo xgft1_lo - %define xgft4_hi xgft1_hi - - %define x0 xmm0 - %define xtmpa xmm1 - %define xp1 xmm2 - %define xp2 xmm3 - %define xp3 xmm4 - %define xp4 xmm5 -%endif -align 16 -global gf_4vect_dot_prod_sse:function -func(gf_4vect_dot_prod_sse) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov vskip3, vec - imul vskip3, 96 - SSTR vskip3_m, vskip3 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - SLDR dest1, dest1_m - mov dest2, [dest1+PS] - SSTR dest2_m, dest2 - mov dest3, [dest1+2*PS] - SSTR dest3_m, dest3 - mov dest4, [dest1+3*PS] - SSTR dest4_m, dest4 - mov dest1, [dest1] - SSTR dest1_m, dest1 - -.loop16: - pxor xp1, xp1 - pxor xp2, xp2 - pxor xp3, xp3 - pxor xp4, xp4 - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - SLDR src, src_m - mov ptr, [src+vec_i] - - %ifidn PS,8 ;64-bit code - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - movdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - movdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - movdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - - XLDR x0, [ptr+pos] ;Get next source vector - add tmp, 32 - add vec_i, PS - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - %else ;32-bit code - XLDR x0, [ptr+pos] ;Get next source vector - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - %endif - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp1, xgft1_hi ;xp1 += partial - - %ifidn PS,4 ;32-bit code - movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - %endif - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pxor xp2, xgft2_hi ;xp2 += partial - - %ifidn PS,4 ;32-bit code - sal vec, 1 - movdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - sar vec, 1 - %endif - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xgft3_lo ;GF add high and low partials - pxor xp3, xgft3_hi ;xp3 += partial - - %ifidn PS,4 ;32-bit code - SLDR vskip3, vskip3_m - movdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - movdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - add tmp, 32 - add vec_i, PS - %endif - pshufb xgft4_hi, x0 ;Lookup mul table of high nibble - pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft4_hi, xgft4_lo ;GF add high and low partials - pxor xp4, xgft4_hi ;xp4 += partial - - cmp vec_i, vec - jl .next_vect - - SLDR dest1, dest1_m - SLDR dest2, dest2_m - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - SLDR dest3, dest3_m - XSTR [dest3+pos], xp3 - SLDR dest4, dest4_m - XSTR [dest4+pos], xp4 - - SLDR len, len_m - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_4vect_dot_prod_sse, 00, 06, 0064 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx.asm.s deleted file mode 100644 index 5b2891628..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx.asm.s +++ /dev/null @@ -1,336 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_4vect_mad_avx(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r15, 10*16 + 2*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r15, [rsp + 10*16 + 2*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r12 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - %endmacro - %macro FUNC_RESTORE 0 - pop r12 - %endmacro -%endif - -;;; gf_4vect_mad_avx(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 tmp2 -%define dest4 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft3_hi xmm14 -%define xgft4_hi xmm13 -%define xgft4_lo xmm12 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xtmph4 xmm8 -%define xtmpl4 xmm9 -%define xd1 xmm10 -%define xd2 xmm11 -%define xd3 xtmph1 -%define xd4 xtmpl1 - -align 16 -global gf_4vect_mad_avx:function -func(gf_4vect_mad_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - - mov tmp, vec - - sal vec_i, 5 ;Multiply by 32 - lea tmp3, [mul_array + vec_i] - - sal tmp, 6 ;Multiply by 64 - vmovdqu xgft3_hi, [tmp3+tmp+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - sal vec, 5 ;Multiply by 32 - add tmp, vec - vmovdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - vmovdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - - mov dest2, [dest1+PS] ; reuse mul_array - mov dest3, [dest1+2*PS] - mov dest4, [dest1+3*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 - - XLDR xd3, [dest3+pos] ;Reuse xtmph1, Get next dest vector - XLDR xd4, [dest4+pos] ;Reuse xtmpl1, Get next dest vector - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xd2, xtmph2 - - ; dest3 - vpshufb xtmph3, xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials - vpxor xd3, xd3, xtmph3 - - ; dest4 - vpshufb xtmph4, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl4, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph4, xtmph4, xtmpl4 ;GF add high and low partials - vpxor xd4, xd4, xtmph4 - - XSTR [dest1+pos], xd1 ;Store result - XSTR [dest2+pos], xd2 ;Store result - XSTR [dest3+pos], xd3 ;Store result - XSTR [dest4+pos], xd4 ;Store result - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - - mov tmp, len ;Overlapped offset length-16 - - XLDR x0, [src+tmp] ;Get next source vector - - vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - XLDR xtmph4, [dest3+tmp] ;Get next dest vector - - sub len, pos - - vmovdqa xtmpl4, [constip16] ;Load const of i + 16 - vpinsrb xtmph3, xtmph3, len.w, 15 - vpshufb xtmph3, xtmph3, xmask0f ;Broadcast len to all bytes - vpcmpgtb xtmph3, xtmph3, xtmpl4 - - XLDR xtmpl4, [dest4+tmp] ;Get next dest vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpand xtmph1, xtmph1, xtmph3 - vpxor xd1, xd1, xtmph1 - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpand xtmph2, xtmph2, xtmph3 - vpxor xd2, xd2, xtmph2 - - ; dest3 - vpshufb xgft3_hi, xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_hi, xtmpl3 ;GF add high and low partials - vpand xgft3_hi, xgft3_hi, xtmph3 - vpxor xtmph4, xtmph4, xgft3_hi - - ; dest4 - vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials - vpand xgft4_hi, xgft4_hi, xtmph3 - vpxor xtmpl4, xtmpl4, xgft4_hi - - XSTR [dest1+tmp], xd1 ;Store result - XSTR [dest2+tmp], xd2 ;Store result - XSTR [dest3+tmp], xtmph4 ;Store result - XSTR [dest4+tmp], xtmpl4 ;Store result - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_4vect_mad_avx, 02, 01, 020a diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx2.asm.s deleted file mode 100644 index 5df1f8385..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_avx2.asm.s +++ /dev/null @@ -1,342 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_4vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r15, 10*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r15, [rsp + 10*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - - -;;; gf_4vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 vec -%define dest4 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f ymm15 -%define xmask0fx xmm15 -%define xgft1_lo ymm14 -%define xgft2_lo ymm13 -%define xgft3_lo ymm12 -%define xgft4_lo ymm11 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xtmpl ymm2 -%define xtmplx xmm2 -%define xtmph1 ymm3 -%define xtmph1x xmm3 -%define xtmph2 ymm4 -%define xtmph3 ymm5 -%define xtmph4 ymm6 -%define xd1 ymm7 -%define xd2 ymm8 -%define xd3 ymm9 -%define xd4 ymm10 - -align 16 -global gf_4vect_mad_avx2:function -func(gf_4vect_mad_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 ;Multiply by 32 - lea tmp, [mul_array + vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - add tmp, vec - vmovdqu xgft4_lo, [tmp+2*vec] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - - mov dest2, [dest1+PS] ; reuse mul_array - mov dest3, [dest1+2*PS] ; reuse vec - mov dest4, [dest1+3*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop32: - XLDR x0, [src+pos] ;Get next source vector - - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - XLDR xd3, [dest3+pos] ;Get next dest vector - XLDR xd4, [dest4+pos] ;reuse xtmpl1. Get next dest vector - - vpand xtmpl, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vperm2i128 xtmpa, xtmpl, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xtmpl, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph4, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl ;GF add high and low partials - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - ; dest3 - vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xtmpl ;GF add high and low partials - vpxor xd3, xd3, xtmph3 ;xd3 += partial - - ; dest4 - vpshufb xtmph4, xtmph4, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph4, xtmph4, xtmpl ;GF add high and low partials - vpxor xd4, xd4, xtmph4 ;xd4 += partial - - XSTR [dest1+pos], xd1 - XSTR [dest2+pos], xd2 - XSTR [dest3+pos], xd3 - XSTR [dest4+pos], xd4 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - -.lessthan32: - ;; Tail len - ;; Do one more overlap pass - mov tmp.b, 0x1f - vpinsrb xtmph1x, xtmph1x, tmp.w, 0 - vpbroadcastb xtmph1, xtmph1x ;Construct mask 0x1f1f1f... - - mov tmp, len ;Overlapped offset length-32 - - XLDR x0, [src+tmp] ;Get next source vector - - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - XLDR xd3, [dest3+tmp] ;Get next dest vector - XLDR xd4, [dest4+tmp] ;Get next dest vector - - sub len, pos - - vmovdqa xtmph2, [constip32] ;Load const of i + 32 - vpinsrb xtmplx, xtmplx, len.w, 15 - vinserti128 xtmpl, xtmpl, xtmplx, 1 ;swapped to xtmplx | xtmplx - vpshufb xtmpl, xtmpl, xtmph1 ;Broadcast len to all bytes. xtmph1=0x1f1f1f... - vpcmpgtb xtmpl, xtmpl, xtmph2 - - vpand xtmph1, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vperm2i128 xtmpa, xtmph1, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xtmph1, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph4, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xgft1_lo ;GF add high and low partials - vpand xtmph1, xtmph1, xtmpl - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xgft2_lo ;GF add high and low partials - vpand xtmph2, xtmph2, xtmpl - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - ; dest3 - vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xgft3_lo ;GF add high and low partials - vpand xtmph3, xtmph3, xtmpl - vpxor xd3, xd3, xtmph3 ;xd3 += partial - - ; dest4 - vpshufb xtmph4, xtmph4, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph4, xtmph4, xgft4_lo ;GF add high and low partials - vpand xtmph4, xtmph4, xtmpl - vpxor xd4, xd4, xtmph4 ;xd4 += partial - - XSTR [dest1+tmp], xd1 - XSTR [dest2+tmp], xd2 - XSTR [dest3+tmp], xd3 - XSTR [dest4+tmp], xd4 - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data -align 32 -constip32: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef - -;;; func core, ver, snum -slversion gf_4vect_mad_avx2, 04, 01, 020b diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_sse.asm.s deleted file mode 100644 index f753c1309..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_4vect_mad_sse.asm.s +++ /dev/null @@ -1,342 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_4vect_mad_sse(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r15, 10*16 + 2*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r15, [rsp + 10*16 + 2*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r12 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - %endmacro - %macro FUNC_RESTORE 0 - pop r12 - %endmacro -%endif - -;;; gf_4vect_mad_sse(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 tmp2 -%define dest4 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft3_hi xmm14 -%define xgft4_hi xmm13 -%define xgft4_lo xmm12 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xtmph4 xmm8 -%define xtmpl4 xmm9 -%define xd1 xmm10 -%define xd2 xmm11 -%define xd3 xtmph1 -%define xd4 xtmpl1 - -align 16 -global gf_4vect_mad_sse:function -func(gf_4vect_mad_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov tmp, vec - - sal vec_i, 5 ;Multiply by 32 - lea tmp3, [mul_array + vec_i] - - sal tmp, 6 ;Multiply by 64 - - movdqu xgft3_hi, [tmp3+tmp+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - sal vec, 5 ;Multiply by 32 - add tmp, vec - movdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - movdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - - mov dest2, [dest1+PS] ; reuse mul_array - mov dest3, [dest1+2*PS] - mov dest4, [dest1+3*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - - movdqa xtmph3, xgft3_hi - movdqa xtmpl4, xgft4_lo - movdqa xtmph4, xgft4_hi - - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ; dest1 - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pxor xd1, xtmph1 - - XLDR xd3, [dest3+pos] ;Reuse xtmph1, Get next dest vector - XLDR xd4, [dest4+pos] ;Reuse xtmpl1, Get next dest vector - - ; dest2 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pxor xd2, xtmph2 - - ; dest3 - pshufb xtmph3, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph3, xtmpl3 ;GF add high and low partials - pxor xd3, xtmph3 - - ; dest4 - pshufb xtmph4, x0 ;Lookup mul table of high nibble - pshufb xtmpl4, xtmpa ;Lookup mul table of low nibble - pxor xtmph4, xtmpl4 ;GF add high and low partials - pxor xd4, xtmph4 - - XSTR [dest1+pos], xd1 ;Store result - XSTR [dest2+pos], xd2 ;Store result - XSTR [dest3+pos], xd3 ;Store result - XSTR [dest4+pos], xd4 ;Store result - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - mov tmp, len ;Overlapped offset length-16 - - XLDR x0, [src+tmp] ;Get next source vector - - movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - XLDR xtmph4, [dest3+tmp] ;Reuse xtmph1. Get next dest vector - - sub len, pos - - movdqa xtmpl4, [constip16] ;Load const of i + 16 - pinsrb xtmph3, len.w, 15 - pshufb xtmph3, xmask0f ;Broadcast len to all bytes - pcmpgtb xtmph3, xtmpl4 - - XLDR xtmpl4, [dest4+tmp] ;Get next dest vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ; dest1 - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pand xtmph1, xtmph3 - pxor xd1, xtmph1 - - ; dest2 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pand xtmph2, xtmph3 - pxor xd2, xtmph2 - - ; dest3 - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xtmpl3 ;GF add high and low partials - pand xgft3_hi, xtmph3 - pxor xtmph4, xgft3_hi - - ; dest4 - pshufb xgft4_hi, x0 ;Lookup mul table of high nibble - pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft4_hi, xgft4_lo ;GF add high and low partials - pand xgft4_hi, xtmph3 - pxor xtmpl4, xgft4_hi - - XSTR [dest1+tmp], xd1 ;Store result - XSTR [dest2+tmp], xd2 ;Store result - XSTR [dest3+tmp], xtmph4 ;Store result - XSTR [dest4+tmp], xtmpl4 ;Store result - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 - -mask0f: - ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_4vect_mad_sse, 00, 01, 0209 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx.asm.s deleted file mode 100644 index 41fd301d3..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx.asm.s +++ /dev/null @@ -1,303 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_5vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_xmm128 xmm12, 6*16 - save_xmm128 xmm13, 7*16 - save_xmm128 xmm14, 8*16 - save_xmm128 xmm15, 9*16 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - save_reg rsi, 10*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - vmovdqa xmm12, [rsp + 6*16] - vmovdqa xmm13, [rsp + 7*16] - vmovdqa xmm14, [rsp + 8*16] - vmovdqa xmm15, [rsp + 9*16] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - mov rsi, [rsp + 10*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest1 tmp3 -%define dest2 tmp4 -%define vskip1 tmp5 -%define vskip3 tmp6 -%define pos return - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft1_lo xmm14 -%define xgft1_hi xmm13 -%define xgft2_lo xmm12 -%define xgft2_hi xmm11 -%define xgft3_lo xmm10 -%define xgft3_hi xmm9 -%define xgft4_lo xmm8 -%define xgft4_hi xmm7 - - -%define x0 xmm0 -%define xtmpa xmm1 -%define xp1 xmm2 -%define xp2 xmm3 -%define xp3 xmm4 -%define xp4 xmm5 -%define xp5 xmm6 - -align 16 -global gf_5vect_dot_prod_avx:function -func(gf_5vect_dot_prod_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov vskip1, vec - imul vskip1, 32 - mov vskip3, vec - imul vskip3, 96 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - mov dest1, [dest] - mov dest2, [dest+PS] - - -.loop16: - mov tmp, mul_array - xor vec_i, vec_i - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - vpxor xp4, xp4 - vpxor xp5, xp5 - - -.next_vect: - mov ptr, [src+vec_i] - add vec_i, PS - XLDR x0, [ptr+pos] ;Get next source vector - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - vmovdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - vmovdqu xgft1_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - vmovdqu xgft1_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - add tmp, 32 - - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_lo ;GF add high and low partials - vpxor xp4, xgft4_hi ;xp4 += partial - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp5, xgft1_hi ;xp5 += partial - - cmp vec_i, vec - jl .next_vect - - mov tmp, [dest+2*PS] - mov ptr, [dest+3*PS] - mov vec_i, [dest+4*PS] - - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - XSTR [tmp+pos], xp3 - XSTR [ptr+pos], xp4 - XSTR [vec_i+pos], xp5 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_5vect_dot_prod_avx, 02, 04, 0194 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx2.asm.s deleted file mode 100644 index 2698addea..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_avx2.asm.s +++ /dev/null @@ -1,315 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_5vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - vmovdqa [rsp + 0*16], xmm6 - vmovdqa [rsp + 1*16], xmm7 - vmovdqa [rsp + 2*16], xmm8 - vmovdqa [rsp + 3*16], xmm9 - vmovdqa [rsp + 4*16], xmm10 - vmovdqa [rsp + 5*16], xmm11 - vmovdqa [rsp + 6*16], xmm12 - vmovdqa [rsp + 7*16], xmm13 - vmovdqa [rsp + 8*16], xmm14 - vmovdqa [rsp + 9*16], xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - save_reg rsi, 10*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - vmovdqa xmm12, [rsp + 6*16] - vmovdqa xmm13, [rsp + 7*16] - vmovdqa xmm14, [rsp + 8*16] - vmovdqa xmm15, [rsp + 9*16] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - mov rsi, [rsp + 10*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest1 tmp3 -%define dest2 tmp4 -%define vskip1 tmp5 -%define vskip3 tmp6 -%define pos return - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f ymm15 -%define xmask0fx xmm15 -%define xgft1_lo ymm14 -%define xgft1_hi ymm13 -%define xgft2_lo ymm12 -%define xgft2_hi ymm11 -%define xgft3_lo ymm10 -%define xgft3_hi ymm9 -%define xgft4_lo ymm8 -%define xgft4_hi ymm7 - - -%define x0 ymm0 -%define xtmpa ymm1 -%define xp1 ymm2 -%define xp2 ymm3 -%define xp3 ymm4 -%define xp4 ymm5 -%define xp5 ymm6 - -align 16 -global gf_5vect_dot_prod_avx2:function -func(gf_5vect_dot_prod_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - mov vskip1, vec - imul vskip1, 32 - mov vskip3, vec - imul vskip3, 96 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - mov dest1, [dest] - mov dest2, [dest+PS] - - -.loop32: - mov tmp, mul_array - xor vec_i, vec_i - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - vpxor xp4, xp4 - vpxor xp5, xp5 - - -.next_vect: - mov ptr, [src+vec_i] - XLDR x0, [ptr+pos] ;Get next source vector - add vec_i, PS - - vpand xgft4_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xgft4_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xgft4_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - ; " Dx{00}, Dx{10}, ..., Dx{f0} - - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft4_hi, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - vmovdqu xgft1_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - ; " Ex{00}, Ex{10}, ..., Ex{f0} - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - add tmp, 32 - - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_lo ;GF add high and low partials - vpxor xp4, xgft4_hi ;xp4 += partial - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp5, xgft1_hi ;xp5 += partial - - cmp vec_i, vec - jl .next_vect - - mov tmp, [dest+2*PS] - mov ptr, [dest+3*PS] - mov vec_i, [dest+4*PS] - - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - XSTR [tmp+pos], xp3 - XSTR [ptr+pos], xp4 - XSTR [vec_i+pos], xp5 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop32 ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_5vect_dot_prod_avx2, 04, 04, 0199 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_sse.asm.s deleted file mode 100644 index 5c8c90359..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_dot_prod_sse.asm.s +++ /dev/null @@ -1,304 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_5vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_xmm128 xmm12, 6*16 - save_xmm128 xmm13, 7*16 - save_xmm128 xmm14, 8*16 - save_xmm128 xmm15, 9*16 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - save_reg rsi, 10*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - movdqa xmm6, [rsp + 0*16] - movdqa xmm7, [rsp + 1*16] - movdqa xmm8, [rsp + 2*16] - movdqa xmm9, [rsp + 3*16] - movdqa xmm10, [rsp + 4*16] - movdqa xmm11, [rsp + 5*16] - movdqa xmm12, [rsp + 6*16] - movdqa xmm13, [rsp + 7*16] - movdqa xmm14, [rsp + 8*16] - movdqa xmm15, [rsp + 9*16] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - mov rsi, [rsp + 10*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest1 tmp3 -%define dest2 tmp4 -%define vskip1 tmp5 -%define vskip3 tmp6 -%define pos return - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft1_lo xmm2 -%define xgft1_hi xmm3 -%define xgft2_lo xmm4 -%define xgft2_hi xmm5 -%define xgft3_lo xmm10 -%define xgft3_hi xmm6 -%define xgft4_lo xmm8 -%define xgft4_hi xmm7 - - -%define x0 xmm0 -%define xtmpa xmm1 -%define xp1 xmm9 -%define xp2 xmm11 -%define xp3 xmm12 -%define xp4 xmm13 -%define xp5 xmm14 - -align 16 -global gf_5vect_dot_prod_sse:function -func(gf_5vect_dot_prod_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov vskip1, vec - imul vskip1, 32 - mov vskip3, vec - imul vskip3, 96 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - mov dest1, [dest] - mov dest2, [dest+PS] - - -.loop16: - mov tmp, mul_array - xor vec_i, vec_i - pxor xp1, xp1 - pxor xp2, xp2 - pxor xp3, xp3 - pxor xp4, xp4 - pxor xp5, xp5 - - -.next_vect: - mov ptr, [src+vec_i] - add vec_i, PS - XLDR x0, [ptr+pos] ;Get next source vector - - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - movdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - movdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - movdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - movdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp1, xgft1_hi ;xp1 += partial - - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pxor xp2, xgft2_hi ;xp2 += partial - - movdqu xgft1_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - movdqu xgft1_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - add tmp, 32 - - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xgft3_lo ;GF add high and low partials - pxor xp3, xgft3_hi ;xp3 += partial - - pshufb xgft4_hi, x0 ;Lookup mul table of high nibble - pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft4_hi, xgft4_lo ;GF add high and low partials - pxor xp4, xgft4_hi ;xp4 += partial - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp5, xgft1_hi ;xp5 += partial - - cmp vec_i, vec - jl .next_vect - - mov tmp, [dest+2*PS] - mov ptr, [dest+3*PS] - mov vec_i, [dest+4*PS] - - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - XSTR [tmp+pos], xp3 - XSTR [ptr+pos], xp4 - XSTR [vec_i+pos], xp5 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_5vect_dot_prod_sse, 00, 05, 0065 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx.asm.s deleted file mode 100644 index 6b534a353..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx.asm.s +++ /dev/null @@ -1,365 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_5vect_mad_avx(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 - %define tmp4 r14 - %define return rax - %define return.w eax - %define stack_size 16*10 + 5*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r12 - %define tmp4 r13 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - %endmacro - %macro FUNC_RESTORE 0 - pop r13 - pop r12 - %endmacro -%endif - -;;; gf_5vect_mad_avx(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp4 -%define dest3 mul_array -%define dest4 tmp2 -%define dest5 vec_i - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft5_hi xmm14 -%define xgft4_lo xmm13 -%define xgft4_hi xmm12 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xtmph5 xmm8 -%define xtmpl5 xmm9 -%define xd1 xmm10 -%define xd2 xmm11 -%define xd3 xtmpl1 -%define xd4 xtmph1 -%define xd5 xtmpl2 - - -align 16 -global gf_5vect_mad_avx:function -func(gf_5vect_mad_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov tmp, vec - sal vec_i, 5 ;Multiply by 32 - lea tmp3, [mul_array + vec_i] - sal tmp, 6 ;Multiply by 64 - vmovdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - sal vec, 5 ;Multiply by 32 - add tmp, vec - vmovdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - vmovdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - - mov dest3, [dest1+2*PS] ; reuse mul_array - mov dest4, [dest1+3*PS] - mov dest5, [dest1+4*PS] ; reuse vec_i - mov dest2, [dest1+PS] - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - - vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 - - XLDR xd3, [dest3+pos] ;Reuse xtmpl1, Get next dest vector - XLDR xd4, [dest4+pos] ;Reuse xtmph1, Get next dest vector - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xd2, xtmph2 - - XLDR xd5, [dest5+pos] ;Reuse xtmpl2. Get next dest vector - - ; dest3 - vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials - vpxor xd3, xd3, xtmph3 - - ; dest4 - vpshufb xtmph2, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl3 ;GF add high and low partials - vpxor xd4, xd4, xtmph2 - - ; dest5 - vpshufb xtmph5, xgft5_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl5, xtmpl5, xtmpa ;Lookup mul table of low nibble - vpxor xtmph5, xtmph5, xtmpl5 ;GF add high and low partials - vpxor xd5, xd5, xtmph5 - - XSTR [dest1+pos], xd1 ;Store result into dest1 - XSTR [dest2+pos], xd2 ;Store result into dest2 - XSTR [dest3+pos], xd3 ;Store result into dest3 - XSTR [dest4+pos], xd4 ;Store result into dest4 - XSTR [dest5+pos], xd5 ;Store result into dest5 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - mov tmp, len ;Overlapped offset length-16 - XLDR x0, [src+tmp] ;Get next source vector - - sub len, pos - - vmovdqa xtmph1, [constip16] ;Load const of i + 16 - vpinsrb xtmph5, len.w, 15 - vpshufb xtmph5, xmask0f ;Broadcast len to all bytes - vpcmpgtb xtmph5, xtmph5, xtmph1 - - vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpand xtmph1, xtmph1, xtmph5 - vpxor xd1, xd1, xtmph1 - - XLDR xd3, [dest3+tmp] ;Reuse xtmpl1, Get next dest vector - XLDR xd4, [dest4+tmp] ;Reuse xtmph1, Get next dest vector - - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpand xtmph2, xtmph2, xtmph5 - vpxor xd2, xd2, xtmph2 - - XLDR xd5, [dest5+tmp] ;Reuse xtmpl2. Get next dest vector - - ; dest3 - vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials - vpand xtmph3, xtmph3, xtmph5 - vpxor xd3, xd3, xtmph3 - - ; dest4 - vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials - vpand xgft4_hi, xgft4_hi, xtmph5 - vpxor xd4, xd4, xgft4_hi - - ; dest5 - vpshufb xgft5_hi, xgft5_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl5, xtmpl5, xtmpa ;Lookup mul table of low nibble - vpxor xgft5_hi, xgft5_hi, xtmpl5 ;GF add high and low partials - vpand xgft5_hi, xgft5_hi, xtmph5 - vpxor xd5, xd5, xgft5_hi - - XSTR [dest1+tmp], xd1 ;Store result into dest1 - XSTR [dest2+tmp], xd2 ;Store result into dest2 - XSTR [dest3+tmp], xd3 ;Store result into dest3 - XSTR [dest4+tmp], xd4 ;Store result into dest4 - XSTR [dest5+tmp], xd5 ;Store result into dest5 - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_5vect_mad_avx, 02, 01, 020d diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx2.asm.s deleted file mode 100644 index b495c2189..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_avx2.asm.s +++ /dev/null @@ -1,363 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_5vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r15, 10*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r15, [rsp + 10*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_5vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp2 -%define dest3 mul_array -%define dest4 vec -%define dest5 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f ymm15 -%define xmask0fx xmm15 -%define xgft1_lo ymm14 -%define xgft2_lo ymm13 -%define xgft3_lo ymm12 -%define xgft4_lo ymm11 -%define xgft5_lo ymm10 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xtmpl ymm2 -%define xtmplx xmm2 -%define xtmph1 ymm3 -%define xtmph1x xmm3 -%define xtmph2 ymm4 -%define xd1 ymm5 -%define xd2 ymm6 -%define xd3 ymm7 -%define xd4 ymm8 -%define xd5 ymm9 - -align 16 -global gf_5vect_mad_avx2:function -func(gf_5vect_mad_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 ;Multiply by 32 - lea tmp, [mul_array + vec_i] - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vmovdqu xgft5_lo, [tmp+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - ; " Ex{00}, Ex{10}, ..., Ex{f0} - add tmp, vec - vmovdqu xgft4_lo, [tmp+2*vec] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - ; " Dx{00}, Dx{10}, ..., Dx{f0} - - mov dest3, [dest1+2*PS] ; reuse mul_array - mov dest4, [dest1+3*PS] ; reuse vec - mov dest5, [dest1+4*PS] ; reuse vec_i - mov dest2, [dest1+PS] - mov dest1, [dest1] - -.loop32: - XLDR x0, [src+pos] ;Get next source vector - - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - XLDR xd3, [dest3+pos] ;Get next dest vector - XLDR xd4, [dest4+pos] ;Get next dest vector - XLDR xd5, [dest5+pos] ;Get next dest vector - - vpand xtmpl, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xtmpl, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xtmpl, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - vperm2i128 xtmph1, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl ;GF add high and low partials - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - vperm2i128 xtmph2, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - ; dest3 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials - vpxor xd3, xd3, xtmph1 ;xd3 += partial - - vperm2i128 xtmph1, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo - ; dest4 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl ;GF add high and low partials - vpxor xd4, xd4, xtmph2 ;xd4 += partial - - ; dest5 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials - vpxor xd5, xd5, xtmph1 ;xd5 += partial - - XSTR [dest1+pos], xd1 - XSTR [dest2+pos], xd2 - XSTR [dest3+pos], xd3 - XSTR [dest4+pos], xd4 - XSTR [dest5+pos], xd5 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - -.lessthan32: - ;; Tail len - ;; Do one more overlap pass - mov tmp.b, 0x1f - vpinsrb xtmph1x, xtmph1x, tmp.w, 0 - vpbroadcastb xtmph1, xtmph1x ;Construct mask 0x1f1f1f... - - mov tmp, len ;Overlapped offset length-32 - - XLDR x0, [src+tmp] ;Get next source vector - - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - XLDR xd3, [dest3+tmp] ;Get next dest vector - XLDR xd4, [dest4+tmp] ;Get next dest vector - XLDR xd5, [dest5+tmp] ;Get next dest vector - - sub len, pos - - vmovdqa xtmph2, [constip32] ;Load const of i + 32 - vpinsrb xtmplx, xtmplx, len.w, 15 - vinserti128 xtmpl, xtmpl, xtmplx, 1 ;swapped to xtmplx | xtmplx - vpshufb xtmpl, xtmpl, xtmph1 ;Broadcast len to all bytes. xtmph1=0x1f1f1f... - vpcmpgtb xtmpl, xtmpl, xtmph2 - - vpand xtmph1, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xtmph1, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xtmph1, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - - ; dest1 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xgft1_lo ;GF add high and low partials - vpand xtmph1, xtmph1, xtmpl - vpxor xd1, xd1, xtmph1 ;xd1 += partial - - vperm2i128 xtmph1, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - ; dest2 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xgft2_lo ;GF add high and low partials - vpand xtmph2, xtmph2, xtmpl - vpxor xd2, xd2, xtmph2 ;xd2 += partial - - vperm2i128 xtmph2, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - ; dest3 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xgft3_lo ;GF add high and low partials - vpand xtmph1, xtmph1, xtmpl - vpxor xd3, xd3, xtmph1 ;xd3 += partial - - vperm2i128 xtmph1, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo - ; dest4 - vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xgft4_lo ;GF add high and low partials - vpand xtmph2, xtmph2, xtmpl - vpxor xd4, xd4, xtmph2 ;xd4 += partial - - ; dest5 - vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xgft5_lo ;GF add high and low partials - vpand xtmph1, xtmph1, xtmpl - vpxor xd5, xd5, xtmph1 ;xd5 += partial - - XSTR [dest1+tmp], xd1 - XSTR [dest2+tmp], xd2 - XSTR [dest3+tmp], xd3 - XSTR [dest4+tmp], xd4 - XSTR [dest5+tmp], xd5 - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data -align 32 -constip32: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef - -;;; func core, ver, snum -slversion gf_5vect_mad_avx2, 04, 01, 020e diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_sse.asm.s deleted file mode 100644 index b26d4bcad..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_5vect_mad_sse.asm.s +++ /dev/null @@ -1,373 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_5vect_mad_sse(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 - %define tmp4 r14 - %define return rax - %define return.w eax - %define stack_size 16*10 + 5*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r12 - %define tmp4 r13 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - %endmacro - %macro FUNC_RESTORE 0 - pop r13 - pop r12 - %endmacro -%endif - -;;; gf_5vect_mad_sse(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp4 -%define dest3 mul_array -%define dest4 tmp2 -%define dest5 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft5_hi xmm14 -%define xgft4_lo xmm13 -%define xgft4_hi xmm12 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xtmph5 xmm8 -%define xtmpl5 xmm9 -%define xd1 xmm10 -%define xd2 xmm11 -%define xd3 xtmpl1 -%define xd4 xtmph1 -%define xd5 xtmpl2 - - -align 16 -global gf_5vect_mad_sse:function -func(gf_5vect_mad_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov tmp, vec - sal vec_i, 5 ;Multiply by 32 - lea tmp3, [mul_array + vec_i] - sal tmp, 6 ;Multiply by 64 - movdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - sal vec, 5 ;Multiply by 32 - add tmp, vec - movdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - movdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - - mov dest3, [dest1+2*PS] ; reuse mul_array - mov dest4, [dest1+3*PS] - mov dest5, [dest1+4*PS] ; reuse vec_i - mov dest2, [dest1+PS] - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - - movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - movdqa xtmph5, xgft5_hi ;Reload const array registers - - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ; dest1 - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pxor xd1, xtmph1 - - XLDR xd3, [dest3+pos] ;Reuse xtmpl1, Get next dest vector - XLDR xd4, [dest4+pos] ;Reuse xtmph1. Get next dest vector - - ; dest2 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pxor xd2, xtmph2 - - XLDR xd5, [dest5+pos] ;Reuse xtmpl2. Get next dest vector - - ; dest3 - pshufb xtmph3, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph3, xtmpl3 ;GF add high and low partials - pxor xd3, xtmph3 - - movdqa xtmph2, xgft4_hi ;Reload const array registers - movdqa xtmpl3, xgft4_lo ;Reload const array registers - - ; dest5 - pshufb xtmph5, x0 ;Lookup mul table of high nibble - pshufb xtmpl5, xtmpa ;Lookup mul table of low nibble - pxor xtmph5, xtmpl5 ;GF add high and low partials - pxor xd5, xtmph5 - - ; dest4 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl3 ;GF add high and low partials - pxor xd4, xtmph2 - - XSTR [dest1+pos], xd1 ;Store result into dest1 - XSTR [dest2+pos], xd2 ;Store result into dest2 - XSTR [dest3+pos], xd3 ;Store result into dest3 - XSTR [dest4+pos], xd4 ;Store result into dest4 - XSTR [dest5+pos], xd5 ;Store result into dest5 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - mov tmp, len ;Overlapped offset length-16 - XLDR x0, [src+tmp] ;Get next source vector - - sub len, pos - - movdqa xtmpl1, [constip16] ;Load const of i + 16 - pinsrb xtmph5, len.w, 15 - pshufb xtmph5, xmask0f ;Broadcast len to all bytes - pcmpgtb xtmph5, xtmpl1 - - movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ; dest1 - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pand xtmph1, xtmph5 - pxor xd1, xtmph1 - - XLDR xd3, [dest3+tmp] ;Reuse xtmpl1, Get next dest vector - XLDR xd4, [dest4+tmp] ;Reuse xtmph1. Get next dest vector - - ; dest2 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pand xtmph2, xtmph5 - pxor xd2, xtmph2 - - XLDR xd5, [dest5+tmp] ;Reuse xtmpl2. Get next dest vector - - ; dest3 - pshufb xtmph3, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph3, xtmpl3 ;GF add high and low partials - pand xtmph3, xtmph5 - pxor xd3, xtmph3 - - ; dest4 - pshufb xgft4_hi, x0 ;Lookup mul table of high nibble - pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft4_hi, xgft4_lo ;GF add high and low partials - pand xgft4_hi, xtmph5 - pxor xd4, xgft4_hi - - ; dest5 - pshufb xgft5_hi, x0 ;Lookup mul table of high nibble - pshufb xtmpl5, xtmpa ;Lookup mul table of low nibble - pxor xgft5_hi, xtmpl5 ;GF add high and low partials - pand xgft5_hi, xtmph5 - pxor xd5, xgft5_hi - - XSTR [dest1+tmp], xd1 ;Store result into dest1 - XSTR [dest2+tmp], xd2 ;Store result into dest2 - XSTR [dest3+tmp], xd3 ;Store result into dest3 - XSTR [dest4+tmp], xd4 ;Store result into dest4 - XSTR [dest5+tmp], xd5 ;Store result into dest5 - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 - -mask0f: - ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_5vect_mad_sse, 00, 01, 020c diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx.asm.s deleted file mode 100644 index fb29f76f1..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx.asm.s +++ /dev/null @@ -1,315 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_6vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_xmm128 xmm12, 6*16 - save_xmm128 xmm13, 7*16 - save_xmm128 xmm14, 8*16 - save_xmm128 xmm15, 9*16 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - save_reg rsi, 10*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - vmovdqa xmm12, [rsp + 6*16] - vmovdqa xmm13, [rsp + 7*16] - vmovdqa xmm14, [rsp + 8*16] - vmovdqa xmm15, [rsp + 9*16] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - mov rsi, [rsp + 10*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest1 tmp3 -%define dest2 tmp4 -%define vskip1 tmp5 -%define vskip3 tmp6 -%define pos return - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft1_lo xmm14 -%define xgft1_hi xmm13 -%define xgft2_lo xmm12 -%define xgft2_hi xmm11 -%define xgft3_lo xmm10 -%define xgft3_hi xmm9 -%define x0 xmm0 -%define xtmpa xmm1 -%define xp1 xmm2 -%define xp2 xmm3 -%define xp3 xmm4 -%define xp4 xmm5 -%define xp5 xmm6 -%define xp6 xmm7 - -align 16 -global gf_6vect_dot_prod_avx:function -func(gf_6vect_dot_prod_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov vskip1, vec - imul vskip1, 32 - mov vskip3, vec - imul vskip3, 96 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - mov dest1, [dest] - mov dest2, [dest+PS] - - -.loop16: - mov tmp, mul_array - xor vec_i, vec_i - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - vpxor xp4, xp4 - vpxor xp5, xp5 - vpxor xp6, xp6 - -.next_vect: - mov ptr, [src+vec_i] - add vec_i, PS - XLDR x0, [ptr+pos] ;Get next source vector - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - vmovdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - lea ptr, [vskip1 + vskip1*4] ;ptr = vskip5 - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - - vmovdqu xgft1_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - vmovdqu xgft1_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - vmovdqu xgft2_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - vmovdqu xgft2_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - vmovdqu xgft3_lo, [tmp+ptr] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} - vmovdqu xgft3_hi, [tmp+ptr+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} - add tmp, 32 - - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp4, xgft1_hi ;xp4 += partial - - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp5, xgft2_hi ;xp5 += partial - - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp6, xgft3_hi ;xp6 += partial - - cmp vec_i, vec - jl .next_vect - - - mov tmp, [dest+2*PS] - mov ptr, [dest+3*PS] - mov vec_i, [dest+4*PS] - - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - XSTR [tmp+pos], xp3 - mov tmp, [dest+5*PS] - XSTR [ptr+pos], xp4 - XSTR [vec_i+pos], xp5 - XSTR [tmp+pos], xp6 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_6vect_dot_prod_avx, 02, 04, 0195 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx2.asm.s deleted file mode 100644 index 85bb78a3d..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_avx2.asm.s +++ /dev/null @@ -1,326 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_6vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - vmovdqa [rsp + 0*16], xmm6 - vmovdqa [rsp + 1*16], xmm7 - vmovdqa [rsp + 2*16], xmm8 - vmovdqa [rsp + 3*16], xmm9 - vmovdqa [rsp + 4*16], xmm10 - vmovdqa [rsp + 5*16], xmm11 - vmovdqa [rsp + 6*16], xmm12 - vmovdqa [rsp + 7*16], xmm13 - vmovdqa [rsp + 8*16], xmm14 - vmovdqa [rsp + 9*16], xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - save_reg rsi, 10*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm8, [rsp + 2*16] - vmovdqa xmm9, [rsp + 3*16] - vmovdqa xmm10, [rsp + 4*16] - vmovdqa xmm11, [rsp + 5*16] - vmovdqa xmm12, [rsp + 6*16] - vmovdqa xmm13, [rsp + 7*16] - vmovdqa xmm14, [rsp + 8*16] - vmovdqa xmm15, [rsp + 9*16] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - mov rsi, [rsp + 10*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest1 tmp3 -%define dest2 tmp4 -%define vskip1 tmp5 -%define vskip3 tmp6 -%define pos return - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f ymm15 -%define xmask0fx xmm15 -%define xgft1_lo ymm14 -%define xgft1_hi ymm13 -%define xgft2_lo ymm12 -%define xgft2_hi ymm11 -%define xgft3_lo ymm10 -%define xgft3_hi ymm9 -%define x0 ymm0 -%define xtmpa ymm1 -%define xp1 ymm2 -%define xp2 ymm3 -%define xp3 ymm4 -%define xp4 ymm5 -%define xp5 ymm6 -%define xp6 ymm7 - -align 16 -global gf_6vect_dot_prod_avx2:function -func(gf_6vect_dot_prod_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - mov vskip1, vec - imul vskip1, 32 - mov vskip3, vec - imul vskip3, 96 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - mov dest1, [dest] - mov dest2, [dest+PS] - - -.loop32: - mov tmp, mul_array - xor vec_i, vec_i - vpxor xp1, xp1 - vpxor xp2, xp2 - vpxor xp3, xp3 - vpxor xp4, xp4 - vpxor xp5, xp5 - vpxor xp6, xp6 - -.next_vect: - mov ptr, [src+vec_i] - XLDR x0, [ptr+pos] ;Get next source vector - add vec_i, PS - - vpand xgft3_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xgft3_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xgft3_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - lea ptr, [vskip1 + vskip1*4] ;ptr = vskip5 - - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp1, xgft1_hi ;xp1 += partial - - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp2, xgft2_hi ;xp2 += partial - - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp3, xgft3_hi ;xp3 += partial - - - vmovdqu xgft1_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - ; " Dx{00}, Dx{10}, ..., Dx{f0} - vmovdqu xgft2_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - ; " Ex{00}, Ex{10}, ..., Ex{f0} - vmovdqu xgft3_lo, [tmp+ptr] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} - ; " Fx{00}, Fx{10}, ..., Fx{f0} - add tmp, 32 - vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - - vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft1_hi, xgft1_lo ;GF add high and low partials - vpxor xp4, xgft1_hi ;xp4 += partial - - vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft2_hi, xgft2_lo ;GF add high and low partials - vpxor xp5, xgft2_hi ;xp5 += partial - - vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft3_hi, xgft3_lo ;GF add high and low partials - vpxor xp6, xgft3_hi ;xp6 += partial - - cmp vec_i, vec - jl .next_vect - - - mov tmp, [dest+2*PS] - mov ptr, [dest+3*PS] - mov vec_i, [dest+4*PS] - - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - XSTR [tmp+pos], xp3 - mov tmp, [dest+5*PS] - XSTR [ptr+pos], xp4 - XSTR [vec_i+pos], xp5 - XSTR [tmp+pos], xp6 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop32 ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_6vect_dot_prod_avx2, 04, 04, 019a diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_sse.asm.s deleted file mode 100644 index 34f7b8731..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_dot_prod_sse.asm.s +++ /dev/null @@ -1,315 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_6vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r12 ; must be saved and restored - %define tmp5 r14 ; must be saved and restored - %define tmp6 r15 ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - push r15 - %endmacro - %macro FUNC_RESTORE 0 - pop r15 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved, loaded and restored - %define arg5 r15 ; must be saved and restored - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 ; must be saved and restored - %define tmp4 r14 ; must be saved and restored - %define tmp5 rdi ; must be saved and restored - %define tmp6 rsi ; must be saved and restored - %define return rax - %define PS 8 - %define LOG_PS 3 - %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 - %define arg(x) [rsp + stack_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm8, 2*16 - save_xmm128 xmm9, 3*16 - save_xmm128 xmm10, 4*16 - save_xmm128 xmm11, 5*16 - save_xmm128 xmm12, 6*16 - save_xmm128 xmm13, 7*16 - save_xmm128 xmm14, 8*16 - save_xmm128 xmm15, 9*16 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - save_reg rsi, 10*16 + 5*8 - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - movdqa xmm6, [rsp + 0*16] - movdqa xmm7, [rsp + 1*16] - movdqa xmm8, [rsp + 2*16] - movdqa xmm9, [rsp + 3*16] - movdqa xmm10, [rsp + 4*16] - movdqa xmm11, [rsp + 5*16] - movdqa xmm12, [rsp + 6*16] - movdqa xmm13, [rsp + 7*16] - movdqa xmm14, [rsp + 8*16] - movdqa xmm15, [rsp + 9*16] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - mov rsi, [rsp + 10*16 + 5*8] - add rsp, stack_size - %endmacro -%endif - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 -%define ptr arg5 -%define vec_i tmp2 -%define dest1 tmp3 -%define dest2 tmp4 -%define vskip1 tmp5 -%define vskip3 tmp6 -%define pos return - - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft1_lo xmm2 -%define xgft1_hi xmm3 -%define xgft2_lo xmm4 -%define xgft2_hi xmm5 -%define xgft3_lo xmm6 -%define xgft3_hi xmm7 -%define x0 xmm0 -%define xtmpa xmm1 -%define xp1 xmm8 -%define xp2 xmm9 -%define xp3 xmm10 -%define xp4 xmm11 -%define xp5 xmm12 -%define xp6 xmm13 - -align 16 -global gf_6vect_dot_prod_sse:function -func(gf_6vect_dot_prod_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov vskip1, vec - imul vskip1, 32 - mov vskip3, vec - imul vskip3, 96 - sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS - mov dest1, [dest] - mov dest2, [dest+PS] - - -.loop16: - mov tmp, mul_array - xor vec_i, vec_i - pxor xp1, xp1 - pxor xp2, xp2 - pxor xp3, xp3 - pxor xp4, xp4 - pxor xp5, xp5 - pxor xp6, xp6 - -.next_vect: - mov ptr, [src+vec_i] - add vec_i, PS - XLDR x0, [ptr+pos] ;Get next source vector - - movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} - movdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - movdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} - movdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - lea ptr, [vskip1 + vskip1*4] ;ptr = vskip5 - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp1, xgft1_hi ;xp1 += partial - - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pxor xp2, xgft2_hi ;xp2 += partial - - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xgft3_lo ;GF add high and low partials - pxor xp3, xgft3_hi ;xp3 += partial - - - movdqu xgft1_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - movdqu xgft1_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} - movdqu xgft2_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - movdqu xgft2_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - movdqu xgft3_lo, [tmp+ptr] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} - movdqu xgft3_hi, [tmp+ptr+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} - add tmp, 32 - - - pshufb xgft1_hi, x0 ;Lookup mul table of high nibble - pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft1_hi, xgft1_lo ;GF add high and low partials - pxor xp4, xgft1_hi ;xp4 += partial - - pshufb xgft2_hi, x0 ;Lookup mul table of high nibble - pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft2_hi, xgft2_lo ;GF add high and low partials - pxor xp5, xgft2_hi ;xp5 += partial - - pshufb xgft3_hi, x0 ;Lookup mul table of high nibble - pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft3_hi, xgft3_lo ;GF add high and low partials - pxor xp6, xgft3_hi ;xp6 += partial - - cmp vec_i, vec - jl .next_vect - - - mov tmp, [dest+2*PS] - mov ptr, [dest+3*PS] - mov vec_i, [dest+4*PS] - - XSTR [dest1+pos], xp1 - XSTR [dest2+pos], xp2 - XSTR [tmp+pos], xp3 - mov tmp, [dest+5*PS] - XSTR [ptr+pos], xp4 - XSTR [vec_i+pos], xp5 - XSTR [tmp+pos], xp6 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_6vect_dot_prod_sse, 00, 05, 0066 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx.asm.s deleted file mode 100644 index 3c60d0a3e..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx.asm.s +++ /dev/null @@ -1,394 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_6vect_mad_avx(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r13 - %define tmp4 r14 - %define tmp5 rdi - %define return rax - %define return.w eax - %define stack_size 16*10 + 5*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp2 r10 - %define tmp3 r12 - %define tmp4 r13 - %define tmp5 r14 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - %endmacro - %macro FUNC_RESTORE 0 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -;;; gf_6vect_mad_avx(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp4 -%define dest3 tmp2 -%define dest4 mul_array -%define dest5 tmp5 -%define dest6 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft4_lo xmm14 -%define xgft4_hi xmm13 -%define xgft5_lo xmm12 -%define xgft5_hi xmm11 -%define xgft6_lo xmm10 -%define xgft6_hi xmm9 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xd1 xmm8 -%define xd2 xtmpl1 -%define xd3 xtmph1 - - -align 16 -global gf_6vect_mad_avx:function -func(gf_6vect_mad_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - mov tmp, vec - sal vec_i, 5 ;Multiply by 32 - lea tmp3, [mul_array + vec_i] - sal tmp, 6 ;Multiply by 64 - - sal vec, 5 ;Multiply by 32 - lea vec_i, [tmp + vec] ;vec_i = vec*96 - lea mul_array, [tmp + vec_i] ;mul_array = vec*160 - - vmovdqu xgft5_lo, [tmp3+2*tmp] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - vmovdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - vmovdqu xgft4_lo, [tmp3+vec_i] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - vmovdqu xgft4_hi, [tmp3+vec_i+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - vmovdqu xgft6_lo, [tmp3+mul_array] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} - vmovdqu xgft6_hi, [tmp3+mul_array+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} - - mov dest2, [dest1+PS] - mov dest3, [dest1+2*PS] - mov dest4, [dest1+3*PS] ; reuse mul_array - mov dest5, [dest1+4*PS] - mov dest6, [dest1+5*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - - vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - XLDR xd1, [dest1+pos] ;Get next dest vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - - ;dest1 - vpshufb xtmph1, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xtmph1 - - XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest vector - - ;dest2 - vpshufb xtmph2, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xtmph2 - - ;dest3 - vpshufb xtmph3, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmpl3 ;GF add high and low partials - vpxor xd3, xtmph3 - - XSTR [dest1+pos], xd1 ;Store result into dest1 - XSTR [dest2+pos], xd2 ;Store result into dest2 - XSTR [dest3+pos], xd3 ;Store result into dest3 - - ;dest4 - XLDR xd1, [dest4+pos] ;Get next dest vector - vpshufb xtmph1, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl1, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials - vpxor xd1, xd1, xtmph1 - - XLDR xd2, [dest5+pos] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest6+pos] ;reuse xtmph1. Get next dest vector - - ;dest5 - vpshufb xtmph2, xgft5_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl2, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials - vpxor xd2, xd2, xtmph2 - - ;dest6 - vpshufb xtmph3, xgft6_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl3, xgft6_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials - vpxor xd3, xd3, xtmph3 - - XSTR [dest4+pos], xd1 ;Store result into dest4 - XSTR [dest5+pos], xd2 ;Store result into dest5 - XSTR [dest6+pos], xd3 ;Store result into dest6 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - ;; Overlapped offset length-16 - mov tmp, len ;Backup len as len=rdi - - XLDR x0, [src+tmp] ;Get next source vector - XLDR xd1, [dest4+tmp] ;Get next dest vector - XLDR xd2, [dest5+tmp] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest6+tmp] ;reuse xtmph1. Get next dest vector - - sub len, pos - - vmovdqa xtmph3, [constip16] ;Load const of i + 16 - vpinsrb xtmpl3, len.w, 15 - vpshufb xtmpl3, xmask0f ;Broadcast len to all bytes - vpcmpgtb xtmpl3, xtmpl3, xtmph3 - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - ;dest4 - vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials - vpand xgft4_hi, xgft4_hi, xtmpl3 - vpxor xd1, xd1, xgft4_hi - - ;dest5 - vpshufb xgft5_hi, xgft5_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft5_hi, xgft5_hi, xgft5_lo ;GF add high and low partials - vpand xgft5_hi, xgft5_hi, xtmpl3 - vpxor xd2, xd2, xgft5_hi - - ;dest6 - vpshufb xgft6_hi, xgft6_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft6_lo, xgft6_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft6_hi, xgft6_hi, xgft6_lo ;GF add high and low partials - vpand xgft6_hi, xgft6_hi, xtmpl3 - vpxor xd3, xd3, xgft6_hi - - XSTR [dest4+tmp], xd1 ;Store result into dest4 - XSTR [dest5+tmp], xd2 ;Store result into dest5 - XSTR [dest6+tmp], xd3 ;Store result into dest6 - - vmovdqu xgft4_lo, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - vmovdqu xgft4_hi, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - vmovdqu xgft5_lo, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - vmovdqu xgft5_hi, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - vmovdqu xgft6_lo, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xgft6_hi, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest3 vector - - ;dest1 - vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials - vpand xgft4_hi, xgft4_hi, xtmpl3 - vpxor xd1, xd1, xgft4_hi - - ;dest2 - vpshufb xgft5_hi, xgft5_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft5_hi, xgft5_hi, xgft5_lo ;GF add high and low partials - vpand xgft5_hi, xgft5_hi, xtmpl3 - vpxor xd2, xd2, xgft5_hi - - ;dest3 - vpshufb xgft6_hi, xgft6_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft6_lo, xgft6_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft6_hi, xgft6_hi, xgft6_lo ;GF add high and low partials - vpand xgft6_hi, xgft6_hi, xtmpl3 - vpxor xd3, xd3, xgft6_hi - - XSTR [dest1+tmp], xd1 ;Store result into dest1 - XSTR [dest2+tmp], xd2 ;Store result into dest2 - XSTR [dest3+tmp], xd3 ;Store result into dest3 - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_6vect_mad_avx, 02, 01, 0210 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx2.asm.s deleted file mode 100644 index e1804578e..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_avx2.asm.s +++ /dev/null @@ -1,400 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_6vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r13 - %define return rax - %define return.w eax - %define stack_size 16*10 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r15, 10*16 + 2*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r15, [rsp + 10*16 + 3*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r12 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - %endmacro - %macro FUNC_RESTORE 0 - pop r12 - %endmacro -%endif - -;;; gf_6vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 tmp3 -%define dest3 tmp2 -%define dest4 mul_array -%define dest5 vec -%define dest6 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f ymm15 -%define xmask0fx xmm15 -%define xgft1_lo ymm14 -%define xgft2_lo ymm13 -%define xgft3_lo ymm12 -%define xgft4_lo ymm11 -%define xgft5_lo ymm10 -%define xgft6_lo ymm9 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xtmpl ymm2 -%define xtmplx xmm2 -%define xtmph ymm3 -%define xtmphx xmm3 -%define xd1 ymm4 -%define xd2 ymm5 -%define xd3 ymm6 -%define xd4 ymm7 -%define xd5 ymm8 -%define xd6 xd1 - -align 16 -global gf_6vect_mad_avx2:function -func(gf_6vect_mad_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec_i, 5 ;Multiply by 32 - sal vec, 5 ;Multiply by 32 - lea tmp, [mul_array + vec_i] - mov vec_i, vec - mov mul_array, vec - sal vec_i, 1 - sal mul_array, 1 - add vec_i, vec ;vec_i=vec*96 - add mul_array, vec_i ;vec_i=vec*160 - - vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} - ; " Ax{00}, Ax{10}, ..., Ax{f0} - vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} - ; " Bx{00}, Bx{10}, ..., Bx{f0} - vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - ; " Cx{00}, Cx{10}, ..., Cx{f0} - vmovdqu xgft4_lo, [tmp+vec_i] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} - ; " Fx{00}, Fx{10}, ..., Fx{f0} - vmovdqu xgft5_lo, [tmp+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - ; " Ex{00}, Ex{10}, ..., Ex{f0} - vmovdqu xgft6_lo, [tmp+mul_array] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} - ; " Dx{00}, Dx{10}, ..., Dx{f0} - - mov dest2, [dest1+PS] ; reuse tmp3 - mov dest3, [dest1+2*PS] ; reuse tmp2 - mov dest4, [dest1+3*PS] ; reuse mul_array - mov dest5, [dest1+4*PS] ; reuse vec - mov dest6, [dest1+5*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop32: - XLDR x0, [src+pos] ;Get next source vector - XLDR xd1, [dest1+pos] ;Get next dest vector - XLDR xd2, [dest2+pos] ;Get next dest vector - XLDR xd3, [dest3+pos] ;Get next dest vector - XLDR xd4, [dest4+pos] ;Get next dest vector - XLDR xd5, [dest5+pos] ;Get next dest vector - - vpand xtmpl, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xtmpl, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xtmpl, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - ;dest1 - vperm2i128 xtmph, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd1, xd1, xtmph ;xd1 += partial - - XSTR [dest1+pos], xd1 ;Store result into dest1 - - ;dest2 - vperm2i128 xtmph, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd2, xd2, xtmph ;xd2 += partial - - ;dest3 - vperm2i128 xtmph, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd3, xd3, xtmph ;xd3 += partial - - XLDR xd6, [dest6+pos] ;reuse xd1. Get next dest vector - - ;dest4 - vperm2i128 xtmph, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd4, xd4, xtmph ;xd4 += partial - - ;dest5 - vperm2i128 xtmph, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd5, xd5, xtmph ;xd5 += partial - - ;dest6 - vperm2i128 xtmph, xgft6_lo, xgft6_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft6_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd6, xd6, xtmph ;xd6 += partial - - XSTR [dest2+pos], xd2 ;Store result into dest2 - XSTR [dest3+pos], xd3 ;Store result into dest3 - XSTR [dest4+pos], xd4 ;Store result into dest4 - XSTR [dest5+pos], xd5 ;Store result into dest5 - XSTR [dest6+pos], xd6 ;Store result into dest6 - - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - -.lessthan32: - ;; Tail len - ;; Do one more overlap pass - mov tmp.b, 0x1f - vpinsrb xtmphx, xtmphx, tmp.w, 0 - vpbroadcastb xtmph, xtmphx ;Construct mask 0x1f1f1f... - - mov tmp, len ;Overlapped offset length-32 - - XLDR x0, [src+tmp] ;Get next source vector - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;Get next dest vector - XLDR xd3, [dest3+tmp] ;Get next dest vector - XLDR xd4, [dest4+tmp] ;Get next dest vector - XLDR xd5, [dest5+tmp] ;Get next dest vector - - sub len, pos - - vpinsrb xtmplx, xtmplx, len.w, 15 - vinserti128 xtmpl, xtmpl, xtmplx, 1 ;swapped to xtmplx | xtmplx - vpshufb xtmpl, xtmpl, xtmph ;Broadcast len to all bytes. xtmph=0x1f1f1f... - vpcmpgtb xtmpl, xtmpl, [constip32] - - vpand xtmph, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vperm2i128 xtmpa, xtmph, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi - vperm2i128 x0, xtmph, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo - - ;dest1 - vperm2i128 xtmph, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xgft1_lo ;GF add high and low partials - vpand xtmph, xtmph, xtmpl - vpxor xd1, xd1, xtmph ;xd1 += partial - - XSTR [dest1+tmp], xd1 ;Store result into dest1 - - ;dest2 - vperm2i128 xtmph, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xgft2_lo ;GF add high and low partials - vpand xtmph, xtmph, xtmpl - vpxor xd2, xd2, xtmph ;xd2 += partial - - ;dest3 - vperm2i128 xtmph, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xgft3_lo ;GF add high and low partials - vpand xtmph, xtmph, xtmpl - vpxor xd3, xd3, xtmph ;xd3 += partial - - XLDR xd6, [dest6+tmp] ;reuse xd1. Get next dest vector - - ;dest4 - vperm2i128 xtmph, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xgft4_lo ;GF add high and low partials - vpand xtmph, xtmph, xtmpl - vpxor xd4, xd4, xtmph ;xd4 += partial - - ;dest5 - vperm2i128 xtmph, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xgft5_lo ;GF add high and low partials - vpand xtmph, xtmph, xtmpl - vpxor xd5, xd5, xtmph ;xd5 += partial - - ;dest6 - vperm2i128 xtmph, xgft6_lo, xgft6_lo, 0x01 ; swapped to hi | lo - vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble - vpshufb xgft6_lo, xgft6_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xgft6_lo ;GF add high and low partials - vpand xtmph, xtmph, xtmpl - vpxor xd6, xd6, xtmph ;xd6 += partial - - XSTR [dest2+tmp], xd2 ;Store result into dest2 - XSTR [dest3+tmp], xd3 ;Store result into dest3 - XSTR [dest4+tmp], xd4 ;Store result into dest4 - XSTR [dest5+tmp], xd5 ;Store result into dest5 - XSTR [dest6+tmp], xd6 ;Store result into dest6 - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data -align 32 -constip32: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef - -;;; func core, ver, snum -slversion gf_6vect_mad_avx2, 04, 01, 0211 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_sse.asm.s deleted file mode 100644 index 574c8e525..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_6vect_mad_sse.asm.s +++ /dev/null @@ -1,406 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_6vect_mad_sse(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%define PS 8 - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define tmp.w r11d - %define tmp2 r10 - %define tmp3 r13 - %define tmp4 r14 - %define tmp5 rdi - %define return rax - %define return.w eax - %define stack_size 16*10 + 5*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - movdqa [rsp+16*3],xmm9 - movdqa [rsp+16*4],xmm10 - movdqa [rsp+16*5],xmm11 - movdqa [rsp+16*6],xmm12 - movdqa [rsp+16*7],xmm13 - movdqa [rsp+16*8],xmm14 - movdqa [rsp+16*9],xmm15 - save_reg r12, 10*16 + 0*8 - save_reg r13, 10*16 + 1*8 - save_reg r14, 10*16 + 2*8 - save_reg r15, 10*16 + 3*8 - save_reg rdi, 10*16 + 4*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - movdqa xmm9, [rsp+16*3] - movdqa xmm10, [rsp+16*4] - movdqa xmm11, [rsp+16*5] - movdqa xmm12, [rsp+16*6] - movdqa xmm13, [rsp+16*7] - movdqa xmm14, [rsp+16*8] - movdqa xmm15, [rsp+16*9] - mov r12, [rsp + 10*16 + 0*8] - mov r13, [rsp + 10*16 + 1*8] - mov r14, [rsp + 10*16 + 2*8] - mov r15, [rsp + 10*16 + 3*8] - mov rdi, [rsp + 10*16 + 4*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define tmp.w r11d - %define tmp2 r10 - %define tmp3 r12 - %define tmp4 r13 - %define tmp5 r14 - %define return rax - %define return.w eax - - %define func(x) x: - %macro FUNC_SAVE 0 - push r12 - push r13 - push r14 - %endmacro - %macro FUNC_RESTORE 0 - pop r14 - pop r13 - pop r12 - %endmacro -%endif - -;;; gf_6vect_mad_sse(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest1 arg5 -%define pos return -%define pos.w return.w - -%define dest2 mul_array -%define dest3 tmp2 -%define dest4 tmp4 -%define dest5 tmp5 -%define dest6 vec_i - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft4_lo xmm14 -%define xgft4_hi xmm13 -%define xgft5_lo xmm12 -%define xgft5_hi xmm11 -%define xgft6_lo xmm10 -%define xgft6_hi xmm9 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph1 xmm2 -%define xtmpl1 xmm3 -%define xtmph2 xmm4 -%define xtmpl2 xmm5 -%define xtmph3 xmm6 -%define xtmpl3 xmm7 -%define xd1 xmm8 -%define xd2 xtmpl1 -%define xd3 xtmph1 - - -align 16 -global gf_6vect_mad_sse:function -func(gf_6vect_mad_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - - mov tmp, vec - sal vec_i, 5 ;Multiply by 32 - lea tmp3, [mul_array + vec_i] - sal tmp, 6 ;Multiply by 64 - - sal vec, 5 ;Multiply by 32 - lea vec_i, [tmp + vec] ;vec_i = 96 - lea mul_array, [tmp + vec_i] ;mul_array = 160 - - movdqu xgft5_lo, [tmp3+2*tmp] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} - movdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} - movdqu xgft4_lo, [tmp3+vec_i] ;Load array Dx{00}, Dx{01}, Dx{02}, ... - movdqu xgft4_hi, [tmp3+vec_i+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} - movdqu xgft6_lo, [tmp3+mul_array] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} - movdqu xgft6_hi, [tmp3+mul_array+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} - - mov dest2, [dest1+PS] - mov dest3, [dest1+2*PS] - mov dest4, [dest1+3*PS] ; reuse mul_array - mov dest5, [dest1+4*PS] - mov dest6, [dest1+5*PS] ; reuse vec_i - mov dest1, [dest1] - -.loop16: - XLDR x0, [src+pos] ;Get next source vector - - movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - XLDR xd1, [dest1+pos] ;Get next dest vector - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ;dest1 - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pxor xd1, xtmph1 - - XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest3 vector - - ;dest2 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pxor xd2, xtmph2 - - ;dest3 - pshufb xtmph3, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph3, xtmpl3 ;GF add high and low partials - pxor xd3, xtmph3 - - XSTR [dest1+pos], xd1 ;Store result into dest1 - XSTR [dest2+pos], xd2 ;Store result into dest2 - XSTR [dest3+pos], xd3 ;Store result into dest3 - - movdqa xtmph1, xgft4_hi ;Reload const array registers - movdqa xtmpl1, xgft4_lo ;Reload const array registers - movdqa xtmph2, xgft5_hi ;Reload const array registers - movdqa xtmpl2, xgft5_lo ;Reload const array registers - movdqa xtmph3, xgft6_hi ;Reload const array registers - movdqa xtmpl3, xgft6_lo ;Reload const array registers - - ;dest4 - XLDR xd1, [dest4+pos] ;Get next dest vector - pshufb xtmph1, x0 ;Lookup mul table of high nibble - pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble - pxor xtmph1, xtmpl1 ;GF add high and low partials - pxor xd1, xtmph1 - - XLDR xd2, [dest5+pos] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest6+pos] ;reuse xtmph1. Get next dest vector - - ;dest5 - pshufb xtmph2, x0 ;Lookup mul table of high nibble - pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble - pxor xtmph2, xtmpl2 ;GF add high and low partials - pxor xd2, xtmph2 - - ;dest6 - pshufb xtmph3, x0 ;Lookup mul table of high nibble - pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble - pxor xtmph3, xtmpl3 ;GF add high and low partials - pxor xd3, xtmph3 - - XSTR [dest4+pos], xd1 ;Store result into dest4 - XSTR [dest5+pos], xd2 ;Store result into dest5 - XSTR [dest6+pos], xd3 ;Store result into dest6 - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - -.lessthan16: - ;; Tail len - ;; Do one more overlap pass - ;; Overlapped offset length-16 - mov tmp, len ;Backup len as len=rdi - - XLDR x0, [src+tmp] ;Get next source vector - XLDR xd1, [dest4+tmp] ;Get next dest vector - XLDR xd2, [dest5+tmp] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest6+tmp] ;reuse xtmph1. Get next dest vector - - sub len, pos - - movdqa xtmph3, [constip16] ;Load const of i + 16 - pinsrb xtmpl3, len.w, 15 - pshufb xtmpl3, xmask0f ;Broadcast len to all bytes - pcmpgtb xtmpl3, xtmph3 - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - ;dest4 - pshufb xgft4_hi, x0 ;Lookup mul table of high nibble - pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft4_hi, xgft4_lo ;GF add high and low partials - pand xgft4_hi, xtmpl3 - pxor xd1, xgft4_hi - - ;dest5 - pshufb xgft5_hi, x0 ;Lookup mul table of high nibble - pshufb xgft5_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft5_hi, xgft5_lo ;GF add high and low partials - pand xgft5_hi, xtmpl3 - pxor xd2, xgft5_hi - - ;dest6 - pshufb xgft6_hi, x0 ;Lookup mul table of high nibble - pshufb xgft6_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft6_hi, xgft6_lo ;GF add high and low partials - pand xgft6_hi, xtmpl3 - pxor xd3, xgft6_hi - - XSTR [dest4+tmp], xd1 ;Store result into dest4 - XSTR [dest5+tmp], xd2 ;Store result into dest5 - XSTR [dest6+tmp], xd3 ;Store result into dest6 - - movdqu xgft4_lo, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... - movdqu xgft4_hi, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} - movdqu xgft5_lo, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... - movdqu xgft5_hi, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} - movdqu xgft6_lo, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xgft6_hi, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - XLDR xd1, [dest1+tmp] ;Get next dest vector - XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector - XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest3 vector - - ;dest1 - pshufb xgft4_hi, x0 ;Lookup mul table of high nibble - pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft4_hi, xgft4_lo ;GF add high and low partials - pand xgft4_hi, xtmpl3 - pxor xd1, xgft4_hi - - ;dest2 - pshufb xgft5_hi, x0 ;Lookup mul table of high nibble - pshufb xgft5_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft5_hi, xgft5_lo ;GF add high and low partials - pand xgft5_hi, xtmpl3 - pxor xd2, xgft5_hi - - ;dest3 - pshufb xgft6_hi, x0 ;Lookup mul table of high nibble - pshufb xgft6_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft6_hi, xgft6_lo ;GF add high and low partials - pand xgft6_hi, xtmpl3 - pxor xd3, xgft6_hi - - XSTR [dest1+tmp], xd1 ;Store result into dest1 - XSTR [dest2+tmp], xd2 ;Store result into dest2 - XSTR [dest3+tmp], xd3 ;Store result into dest3 - -.return_pass: - FUNC_RESTORE - mov return, 0 - ret - -.return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 - -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f -constip16: - ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff - -;;; func core, ver, snum -slversion gf_6vect_mad_sse, 00, 01, 020f diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx.asm.s deleted file mode 100644 index 4f06b124b..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx.asm.s +++ /dev/null @@ -1,271 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_dot_prod_avx(len, vec, *g_tbls, **buffs, *dest); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r9 - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved and loaded - %define tmp r11 - %define tmp2 r10 - %define tmp3 rdi ; must be saved and loaded - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define frame_size 2*8 - %define arg(x) [rsp + frame_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - rex_push_reg r12 - push_reg rdi - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - pop rdi - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - - %define trans ecx ;trans is for the variables in stack - %define arg0 trans - %define arg0_m arg(0) - %define arg1 trans - %define arg1_m arg(1) - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 ebx - %define arg4 trans - %define arg4_m arg(4) - %define tmp edx - %define tmp2 edi - %define tmp3 esi - %define return eax - %macro SLDR 2 ;; stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - push esi - push edi - push ebx - mov arg3, arg(3) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - mov esp, ebp - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 - -%define vec_i tmp2 -%define ptr tmp3 -%define pos return - - %ifidn PS,4 ;32-bit code - %define vec_m arg1_m - %define len_m arg0_m - %define dest_m arg4_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ; 64-bit code - default rel - [bits 64] -%endif - -section .text - -%define xmask0f xmm5 -%define xgft_lo xmm4 -%define xgft_hi xmm3 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xp xmm2 - -align 16 -global gf_vect_dot_prod_avx:function -func(gf_vect_dot_prod_avx) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - -.loop16: - vpxor xp, xp - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - - mov ptr, [src+vec_i*PS] - vmovdqu xgft_lo, [tmp] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - vmovdqu xgft_hi, [tmp+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - XLDR x0, [ptr+pos] ;Get next source vector - - add tmp, 32 - add vec_i, 1 - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft_hi, xgft_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft_lo, xgft_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft_hi, xgft_hi, xgft_lo ;GF add high and low partials - vpxor xp, xp, xgft_hi ;xp += partial - - SLDR vec, vec_m - cmp vec_i, vec - jl .next_vect - - SLDR dest, dest_m - XSTR [dest+pos], xp - - add pos, 16 ;Loop on 16 bytes at a time - SLDR len, len_m - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 - -mask0f: -ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_vect_dot_prod_avx, 02, 05, 0061 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx2.asm.s deleted file mode 100644 index 47bb38cc6..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_avx2.asm.s +++ /dev/null @@ -1,280 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, *dest); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 r9 - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved and loaded - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define tmp2 r10 - %define tmp3 rdi ; must be saved and loaded - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define frame_size 2*8 - %define arg(x) [rsp + frame_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - rex_push_reg r12 - push_reg rdi - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - pop rdi - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - - %define trans ecx ;trans is for the variables in stack - %define arg0 trans - %define arg0_m arg(0) - %define arg1 trans - %define arg1_m arg(1) - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 ebx - %define arg4 trans - %define arg4_m arg(4) - %define tmp edx - %define tmp.w edx - %define tmp.b dl - %define tmp2 edi - %define tmp3 esi - %define return eax - %macro SLDR 2 ;stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - push esi - push edi - push ebx - mov arg3, arg(3) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - mov esp, ebp - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 - -%define vec_i tmp2 -%define ptr tmp3 -%define pos return - -%ifidn PS,4 ;32-bit code - %define vec_m arg1_m - %define len_m arg0_m - %define dest_m arg4_m -%endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - -%ifidn PS,8 ;64-bit code - default rel - [bits 64] -%endif - -section .text - -%define xmask0f ymm3 -%define xmask0fx xmm3 -%define xgft_lo ymm4 -%define xgft_hi ymm5 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xp ymm2 - -align 16 -global gf_vect_dot_prod_avx2:function -func(gf_vect_dot_prod_avx2) - FUNC_SAVE - SLDR len, len_m - sub len, 32 - SSTR len_m, len - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - -.loop32: - vpxor xp, xp - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - - mov ptr, [src+vec_i*PS] - - vmovdqu xgft_lo, [tmp] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - vperm2i128 xgft_hi, xgft_lo, xgft_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft_lo, xgft_lo, xgft_lo, 0x00 ; swapped to lo | lo - - XLDR x0, [ptr+pos] ;Get next source vector - - add tmp, 32 - add vec_i, 1 - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xgft_hi, xgft_hi, x0 ;Lookup mul table of high nibble - vpshufb xgft_lo, xgft_lo, xtmpa ;Lookup mul table of low nibble - vpxor xgft_hi, xgft_hi, xgft_lo ;GF add high and low partials - vpxor xp, xp, xgft_hi ;xp += partial - - SLDR vec, vec_m - cmp vec_i, vec - jl .next_vect - - SLDR dest, dest_m - XSTR [dest+pos], xp - - add pos, 32 ;Loop on 32 bytes at a time - SLDR len, len_m - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-32 - jmp .loop32 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_vect_dot_prod_avx2, 04, 05, 0190 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_sse.asm.s deleted file mode 100644 index f7699c111..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_dot_prod_sse.asm.s +++ /dev/null @@ -1,271 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_dot_prod_sse(len, vec, *g_tbls, **buffs, *dest); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - - %define tmp r11 - %define tmp2 r10 - %define tmp3 r9 - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - - %define arg4 r12 ; must be saved and loaded - %define tmp r11 - %define tmp2 r10 - %define tmp3 rdi ; must be saved and loaded - %define return rax - %macro SLDR 2 - %endmacro - %define SSTR SLDR - %define PS 8 - %define frame_size 2*8 - %define arg(x) [rsp + frame_size + PS + PS*x] - - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - rex_push_reg r12 - push_reg rdi - end_prolog - mov arg4, arg(4) - %endmacro - - %macro FUNC_RESTORE 0 - pop rdi - pop r12 - %endmacro -%endif - -%ifidn __OUTPUT_FORMAT__, elf32 - -;;;================== High Address; -;;; arg4 -;;; arg3 -;;; arg2 -;;; arg1 -;;; arg0 -;;; return -;;;<================= esp of caller -;;; ebp -;;;<================= ebp = esp -;;; esi -;;; edi -;;; ebx -;;;<================= esp of callee -;;; -;;;================== Low Address; - - %define PS 4 - %define LOG_PS 2 - %define func(x) x: - %define arg(x) [ebp + PS*2 + PS*x] - - %define trans ecx ;trans is for the variables in stack - %define arg0 trans - %define arg0_m arg(0) - %define arg1 trans - %define arg1_m arg(1) - %define arg2 arg2_m - %define arg2_m arg(2) - %define arg3 ebx - %define arg4 trans - %define arg4_m arg(4) - %define tmp edx - %define tmp2 edi - %define tmp3 esi - %define return eax - %macro SLDR 2 ;; stack load/restore - mov %1, %2 - %endmacro - %define SSTR SLDR - - %macro FUNC_SAVE 0 - push ebp - mov ebp, esp - push esi - push edi - push ebx - mov arg3, arg(3) - %endmacro - - %macro FUNC_RESTORE 0 - pop ebx - pop edi - pop esi - mov esp, ebp - pop ebp - %endmacro - -%endif ; output formats - -%define len arg0 -%define vec arg1 -%define mul_array arg2 -%define src arg3 -%define dest arg4 - -%define vec_i tmp2 -%define ptr tmp3 -%define pos return - - %ifidn PS,4 ;32-bit code - %define vec_m arg1_m - %define len_m arg0_m - %define dest_m arg4_m - %endif - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -%ifidn PS,8 ;64-bit code - default rel - [bits 64] -%endif - -section .text - -%define xmask0f xmm5 -%define xgft_lo xmm4 -%define xgft_hi xmm3 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xp xmm2 - -align 16 -global gf_vect_dot_prod_sse:function -func(gf_vect_dot_prod_sse) - FUNC_SAVE - SLDR len, len_m - sub len, 16 - SSTR len_m, len - jl .return_fail - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - -.loop16: - pxor xp, xp - mov tmp, mul_array - xor vec_i, vec_i - -.next_vect: - - mov ptr, [src+vec_i*PS] - movdqu xgft_lo, [tmp] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} - movdqu xgft_hi, [tmp+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} - XLDR x0, [ptr+pos] ;Get next source vector - - add tmp, 32 - add vec_i, 1 - - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - - pshufb xgft_hi, x0 ;Lookup mul table of high nibble - pshufb xgft_lo, xtmpa ;Lookup mul table of low nibble - pxor xgft_hi, xgft_lo ;GF add high and low partials - pxor xp, xgft_hi ;xp += partial - - SLDR vec, vec_m - cmp vec_i, vec - jl .next_vect - - SLDR dest, dest_m - XSTR [dest+pos], xp - - add pos, 16 ;Loop on 16 bytes at a time - SLDR len, len_m - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - jmp .loop16 ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 - -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_vect_dot_prod_sse, 00, 05, 0060 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx.asm.s deleted file mode 100644 index f0fd91ac1..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx.asm.s +++ /dev/null @@ -1,196 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_mad_avx(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define return rax - %define return.w eax - %define PS 8 - %define stack_size 16*3 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - vmovdqa [rsp+16*0],xmm6 - vmovdqa [rsp+16*1],xmm7 - vmovdqa [rsp+16*2],xmm8 - save_reg r12, 3*16 + 0*8 - save_reg r15, 3*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp+16*0] - vmovdqa xmm7, [rsp+16*1] - vmovdqa xmm8, [rsp+16*2] - mov r12, [rsp + 3*16 + 0*8] - mov r15, [rsp + 3*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_vect_mad_avx(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest arg5 -%define pos return -%define pos.w return.w - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f xmm8 -%define xgft_lo xmm7 -%define xgft_hi xmm6 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph xmm2 -%define xtmpl xmm3 -%define xd xmm4 -%define xtmpd xmm5 - -align 16 -global gf_vect_mad_avx:function -func(gf_vect_mad_avx) - FUNC_SAVE - sub len, 16 - jl .return_fail - - xor pos, pos - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - - sal vec_i, 5 ;Multiply by 32 - vmovdqu xgft_lo, [vec_i+mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xgft_hi, [vec_i+mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - - XLDR xtmpd, [dest+len] ;backup the last 16 bytes in dest - -.loop16: - XLDR xd, [dest+pos] ;Get next dest vector -.loop16_overlap: - XLDR x0, [src+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xtmph, xgft_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd, xd, xtmph ;xd += partial - - XSTR [dest+pos], xd - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - vmovdqa xd, xtmpd ;Restore xd - jmp .loop16_overlap ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 - -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_vect_mad_avx, 02, 01, 0201 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx2.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx2.asm.s deleted file mode 100644 index 5fa5da4d1..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_avx2.asm.s +++ /dev/null @@ -1,203 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 ; must be saved and loaded - %define arg5 r15 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define return rax - %define return.w eax - %define PS 8 - %define stack_size 16*3 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - - %macro FUNC_SAVE 0 - sub rsp, stack_size - vmovdqa [rsp+16*0],xmm6 - vmovdqa [rsp+16*1],xmm7 - vmovdqa [rsp+16*2],xmm8 - save_reg r12, 3*16 + 0*8 - save_reg r15, 3*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp+16*0] - vmovdqa xmm7, [rsp+16*1] - vmovdqa xmm8, [rsp+16*2] - mov r12, [rsp + 3*16 + 0*8] - mov r15, [rsp + 3*16 + 1*8] - add rsp, stack_size - %endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - - %define tmp r11 - %define tmp.w r11d - %define tmp.b r11b - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - - -;;; gf_vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest arg5 -%define pos return -%define pos.w return.w - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR vmovdqu - %define XSTR vmovdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa - %else - %define XLDR vmovntdqa - %define XSTR vmovntdq - %endif -%endif - - -default rel - -[bits 64] -section .text - -%define xmask0f ymm8 -%define xmask0fx xmm8 -%define xgft_lo ymm7 -%define xgft_hi ymm6 - -%define x0 ymm0 -%define xtmpa ymm1 -%define xtmph ymm2 -%define xtmpl ymm3 -%define xd ymm4 -%define xtmpd ymm5 - -align 16 -global gf_vect_mad_avx2:function -func(gf_vect_mad_avx2) - FUNC_SAVE - sub len, 32 - jl .return_fail - xor pos, pos - mov tmp.b, 0x0f - vpinsrb xmask0fx, xmask0fx, tmp.w, 0 - vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... - - sal vec_i, 5 ;Multiply by 32 - vmovdqu xgft_lo, [vec_i+mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - vperm2i128 xgft_hi, xgft_lo, xgft_lo, 0x11 ; swapped to hi | hi - vperm2i128 xgft_lo, xgft_lo, xgft_lo, 0x00 ; swapped to lo | lo - - XLDR xtmpd, [dest+len] ;backup the last 32 bytes in dest - -.loop32: - XLDR xd, [dest+pos] ;Get next dest vector -.loop32_overlap: - XLDR x0, [src+pos] ;Get next source vector - - vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - - vpshufb xtmph, xgft_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmpl, xgft_lo, xtmpa ;Lookup mul table of low nibble - vpxor xtmph, xtmph, xtmpl ;GF add high and low partials - vpxor xd, xd, xtmph ;xd += partial - - XSTR [dest+pos], xd - add pos, 32 ;Loop on 32 bytes at a time - cmp pos, len - jle .loop32 - - lea tmp, [len + 32] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-32 - vmovdqa xd, xtmpd ;Restore xd - jmp .loop32_overlap ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -;;; func core, ver, snum -slversion gf_vect_mad_avx2, 04, 01, 0202 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_sse.asm.s deleted file mode 100644 index b3ebc9776..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mad_sse.asm.s +++ /dev/null @@ -1,197 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_mad_sse(len, vec, vec_i, mul_array, src, dest); -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg0.w ecx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define arg4 r12 - %define arg5 r15 - %define tmp r11 - %define return rax - %define return.w eax - %define PS 8 - %define stack_size 16*3 + 3*8 - %define arg(x) [rsp + stack_size + PS + PS*x] - %define func(x) proc_frame x - -%macro FUNC_SAVE 0 - sub rsp, stack_size - movdqa [rsp+16*0],xmm6 - movdqa [rsp+16*1],xmm7 - movdqa [rsp+16*2],xmm8 - save_reg r12, 3*16 + 0*8 - save_reg r15, 3*16 + 1*8 - end_prolog - mov arg4, arg(4) - mov arg5, arg(5) -%endmacro - -%macro FUNC_RESTORE 0 - movdqa xmm6, [rsp+16*0] - movdqa xmm7, [rsp+16*1] - movdqa xmm8, [rsp+16*2] - mov r12, [rsp + 3*16 + 0*8] - mov r15, [rsp + 3*16 + 1*8] - add rsp, stack_size -%endmacro - -%elifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg0.w edi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define return rax - %define return.w eax - - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE -%endif - -;;; gf_vect_mad_sse(len, vec, vec_i, mul_array, src, dest) -%define len arg0 -%define len.w arg0.w -%define vec arg1 -%define vec_i arg2 -%define mul_array arg3 -%define src arg4 -%define dest arg5 -%define pos return -%define pos.w return.w - -%ifndef EC_ALIGNED_ADDR -;;; Use Un-aligned load/store - %define XLDR movdqu - %define XSTR movdqu -%else -;;; Use Non-temporal load/stor - %ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa - %else - %define XLDR movntdqa - %define XSTR movntdq - %endif -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm8 -%define xgft_lo xmm7 -%define xgft_hi xmm6 - -%define x0 xmm0 -%define xtmpa xmm1 -%define xtmph xmm2 -%define xtmpl xmm3 -%define xd xmm4 -%define xtmpd xmm5 - - -align 16 -global gf_vect_mad_sse:function -func(gf_vect_mad_sse) - FUNC_SAVE - sub len, 16 - jl .return_fail - - xor pos, pos - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - sal vec_i, 5 ;Multiply by 32 - movdqu xgft_lo, [vec_i+mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xgft_hi, [vec_i+mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - - XLDR xtmpd, [dest+len] ;backup the last 16 bytes in dest - -.loop16: - XLDR xd, [dest+pos] ;Get next dest vector -.loop16_overlap: - XLDR x0, [src+pos] ;Get next source vector - movdqa xtmph, xgft_hi ;Reload const array registers - movdqa xtmpl, xgft_lo - movdqa xtmpa, x0 ;Keep unshifted copy of src - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 - pshufb xtmph, x0 ;Lookup mul table of high nibble - pshufb xtmpl, xtmpa ;Lookup mul table of low nibble - pxor xtmph, xtmpl ;GF add high and low partials - - pxor xd, xtmph - XSTR [dest+pos], xd ;Store result - - add pos, 16 ;Loop on 16 bytes at a time - cmp pos, len - jle .loop16 - - lea tmp, [len + 16] - cmp pos, tmp - je .return_pass - - ;; Tail len - mov pos, len ;Overlapped offset length-16 - movdqa xd, xtmpd ;Restore xd - jmp .loop16_overlap ;Do one more overlap pass - -.return_pass: - mov return, 0 - FUNC_RESTORE - ret - -.return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 - -mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_vect_mad_sse, 00, 01, 0200 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_avx.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_avx.asm.s deleted file mode 100644 index c9438b11a..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_avx.asm.s +++ /dev/null @@ -1,164 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_mul_avx(len, mul_array, src, dest) -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define return rax - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE - -%elifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define return rax - %define stack_size 5*16 + 8 ; must be an odd multiple of 8 - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm13, 2*16 - save_xmm128 xmm14, 3*16 - save_xmm128 xmm15, 4*16 - end_prolog - %endmacro - - %macro FUNC_RESTORE 0 - vmovdqa xmm6, [rsp + 0*16] - vmovdqa xmm7, [rsp + 1*16] - vmovdqa xmm13, [rsp + 2*16] - vmovdqa xmm14, [rsp + 3*16] - vmovdqa xmm15, [rsp + 4*16] - add rsp, stack_size - %endmacro - -%endif - - -%define len arg0 -%define mul_array arg1 -%define src arg2 -%define dest arg3 -%define pos return - - -;;; Use Non-temporal load/stor -%ifdef NO_NT_LDST - %define XLDR vmovdqa - %define XSTR vmovdqa -%else - %define XLDR vmovntdqa - %define XSTR vmovntdq -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft_lo xmm14 -%define xgft_hi xmm13 - -%define x0 xmm0 -%define xtmp1a xmm1 -%define xtmp1b xmm2 -%define xtmp1c xmm3 -%define x1 xmm4 -%define xtmp2a xmm5 -%define xtmp2b xmm6 -%define xtmp2c xmm7 - -align 16 -global gf_vect_mul_avx:function -func(gf_vect_mul_avx) - FUNC_SAVE - mov pos, 0 - vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - vmovdqu xgft_lo, [mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - vmovdqu xgft_hi, [mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - -loop32: - XLDR x0, [src+pos] ;Get next source vector - XLDR x1, [src+pos+16] ;Get next source vector + 16B ahead - add pos, 32 ;Loop on 16 bytes at a time - cmp pos, len - vpand xtmp1a, x0, xmask0f ;Mask low src nibble in bits 4-0 - vpand xtmp2a, x1, xmask0f - vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 - vpsraw x1, x1, 4 - vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 - vpand x1, x1, xmask0f - vpshufb xtmp1b, xgft_hi, x0 ;Lookup mul table of high nibble - vpshufb xtmp1c, xgft_lo, xtmp1a ;Lookup mul table of low nibble - vpshufb xtmp2b, xgft_hi, x1 ;Lookup mul table of high nibble - vpshufb xtmp2c, xgft_lo, xtmp2a ;Lookup mul table of low nibble - vpxor xtmp1b, xtmp1b, xtmp1c ;GF add high and low partials - vpxor xtmp2b, xtmp2b, xtmp2c - XSTR [dest+pos-32], xtmp1b ;Store result - XSTR [dest+pos-16], xtmp2b ;Store +16B result - jl loop32 - - -return_pass: - FUNC_RESTORE - sub pos, len - ret - -return_fail: - FUNC_RESTORE - mov return, 1 - ret - -endproc_frame - -section .data - -align 16 - -mask0f: -ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_vect_mul_avx, 01, 03, 0036 diff --git a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_sse.asm.s b/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_sse.asm.s deleted file mode 100644 index 2a14cc9d8..000000000 --- a/ceph/src/erasure-code/isa/isa-l/erasure_code/gf_vect_mul_sse.asm.s +++ /dev/null @@ -1,170 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; -;;; gf_vect_mul_sse(len, mul_array, src, dest) -;;; - -%include "reg_sizes.asm" - -%ifidn __OUTPUT_FORMAT__, elf64 - %define arg0 rdi - %define arg1 rsi - %define arg2 rdx - %define arg3 rcx - %define arg4 r8 - %define arg5 r9 - %define tmp r11 - %define return rax - %define func(x) x: - %define FUNC_SAVE - %define FUNC_RESTORE - -%elifidn __OUTPUT_FORMAT__, win64 - %define arg0 rcx - %define arg1 rdx - %define arg2 r8 - %define arg3 r9 - %define return rax - %define stack_size 5*16 + 8 ; must be an odd multiple of 8 - %define func(x) proc_frame x - %macro FUNC_SAVE 0 - alloc_stack stack_size - save_xmm128 xmm6, 0*16 - save_xmm128 xmm7, 1*16 - save_xmm128 xmm13, 2*16 - save_xmm128 xmm14, 3*16 - save_xmm128 xmm15, 4*16 - end_prolog - %endmacro - - %macro FUNC_RESTORE 0 - movdqa xmm6, [rsp + 0*16] - movdqa xmm7, [rsp + 1*16] - movdqa xmm13, [rsp + 2*16] - movdqa xmm14, [rsp + 3*16] - movdqa xmm15, [rsp + 4*16] - add rsp, stack_size - %endmacro - -%endif - - -%define len arg0 -%define mul_array arg1 -%define src arg2 -%define dest arg3 -%define pos return - - -;;; Use Non-temporal load/stor -%ifdef NO_NT_LDST - %define XLDR movdqa - %define XSTR movdqa -%else - %define XLDR movntdqa - %define XSTR movntdq -%endif - -default rel - -[bits 64] -section .text - -%define xmask0f xmm15 -%define xgft_lo xmm14 -%define xgft_hi xmm13 - -%define x0 xmm0 -%define xtmp1a xmm1 -%define xtmp1b xmm2 -%define xtmp1c xmm3 -%define x1 xmm4 -%define xtmp2a xmm5 -%define xtmp2b xmm6 -%define xtmp2c xmm7 - - -align 16 -global gf_vect_mul_sse:function -func(gf_vect_mul_sse) - FUNC_SAVE - mov pos, 0 - movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte - movdqu xgft_lo, [mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... - movdqu xgft_hi, [mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} - -loop32: - XLDR x0, [src+pos] ;Get next source vector - XLDR x1, [src+pos+16] ;Get next source vector + 16B ahead - movdqa xtmp1b, xgft_hi ;Reload const array registers - movdqa xtmp1c, xgft_lo - movdqa xtmp2b, xgft_hi - movdqa xtmp2c, xgft_lo - movdqa xtmp1a, x0 ;Keep unshifted copy of src - movdqa xtmp2a, x1 - psraw x0, 4 ;Shift to put high nibble into bits 4-0 - psraw x1, 4 - pand xtmp1a, xmask0f ;Mask low src nibble in bits 4-0 - pand xtmp2a, xmask0f - pand x0, xmask0f ;Mask high src nibble in bits 4-0 - pand x1, xmask0f - pshufb xtmp1b, x0 ;Lookup mul table of high nibble - pshufb xtmp1c, xtmp1a ;Lookup mul table of low nibble - pshufb xtmp2b, x1 - pshufb xtmp2c, xtmp2a - pxor xtmp1b, xtmp1c ;GF add high and low partials - pxor xtmp2b, xtmp2c - XSTR [dest+pos], xtmp1b ;Store result - XSTR [dest+pos+16], xtmp2b ;Store +16B result - add pos, 32 ;Loop on 32 bytes at at time - cmp pos, len - jl loop32 - - -return_pass: - sub pos, len - FUNC_RESTORE - ret - -return_fail: - mov return, 1 - FUNC_RESTORE - ret - -endproc_frame - -section .data - -align 16 -mask0f: -ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f - -;;; func core, ver, snum -slversion gf_vect_mul_sse, 00, 03, 0034 diff --git a/ceph/src/erasure-code/isa/isa-l/include/erasure_code.h b/ceph/src/erasure-code/isa/isa-l/include/erasure_code.h deleted file mode 100644 index 53e480f01..000000000 --- a/ceph/src/erasure-code/isa/isa-l/include/erasure_code.h +++ /dev/null @@ -1,933 +0,0 @@ -/********************************************************************** - Copyright(c) 2011-2015 Intel Corporation All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************/ - - -#ifndef _ERASURE_CODE_H_ -#define _ERASURE_CODE_H_ - -/** - * @file erasure_code.h - * @brief Interface to functions supporting erasure code encode and decode. - * - * This file defines the interface to optimized functions used in erasure - * codes. Encode and decode of erasures in GF(2^8) are made by calculating the - * dot product of the symbols (bytes in GF(2^8)) across a set of buffers and a - * set of coefficients. Values for the coefficients are determined by the type - * of erasure code. Using a general dot product means that any sequence of - * coefficients may be used including erasure codes based on random - * coefficients. - * Multiple versions of dot product are supplied to calculate 1-6 output - * vectors in one pass. - * Base GF multiply and divide functions can be sped up by defining - * GF_LARGE_TABLES at the expense of memory size. - * - */ - -#include "gf_vect_mul.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize tables for fast Erasure Code encode and decode. - * - * Generates the expanded tables needed for fast encode or decode for erasure - * codes on blocks of data. 32bytes is generated for each input coefficient. - * - * @param k The number of vector sources or rows in the generator matrix - * for coding. - * @param rows The number of output vectors to concurrently encode/decode. - * @param a Pointer to sets of arrays of input coefficients used to encode - * or decode data. - * @param gftbls Pointer to start of space for concatenated output tables - * generated from input coefficients. Must be of size 32*k*rows. - * @returns none - */ - -void ec_init_tables(int k, int rows, unsigned char* a, unsigned char* gftbls); - -/** - * @brief Generate or decode erasure codes on blocks of data, runs appropriate version. - * - * Given a list of source data blocks, generate one or multiple blocks of - * encoded data as specified by a matrix of GF(2^8) coefficients. When given a - * suitable set of coefficients, this function will perform the fast generation - * or decoding of Reed-Solomon type erasure codes. - * - * This function determines what instruction sets are enabled and - * selects the appropriate version at runtime. - * - * @param len Length of each block of data (vector) of source or dest data. - * @param k The number of vector sources or rows in the generator matrix - * for coding. - * @param rows The number of output vectors to concurrently encode/decode. - * @param gftbls Pointer to array of input tables generated from coding - * coefficients in ec_init_tables(). Must be of size 32*k*rows - * @param data Array of pointers to source input buffers. - * @param coding Array of pointers to coded output buffers. - * @returns none - */ - -void ec_encode_data(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, - unsigned char **coding); - -/** - * @brief Generate or decode erasure codes on blocks of data. - * - * Arch specific version of ec_encode_data() with same parameters. - * @requires SSE4.1 - */ -void ec_encode_data_sse(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, - unsigned char **coding); - -/** - * @brief Generate or decode erasure codes on blocks of data. - * - * Arch specific version of ec_encode_data() with same parameters. - * @requires AVX - */ -void ec_encode_data_avx(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, - unsigned char **coding); - -/** - * @brief Generate or decode erasure codes on blocks of data. - * - * Arch specific version of ec_encode_data() with same parameters. - * @requires AVX2 - */ -void ec_encode_data_avx2(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, - unsigned char **coding); - -/** - * @brief Generate or decode erasure codes on blocks of data, runs baseline version. - * - * Baseline version of ec_encode_data() with same parameters. - */ -void ec_encode_data_base(int len, int srcs, int dests, unsigned char *v, unsigned char **src, - unsigned char **dest); - -/** - * @brief Generate update for encode or decode of erasure codes from single source, runs appropriate version. - * - * Given one source data block, update one or multiple blocks of encoded data as - * specified by a matrix of GF(2^8) coefficients. When given a suitable set of - * coefficients, this function will perform the fast generation or decoding of - * Reed-Solomon type erasure codes from one input source at a time. - * - * This function determines what instruction sets are enabled and selects the - * appropriate version at runtime. - * - * @param len Length of each block of data (vector) of source or dest data. - * @param k The number of vector sources or rows in the generator matrix - * for coding. - * @param rows The number of output vectors to concurrently encode/decode. - * @param vec_i The vector index corresponding to the single input source. - * @param g_tbls Pointer to array of input tables generated from coding - * coefficients in ec_init_tables(). Must be of size 32*k*rows - * @param data Pointer to single input source used to update output parity. - * @param coding Array of pointers to coded output buffers. - * @returns none - */ -void ec_encode_data_update(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding); - -/** - * @brief Generate update for encode or decode of erasure codes from single source. - * - * Arch specific version of ec_encode_data_update() with same parameters. - * @requires SSE4.1 - */ - -void ec_encode_data_update_sse(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding); - -/** - * @brief Generate update for encode or decode of erasure codes from single source. - * - * Arch specific version of ec_encode_data_update() with same parameters. - * @requires AVX - */ - -void ec_encode_data_update_avx(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding); - -/** - * @brief Generate update for encode or decode of erasure codes from single source. - * - * Arch specific version of ec_encode_data_update() with same parameters. - * @requires AVX2 - */ - -void ec_encode_data_update_avx2(int len, int k, int rows, int vec_i, unsigned char *g_tbls, - unsigned char *data, unsigned char **coding); - -/** - * @brief Generate update for encode or decode of erasure codes from single source. - * - * Baseline version of ec_encode_data_update(). - */ - -void ec_encode_data_update_base(int len, int k, int rows, int vec_i, unsigned char *v, - unsigned char *data, unsigned char **dest); - - -/** - * @brief GF(2^8) vector dot product. - * - * Does a GF(2^8) dot product across each byte of the input array and a constant - * set of coefficients to produce each byte of the output. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 32*vlen byte constant array based on the input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based - * on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Pointer to destination data array. - * @returns none - */ - -void gf_vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char *dest); - -/** - * @brief GF(2^8) vector dot product. - * - * Does a GF(2^8) dot product across each byte of the input array and a constant - * set of coefficients to produce each byte of the output. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 32*vlen byte constant array based on the input coefficients. - * @requires AVX - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based - * on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Pointer to destination data array. - * @returns none - */ - -void gf_vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char *dest); - -/** - * @brief GF(2^8) vector dot product. - * - * Does a GF(2^8) dot product across each byte of the input array and a constant - * set of coefficients to produce each byte of the output. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 32*vlen byte constant array based on the input coefficients. - * @requires AVX2 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based - * on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Pointer to destination data array. - * @returns none - */ - -void gf_vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char *dest); - -/** - * @brief GF(2^8) vector dot product with two outputs. - * - * Vector dot product optimized to calculate two ouputs at a time. Does two - * GF(2^8) dot products across each byte of the input array and two constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 2*32*vlen byte constant array based on the two sets of input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_2vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with two outputs. - * - * Vector dot product optimized to calculate two ouputs at a time. Does two - * GF(2^8) dot products across each byte of the input array and two constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 2*32*vlen byte constant array based on the two sets of input coefficients. - * @requires AVX - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_2vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with two outputs. - * - * Vector dot product optimized to calculate two ouputs at a time. Does two - * GF(2^8) dot products across each byte of the input array and two constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 2*32*vlen byte constant array based on the two sets of input coefficients. - * @requires AVX2 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_2vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with three outputs. - * - * Vector dot product optimized to calculate three ouputs at a time. Does three - * GF(2^8) dot products across each byte of the input array and three constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 3*32*vlen byte constant array based on the three sets of input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_3vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with three outputs. - * - * Vector dot product optimized to calculate three ouputs at a time. Does three - * GF(2^8) dot products across each byte of the input array and three constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 3*32*vlen byte constant array based on the three sets of input coefficients. - * @requires AVX - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_3vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with three outputs. - * - * Vector dot product optimized to calculate three ouputs at a time. Does three - * GF(2^8) dot products across each byte of the input array and three constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 3*32*vlen byte constant array based on the three sets of input coefficients. - * @requires AVX2 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_3vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with four outputs. - * - * Vector dot product optimized to calculate four ouputs at a time. Does four - * GF(2^8) dot products across each byte of the input array and four constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 4*32*vlen byte constant array based on the four sets of input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_4vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with four outputs. - * - * Vector dot product optimized to calculate four ouputs at a time. Does four - * GF(2^8) dot products across each byte of the input array and four constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 4*32*vlen byte constant array based on the four sets of input coefficients. - * @requires AVX - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_4vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with four outputs. - * - * Vector dot product optimized to calculate four ouputs at a time. Does four - * GF(2^8) dot products across each byte of the input array and four constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 4*32*vlen byte constant array based on the four sets of input coefficients. - * @requires AVX2 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_4vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with five outputs. - * - * Vector dot product optimized to calculate five ouputs at a time. Does five - * GF(2^8) dot products across each byte of the input array and five constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 5*32*vlen byte constant array based on the five sets of input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_5vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with five outputs. - * - * Vector dot product optimized to calculate five ouputs at a time. Does five - * GF(2^8) dot products across each byte of the input array and five constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 5*32*vlen byte constant array based on the five sets of input coefficients. - * @requires AVX - * - * @param len Length of each vector in bytes. Must >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_5vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with five outputs. - * - * Vector dot product optimized to calculate five ouputs at a time. Does five - * GF(2^8) dot products across each byte of the input array and five constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 5*32*vlen byte constant array based on the five sets of input coefficients. - * @requires AVX2 - * - * @param len Length of each vector in bytes. Must >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_5vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with six outputs. - * - * Vector dot product optimized to calculate six ouputs at a time. Does six - * GF(2^8) dot products across each byte of the input array and six constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 6*32*vlen byte constant array based on the six sets of input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_6vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with six outputs. - * - * Vector dot product optimized to calculate six ouputs at a time. Does six - * GF(2^8) dot products across each byte of the input array and six constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 6*32*vlen byte constant array based on the six sets of input coefficients. - * @requires AVX - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_6vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product with six outputs. - * - * Vector dot product optimized to calculate six ouputs at a time. Does six - * GF(2^8) dot products across each byte of the input array and six constant - * sets of coefficients to produce each byte of the outputs. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 6*32*vlen byte constant array based on the six sets of input coefficients. - * @requires AVX2 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants - * based on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Array of pointers to destination data buffers. - * @returns none - */ - -void gf_6vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char **dest); - -/** - * @brief GF(2^8) vector dot product, runs baseline version. - * - * Does a GF(2^8) dot product across each byte of the input array and a constant - * set of coefficients to produce each byte of the output. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 32*vlen byte constant array based on the input coefficients. - * - * @param len Length of each vector in bytes. Must be >= 16. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based - * on the array of input coefficients. Only elements 32*CONST*j + 1 - * of this array are used, where j = (0, 1, 2...) and CONST is the - * number of elements in the array of input coefficients. The - * elements used correspond to the original input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Pointer to destination data array. - * @returns none - */ - -void gf_vect_dot_prod_base(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char *dest); - -/** - * @brief GF(2^8) vector dot product, runs appropriate version. - * - * Does a GF(2^8) dot product across each byte of the input array and a constant - * set of coefficients to produce each byte of the output. Can be used for - * erasure coding encode and decode. Function requires pre-calculation of a - * 32*vlen byte constant array based on the input coefficients. - * - * This function determines what instruction sets are enabled and - * selects the appropriate version at runtime. - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vlen Number of vector sources. - * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based - * on the array of input coefficients. - * @param src Array of pointers to source inputs. - * @param dest Pointer to destination data array. - * @returns none - */ - -void gf_vect_dot_prod(int len, int vlen, unsigned char *gftbls, - unsigned char **src, unsigned char *dest); - - -/** - * @brief GF(2^8) vector multiply accumulate, runs appropriate version. - * - * Does a GF(2^8) multiply across each byte of input source with expanded - * constant and add to destination array. Can be used for erasure coding encode - * and decode update when only one source is available at a time. Function - * requires pre-calculation of a 32*vec byte constant array based on the input - * coefficients. - * - * This function determines what instruction sets are enabled and selects the - * appropriate version at runtime. - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vec The number of vector sources or rows in the generator matrix - * for coding. - * @param vec_i The vector index corresponding to the single input source. - * @param gftbls Pointer to array of input tables generated from coding - * coefficients in ec_init_tables(). Must be of size 32*vec. - * @param src Array of pointers to source inputs. - * @param dest Pointer to destination data array. - * @returns none - */ - -void gf_vect_mad(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char *dest); - -/** - * @brief GF(2^8) vector multiply accumulate, arch specific version. - * - * Arch specific version of gf_vect_mad() with same parameters. - * @requires SSE4.1 - */ - -void gf_vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char *dest); -/** - * @brief GF(2^8) vector multiply accumulate, arch specific version. - * - * Arch specific version of gf_vect_mad() with same parameters. - * @requires AVX - */ - -void gf_vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char *dest); - -/** - * @brief GF(2^8) vector multiply accumulate, arch specific version. - * - * Arch specific version of gf_vect_mad() with same parameters. - * @requires AVX2 - */ - -void gf_vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char *dest); - -/** - * @brief GF(2^8) vector multiply accumulate, baseline version. - * - * Baseline version of gf_vect_mad() with same parameters. - */ - -void gf_vect_mad_base(int len, int vec, int vec_i, unsigned char *v, unsigned char *src, - unsigned char *dest); - -/** - * @brief GF(2^8) vector multiply with 2 accumulate. SSE version. - * - * Does a GF(2^8) multiply across each byte of input source with expanded - * constants and add to destination arrays. Can be used for erasure coding - * encode and decode update when only one source is available at a - * time. Function requires pre-calculation of a 32*vec byte constant array based - * on the input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vec The number of vector sources or rows in the generator matrix - * for coding. - * @param vec_i The vector index corresponding to the single input source. - * @param gftbls Pointer to array of input tables generated from coding - * coefficients in ec_init_tables(). Must be of size 32*vec. - * @param src Pointer to source input array. - * @param dest Array of pointers to destination input/outputs. - * @returns none - */ - -void gf_2vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 2 accumulate. AVX version of gf_2vect_mad_sse(). - * @requires AVX - */ -void gf_2vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); -/** - * @brief GF(2^8) vector multiply with 2 accumulate. AVX2 version of gf_2vect_mad_sse(). - * @requires AVX2 - */ -void gf_2vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 3 accumulate. SSE version. - * - * Does a GF(2^8) multiply across each byte of input source with expanded - * constants and add to destination arrays. Can be used for erasure coding - * encode and decode update when only one source is available at a - * time. Function requires pre-calculation of a 32*vec byte constant array based - * on the input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vec The number of vector sources or rows in the generator matrix - * for coding. - * @param vec_i The vector index corresponding to the single input source. - * @param gftbls Pointer to array of input tables generated from coding - * coefficients in ec_init_tables(). Must be of size 32*vec. - * @param src Pointer to source input array. - * @param dest Array of pointers to destination input/outputs. - * @returns none - */ - -void gf_3vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 3 accumulate. AVX version of gf_3vect_mad_sse(). - * @requires AVX - */ -void gf_3vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 3 accumulate. AVX2 version of gf_3vect_mad_sse(). - * @requires AVX2 - */ -void gf_3vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 4 accumulate. SSE version. - * - * Does a GF(2^8) multiply across each byte of input source with expanded - * constants and add to destination arrays. Can be used for erasure coding - * encode and decode update when only one source is available at a - * time. Function requires pre-calculation of a 32*vec byte constant array based - * on the input coefficients. - * @requires SSE4.1 - * - * @param len Length of each vector in bytes. Must be >= 32. - * @param vec The number of vector sources or rows in the generator matrix - * for coding. - * @param vec_i The vector index corresponding to the single input source. - * @param gftbls Pointer to array of input tables generated from coding - * coefficients in ec_init_tables(). Must be of size 32*vec. - * @param src Pointer to source input array. - * @param dest Array of pointers to destination input/outputs. - * @returns none - */ - -void gf_4vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 4 accumulate. AVX version of gf_4vect_mad_sse(). - * @requires AVX - */ -void gf_4vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); -/** - * @brief GF(2^8) vector multiply with 4 accumulate. AVX2 version of gf_4vect_mad_sse(). - * @requires AVX2 - */ -void gf_4vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 5 accumulate. SSE version. - * @requires SSE4.1 - */ -void gf_5vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 5 accumulate. AVX version. - * @requires AVX - */ -void gf_5vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); -/** - * @brief GF(2^8) vector multiply with 5 accumulate. AVX2 version. - * @requires AVX2 - */ -void gf_5vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 6 accumulate. SSE version. - * @requires SSE4.1 - */ -void gf_6vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); -/** - * @brief GF(2^8) vector multiply with 6 accumulate. AVX version. - * @requires AVX - */ -void gf_6vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - -/** - * @brief GF(2^8) vector multiply with 6 accumulate. AVX2 version. - * @requires AVX2 - */ -void gf_6vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, - unsigned char **dest); - - -/********************************************************************** - * The remaining are lib support functions used in GF(2^8) operations. - */ - -/** - * @brief Single element GF(2^8) multiply. - * - * @param a Multiplicand a - * @param b Multiplicand b - * @returns Product of a and b in GF(2^8) - */ - -unsigned char gf_mul(unsigned char a, unsigned char b); - -/** - * @brief Single element GF(2^8) inverse. - * - * @param a Input element - * @returns Field element b such that a x b = {1} - */ - -unsigned char gf_inv(unsigned char a); - -/** - * @brief Generate a matrix of coefficients to be used for encoding. - * - * Vandermonde matrix example of encoding coefficients where high portion of - * matrix is identity matrix I and lower portion is constructed as 2^{i*(j-k+1)} - * i:{0,k-1} j:{k,m-1}. Commonly used method for choosing coefficients in - * erasure encoding but does not guarantee invertable for every sub matrix. For - * large k it is possible to find cases where the decode matrix chosen from - * sources and parity not in erasure are not invertable. Users may want to - * adjust for k > 5. - * - * @param a [mxk] array to hold coefficients - * @param m number of rows in matrix corresponding to srcs + parity. - * @param k number of columns in matrix corresponding to srcs. - * @returns none - */ - -void gf_gen_rs_matrix(unsigned char *a, int m, int k); - -/** - * @brief Generate a Cauchy matrix of coefficients to be used for encoding. - * - * Cauchy matrix example of encoding coefficients where high portion of matrix - * is identity matrix I and lower portion is constructed as 1/(i + j) | i != j, - * i:{0,k-1} j:{k,m-1}. Any sub-matrix of a Cauchy matrix should be invertable. - * - * @param a [mxk] array to hold coefficients - * @param m number of rows in matrix corresponding to srcs + parity. - * @param k number of columns in matrix corresponding to srcs. - * @returns none - */ - -void gf_gen_cauchy1_matrix(unsigned char *a, int m, int k); - -/** - * @brief Invert a matrix in GF(2^8) - * - * @param in input matrix - * @param out output matrix such that [in] x [out] = [I] - identity matrix - * @param n size of matrix [nxn] - * @returns 0 successful, other fail on singular input matrix - */ - -int gf_invert_matrix(unsigned char *in, unsigned char *out, const int n); - - -/*************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif //_ERASURE_CODE_H_ diff --git a/ceph/src/erasure-code/isa/isa-l/include/gf_vect_mul.h b/ceph/src/erasure-code/isa/isa-l/include/gf_vect_mul.h deleted file mode 100644 index bf4fd01a6..000000000 --- a/ceph/src/erasure-code/isa/isa-l/include/gf_vect_mul.h +++ /dev/null @@ -1,148 +0,0 @@ -/********************************************************************** - Copyright(c) 2011-2015 Intel Corporation All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************/ - - -#ifndef _GF_VECT_MUL_H -#define _GF_VECT_MUL_H - -/** - * @file gf_vect_mul.h - * @brief Interface to functions for vector (block) multiplication in GF(2^8). - * - * This file defines the interface to routines used in fast RAID rebuild and - * erasure codes. - */ - -#ifdef __cplusplus -extern "C" { -#endif - - /** - * @brief GF(2^8) vector multiply by constant. - * - * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C - * is a single field element in GF(2^8). Can be used for RAID6 rebuild - * and partial write functions. Function requires pre-calculation of a - * 32-element constant array based on constant C. gftbl(C) = {C{00}, - * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. Len - * and src must be aligned to 32B. - * @requires SSE4.1 - * - * @param len Length of vector in bytes. Must be aligned to 32B. - * @param gftbl Pointer to 32-byte array of pre-calculated constants based on C. - * @param src Pointer to src data array. Must be aligned to 32B. - * @param dest Pointer to destination data array. Must be aligned to 32B. - * @returns 0 pass, other fail - */ - -int gf_vect_mul_sse(int len, unsigned char *gftbl, void *src, void *dest); - - - /** - * @brief GF(2^8) vector multiply by constant. - * - * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C - * is a single field element in GF(2^8). Can be used for RAID6 rebuild - * and partial write functions. Function requires pre-calculation of a - * 32-element constant array based on constant C. gftbl(C) = {C{00}, - * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. Len - * and src must be aligned to 32B. - * @requires AVX - * - * @param len Length of vector in bytes. Must be aligned to 32B. - * @param gftbl Pointer to 32-byte array of pre-calculated constants based on C. - * @param src Pointer to src data array. Must be aligned to 32B. - * @param dest Pointer to destination data array. Must be aligned to 32B. - * @returns 0 pass, other fail - */ - -int gf_vect_mul_avx(int len, unsigned char *gftbl, void *src, void *dest); - - -/** - * @brief GF(2^8) vector multiply by constant, runs appropriate version. - * - * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C - * is a single field element in GF(2^8). Can be used for RAID6 rebuild - * and partial write functions. Function requires pre-calculation of a - * 32-element constant array based on constant C. gftbl(C) = {C{00}, - * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. - * Len and src must be aligned to 32B. - * - * This function determines what instruction sets are enabled - * and selects the appropriate version at runtime. - * - * @param len Length of vector in bytes. Must be aligned to 32B. - * @param gftbl Pointer to 32-byte array of pre-calculated constants based on C. - * @param src Pointer to src data array. Must be aligned to 32B. - * @param dest Pointer to destination data array. Must be aligned to 32B. - * @returns 0 pass, other fail - */ - -int gf_vect_mul(int len, unsigned char *gftbl, void *src, void *dest); - - -/** - * @brief Initialize 32-byte constant array for GF(2^8) vector multiply - * - * Calculates array {C{00}, C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, - * C{20}, ... , C{f0} } as required by other fast vector multiply - * functions. - * @param c Constant input. - * @param gftbl Table output. - */ - -void gf_vect_mul_init(unsigned char c, unsigned char* gftbl); - - -/** - * @brief GF(2^8) vector multiply by constant, runs baseline version. - * - * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C - * is a single field element in GF(2^8). Can be used for RAID6 rebuild - * and partial write functions. Function requires pre-calculation of a - * 32-element constant array based on constant C. gftbl(C) = {C{00}, - * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. Len - * and src must be aligned to 32B. - * - * @param len Length of vector in bytes. Must be aligned to 32B. - * @param a Pointer to 32-byte array of pre-calculated constants based on C. - * only use 2nd element is used. - * @param src Pointer to src data array. Must be aligned to 32B. - * @param dest Pointer to destination data array. Must be aligned to 32B. - */ - -void gf_vect_mul_base(int len, unsigned char *a, unsigned char *src, - unsigned char *dest); - -#ifdef __cplusplus -} -#endif - -#endif //_GF_VECT_MUL_H diff --git a/ceph/src/erasure-code/isa/isa-l/include/reg_sizes.asm b/ceph/src/erasure-code/isa/isa-l/include/reg_sizes.asm deleted file mode 100644 index 650c1fe3e..000000000 --- a/ceph/src/erasure-code/isa/isa-l/include/reg_sizes.asm +++ /dev/null @@ -1,123 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Copyright(c) 2011-2015 Intel Corporation All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions -; are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in -; the documentation and/or other materials provided with the -; distribution. -; * Neither the name of Intel Corporation nor the names of its -; contributors may be used to endorse or promote products derived -; from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -%ifndef _REG_SIZES_ASM_ -%define _REG_SIZES_ASM_ - -%define EFLAGS_HAS_CPUID (1<<21) -%define FLAG_CPUID1_ECX_CLMUL (1<<1) -%define FLAG_CPUID1_EDX_SSE2 (1<<26) -%define FLAG_CPUID1_ECX_SSE3 (1) -%define FLAG_CPUID1_ECX_SSE4_1 (1<<19) -%define FLAG_CPUID1_ECX_SSE4_2 (1<<20) -%define FLAG_CPUID1_ECX_POPCNT (1<<23) -%define FLAG_CPUID1_ECX_AESNI (1<<25) -%define FLAG_CPUID1_ECX_OSXSAVE (1<<27) -%define FLAG_CPUID1_ECX_AVX (1<<28) -%define FLAG_CPUID1_EBX_AVX2 (1<<5) -%define FLAG_XGETBV_EAX_XMM_YMM 0x6 - -%define FLAG_CPUID1_EAX_AVOTON 0x000406d0 - -; define d and w variants for registers - -%define raxd eax -%define raxw ax -%define raxb al - -%define rbxd ebx -%define rbxw bx -%define rbxb bl - -%define rcxd ecx -%define rcxw cx -%define rcxb cl - -%define rdxd edx -%define rdxw dx -%define rdxb dl - -%define rsid esi -%define rsiw si -%define rsib sil - -%define rdid edi -%define rdiw di -%define rdib dil - -%define rbpd ebp -%define rbpw bp -%define rbpb bpl - -%define ymm0x xmm0 -%define ymm1x xmm1 -%define ymm2x xmm2 -%define ymm3x xmm3 -%define ymm4x xmm4 -%define ymm5x xmm5 -%define ymm6x xmm6 -%define ymm7x xmm7 -%define ymm8x xmm8 -%define ymm9x xmm9 -%define ymm10x xmm10 -%define ymm11x xmm11 -%define ymm12x xmm12 -%define ymm13x xmm13 -%define ymm14x xmm14 -%define ymm15x xmm15 - -%define DWORD(reg) reg %+ d -%define WORD(reg) reg %+ w -%define BYTE(reg) reg %+ b - -%define XWORD(reg) reg %+ x - -%ifidn __OUTPUT_FORMAT__,elf32 -section .note.GNU-stack noalloc noexec nowrite progbits -section .text -%endif -%ifidn __OUTPUT_FORMAT__,elf64 -section .note.GNU-stack noalloc noexec nowrite progbits -section .text -%endif -%ifidn __OUTPUT_FORMAT__, macho64 -%define elf64 macho64 -%endif - -%macro slversion 4 - section .text - global %1_slver_%2%3%4 - global %1_slver - %1_slver: - %1_slver_%2%3%4: - dw 0x%4 - db 0x%3, 0x%2 -%endmacro - -%endif ; ifndef _REG_SIZES_ASM_ diff --git a/ceph/src/erasure-code/isa/isa-l/include/types.h b/ceph/src/erasure-code/isa/isa-l/include/types.h deleted file mode 100644 index f5775efaa..000000000 --- a/ceph/src/erasure-code/isa/isa-l/include/types.h +++ /dev/null @@ -1,88 +0,0 @@ -/********************************************************************** - Copyright(c) 2011-2015 Intel Corporation All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************/ - - -/** - * @file types.h - * @brief Defines standard width types. - * - */ - -#ifndef __TYPES_H -#define __TYPES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __WIN32__ -#ifdef __MINGW32__ -# include <_mingw.h> -#endif -typedef unsigned __int64 UINT64; -typedef __int64 INT64; -typedef unsigned __int32 UINT32; -typedef unsigned __int16 UINT16; -typedef unsigned char UINT8; -#else -typedef unsigned long int UINT64; -typedef long int INT64; -typedef unsigned int UINT32; -typedef unsigned short int UINT16; -typedef unsigned char UINT8; -#endif - - -#if defined __unix__ || defined __APPLE__ -# define DECLARE_ALIGNED(decl, alignval) decl __attribute__((aligned(alignval))) -# define __forceinline static inline -# define aligned_free(x) free(x) -#else -# ifdef __MINGW32__ -# define DECLARE_ALIGNED(decl, alignval) decl __attribute__((aligned(alignval))) -# define posix_memalign(p, algn, len) (NULL == (*((char**)(p)) = (void*) _aligned_malloc(len, algn))) -# define aligned_free(x) _aligned_free(x) -# else -# define DECLARE_ALIGNED(decl, alignval) __declspec(align(alignval)) decl -# define posix_memalign(p, algn, len) (NULL == (*((char**)(p)) = (void*) _aligned_malloc(len, algn))) -# define aligned_free(x) _aligned_free(x) -# endif -#endif - -#ifdef DEBUG -# define DEBUG_PRINT(x) printf x -#else -# define DEBUG_PRINT(x) do {} while (0) -#endif - -#ifdef __cplusplus -} -#endif - -#endif //__TYPES_H diff --git a/ceph/src/erasure-code/isa/xor_op.cc b/ceph/src/erasure-code/isa/xor_op.cc index 358ce4a5e..be0071d8f 100644 --- a/ceph/src/erasure-code/isa/xor_op.cc +++ b/ceph/src/erasure-code/isa/xor_op.cc @@ -13,6 +13,7 @@ // ----------------------------------------------------------------------------- #include "xor_op.h" #include +#include #include "arch/intel.h" // ----------------------------------------------------------------------------- diff --git a/ceph/src/erasure-code/isa/xor_op.h b/ceph/src/erasure-code/isa/xor_op.h index 9dc706142..978b9a953 100644 --- a/ceph/src/erasure-code/isa/xor_op.h +++ b/ceph/src/erasure-code/isa/xor_op.h @@ -18,7 +18,6 @@ // ----------------------------------------------------------------------------- #include #include -#include // ----------------------------------------------------------------------------- // ------------------------------------------------------------------------- diff --git a/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.cc b/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.cc index 1d411b9c2..ca1b09649 100644 --- a/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.cc +++ b/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.cc @@ -19,6 +19,9 @@ #include "ErasureCodeJerasure.h" #include "crush/CrushWrapper.h" #include "osd/osd_types.h" + +using namespace std; + extern "C" { #include "jerasure.h" #include "reed_sol.h" @@ -43,8 +46,9 @@ int ErasureCodeJerasure::create_ruleset(const string &name, CrushWrapper &crush, ostream *ss) const { - int ruleid = crush.add_simple_ruleset(name, ruleset_root, ruleset_failure_domain, - "indep", pg_pool_t::TYPE_ERASURE, ss); + int ruleid = crush.add_simple_rule( + name, ruleset_root, ruleset_failure_domain, + "indep", pg_pool_t::TYPE_ERASURE, ss); if (ruleid < 0) return ruleid; else { diff --git a/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.h b/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.h index da341175e..5696c6e90 100644 --- a/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.h +++ b/ceph/src/erasure-code/jerasure/ErasureCodeJerasure.h @@ -32,8 +32,8 @@ public: int w; std::string DEFAULT_W; const char *technique; - string ruleset_root; - string ruleset_failure_domain; + std::string ruleset_root; + std::string ruleset_failure_domain; bool per_chunk_alignment; explicit ErasureCodeJerasure(const char *_technique) : @@ -51,9 +51,9 @@ public: ~ErasureCodeJerasure() override {} - int create_ruleset(const string &name, + int create_ruleset(const std::string &name, CrushWrapper &crush, - ostream *ss) const override; + std::ostream *ss) const override; unsigned int get_chunk_count() const override { return k + m; @@ -65,14 +65,14 @@ public: unsigned int get_chunk_size(unsigned int object_size) const override; - int encode_chunks(const set &want_to_encode, - map *encoded) override; + int encode_chunks(const std::set &want_to_encode, + std::map *encoded) override; - int decode_chunks(const set &want_to_read, - const map &chunks, - map *decoded) override; + int decode_chunks(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) override; - int init(ErasureCodeProfile &profile, ostream *ss) override; + int init(ErasureCodeProfile &profile, std::ostream *ss) override; virtual void jerasure_encode(char **data, char **coding, @@ -85,7 +85,7 @@ public: virtual void prepare() = 0; static bool is_prime(int value); protected: - virtual int parse(ErasureCodeProfile &profile, ostream *ss); + virtual int parse(ErasureCodeProfile &profile, std::ostream *ss); }; class ErasureCodeJerasureReedSolomonVandermonde : public ErasureCodeJerasure { @@ -115,7 +115,7 @@ public: unsigned get_alignment() const override; void prepare() override; private: - int parse(ErasureCodeProfile &profile, ostream *ss) override; + int parse(ErasureCodeProfile &profile, std::ostream *ss) override; }; class ErasureCodeJerasureReedSolomonRAID6 : public ErasureCodeJerasure { @@ -144,7 +144,7 @@ public: unsigned get_alignment() const override; void prepare() override; private: - int parse(ErasureCodeProfile &profile, ostream *ss) override; + int parse(ErasureCodeProfile &profile, std::ostream *ss) override; }; #define DEFAULT_PACKETSIZE "2048" @@ -182,7 +182,7 @@ public: unsigned get_alignment() const override; void prepare_schedule(int *matrix); private: - int parse(ErasureCodeProfile &profile, ostream *ss) override; + int parse(ErasureCodeProfile &profile, std::ostream *ss) override; }; class ErasureCodeJerasureCauchyOrig : public ErasureCodeJerasureCauchy { @@ -229,15 +229,15 @@ public: char **coding, int blocksize) override; unsigned get_alignment() const override; - virtual bool check_k(ostream *ss) const; - virtual bool check_w(ostream *ss) const; - virtual bool check_packetsize_set(ostream *ss) const; - virtual bool check_packetsize(ostream *ss) const; + virtual bool check_k(std::ostream *ss) const; + virtual bool check_w(std::ostream *ss) const; + virtual bool check_packetsize_set(std::ostream *ss) const; + virtual bool check_packetsize(std::ostream *ss) const; virtual int revert_to_default(ErasureCodeProfile &profile, - ostream *ss); + std::ostream *ss); void prepare() override; private: - int parse(ErasureCodeProfile &profile, ostream *ss) override; + int parse(ErasureCodeProfile &profile, std::ostream *ss) override; }; class ErasureCodeJerasureBlaumRoth : public ErasureCodeJerasureLiberation { @@ -247,7 +247,7 @@ public: { } - bool check_w(ostream *ss) const override; + bool check_w(std::ostream *ss) const override; void prepare() override; }; @@ -263,7 +263,7 @@ public: void prepare() override; private: - int parse(ErasureCodeProfile &profile, ostream *ss) override; + int parse(ErasureCodeProfile &profile, std::ostream *ss) override; }; #endif diff --git a/ceph/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc b/ceph/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc index ac6923e33..38f403826 100644 --- a/ceph/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc +++ b/ceph/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc @@ -34,7 +34,7 @@ static ostream& _prefix(std::ostream* _dout) int ErasureCodePluginJerasure::factory(const std::string& directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss) { + std::ostream *ss) { ErasureCodeJerasure *interface; std::string t; if (profile.find("technique") != profile.end()) diff --git a/ceph/src/erasure-code/lrc/ErasureCodeLrc.cc b/ceph/src/erasure-code/lrc/ErasureCodeLrc.cc index a60fa6e08..52dc2d879 100644 --- a/ceph/src/erasure-code/lrc/ErasureCodeLrc.cc +++ b/ceph/src/erasure-code/lrc/ErasureCodeLrc.cc @@ -36,6 +36,8 @@ #undef dout_prefix #define dout_prefix _prefix(_dout) +using namespace std; + static ostream& _prefix(std::ostream* _dout) { return *_dout << "ErasureCodeLrc: "; diff --git a/ceph/src/erasure-code/lrc/ErasureCodeLrc.h b/ceph/src/erasure-code/lrc/ErasureCodeLrc.h index c12a8ad35..fac4d54a5 100644 --- a/ceph/src/erasure-code/lrc/ErasureCodeLrc.h +++ b/ceph/src/erasure-code/lrc/ErasureCodeLrc.h @@ -46,33 +46,33 @@ class ErasureCodeLrc : public ErasureCode { public: - static const string DEFAULT_KML; + static const std::string DEFAULT_KML; struct Layer { - explicit Layer(string _chunks_map) : chunks_map(_chunks_map) { } + explicit Layer(std::string _chunks_map) : chunks_map(_chunks_map) { } ErasureCodeInterfaceRef erasure_code; - vector data; - vector coding; - vector chunks; - set chunks_as_set; - string chunks_map; + std::vector data; + std::vector coding; + std::vector chunks; + std::set chunks_as_set; + std::string chunks_map; ErasureCodeProfile profile; }; - vector layers; - string directory; + std::vector layers; + std::string directory; unsigned int chunk_count; unsigned int data_chunk_count; - string ruleset_root; + std::string ruleset_root; struct Step { - Step(string _op, string _type, int _n) : + Step(std::string _op, std::string _type, int _n) : op(_op), type(_type), n(_n) {} - string op; - string type; + std::string op; + std::string type; int n; }; - vector ruleset_steps; + std::vector ruleset_steps; explicit ErasureCodeLrc(const std::string &dir) : directory(dir), @@ -83,16 +83,16 @@ public: ~ErasureCodeLrc() override {} - set get_erasures(const set &need, - const set &available) const; + std::set get_erasures(const std::set &need, + const std::set &available) const; - int minimum_to_decode(const set &want_to_read, - const set &available, - set *minimum) override; + int minimum_to_decode(const std::set &want_to_read, + const std::set &available, + std::set *minimum) override; - int create_ruleset(const string &name, + int create_ruleset(const std::string &name, CrushWrapper &crush, - ostream *ss) const override; + std::ostream *ss) const override; unsigned int get_chunk_count() const override { return chunk_count; @@ -104,34 +104,34 @@ public: unsigned int get_chunk_size(unsigned int object_size) const override; - int encode_chunks(const set &want_to_encode, - map *encoded) override; + int encode_chunks(const std::set &want_to_encode, + std::map *encoded) override; - int decode_chunks(const set &want_to_read, - const map &chunks, - map *decoded) override; + int decode_chunks(const std::set &want_to_read, + const std::map &chunks, + std::map *decoded) override; - int init(ErasureCodeProfile &profile, ostream *ss) override; + int init(ErasureCodeProfile &profile, std::ostream *ss) override; - virtual int parse(ErasureCodeProfile &profile, ostream *ss); + virtual int parse(ErasureCodeProfile &profile, std::ostream *ss); - int parse_kml(ErasureCodeProfile &profile, ostream *ss); + int parse_kml(ErasureCodeProfile &profile, std::ostream *ss); - int parse_ruleset(ErasureCodeProfile &profile, ostream *ss); + int parse_ruleset(ErasureCodeProfile &profile, std::ostream *ss); - int parse_ruleset_step(string description_string, + int parse_ruleset_step(std::string description_string, json_spirit::mArray description, - ostream *ss); + std::ostream *ss); int layers_description(const ErasureCodeProfile &profile, json_spirit::mArray *description, - ostream *ss) const; - int layers_parse(string description_string, + std::ostream *ss) const; + int layers_parse(std::string description_string, json_spirit::mArray description, - ostream *ss); - int layers_init(ostream *ss); - int layers_sanity_checks(string description_string, - ostream *ss) const; + std::ostream *ss); + int layers_init(std::ostream *ss); + int layers_sanity_checks(std::string description_string, + std::ostream *ss) const; }; #endif diff --git a/ceph/src/erasure-code/lrc/ErasureCodePluginLrc.cc b/ceph/src/erasure-code/lrc/ErasureCodePluginLrc.cc index c2be14b01..b5699cd74 100644 --- a/ceph/src/erasure-code/lrc/ErasureCodePluginLrc.cc +++ b/ceph/src/erasure-code/lrc/ErasureCodePluginLrc.cc @@ -20,9 +20,6 @@ #include "ErasureCodePluginLrc.h" #include "ErasureCodeLrc.h" -// re-include our assert -#include "include/assert.h" - #define dout_subsys ceph_subsys_osd #undef dout_prefix #define dout_prefix _prefix(_dout) @@ -30,7 +27,7 @@ int ErasureCodePluginLrc::factory(const std::string &directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss) { + std::ostream *ss) { ErasureCodeLrc *interface; interface = new ErasureCodeLrc(directory); int r = interface->init(profile, ss); diff --git a/ceph/src/erasure-code/shec/ErasureCodePluginShec.cc b/ceph/src/erasure-code/shec/ErasureCodePluginShec.cc index ded31692f..eb967f8d4 100644 --- a/ceph/src/erasure-code/shec/ErasureCodePluginShec.cc +++ b/ceph/src/erasure-code/shec/ErasureCodePluginShec.cc @@ -39,7 +39,7 @@ static ostream& _prefix(std::ostream* _dout) int ErasureCodePluginShec::factory(const std::string &directory, ErasureCodeProfile &profile, ErasureCodeInterfaceRef *erasure_code, - ostream *ss) { + std::ostream *ss) { ErasureCodeShec *interface; if (profile.find("technique") == profile.end()) diff --git a/ceph/src/erasure-code/shec/ErasureCodeShec.cc b/ceph/src/erasure-code/shec/ErasureCodeShec.cc index 139b7b9e8..c25732c47 100644 --- a/ceph/src/erasure-code/shec/ErasureCodeShec.cc +++ b/ceph/src/erasure-code/shec/ErasureCodeShec.cc @@ -23,6 +23,8 @@ #include #include #include +using namespace std; + #include "common/debug.h" #include "ErasureCodeShec.h" #include "crush/CrushWrapper.h" @@ -49,8 +51,9 @@ int ErasureCodeShec::create_ruleset(const string &name, CrushWrapper &crush, ostream *ss) const { - int ruleid = crush.add_simple_ruleset(name, ruleset_root, ruleset_failure_domain, - "indep", pg_pool_t::TYPE_ERASURE, ss); + int ruleid = crush.add_simple_rule( + name, ruleset_root, ruleset_failure_domain, + "indep", pg_pool_t::TYPE_ERASURE, ss); if (ruleid < 0) { return ruleid; } else { @@ -63,10 +66,10 @@ int ErasureCodeShec::init(ErasureCodeProfile &profile, ostream *ss) { int err = 0; - err |= to_string("ruleset-root", profile, + err |= ErasureCode::to_string("ruleset-root", profile, &ruleset_root, DEFAULT_RULESET_ROOT, ss); - err |= to_string("ruleset-failure-domain", profile, + err |= ErasureCode::to_string("ruleset-failure-domain", profile, &ruleset_failure_domain, DEFAULT_RULESET_FAILURE_DOMAIN, ss); err |= parse(profile); diff --git a/ceph/src/erasure-code/shec/ErasureCodeShec.h b/ceph/src/erasure-code/shec/ErasureCodeShec.h index b3c460146..2974bce9d 100644 --- a/ceph/src/erasure-code/shec/ErasureCodeShec.h +++ b/ceph/src/erasure-code/shec/ErasureCodeShec.h @@ -21,10 +21,8 @@ #ifndef CEPH_ERASURE_CODE_SHEC_H #define CEPH_ERASURE_CODE_SHEC_H -#include "common/Mutex.h" #include "erasure-code/ErasureCode.h" #include "ErasureCodeShecTableCache.h" -#include #define DEFAULT_RULESET_ROOT "default" #define DEFAULT_RULESET_FAILURE_DOMAIN "host" diff --git a/ceph/src/erasure-code/shec/ErasureCodeShecTableCache.cc b/ceph/src/erasure-code/shec/ErasureCodeShecTableCache.cc index 6f0c1d83c..891cada64 100644 --- a/ceph/src/erasure-code/shec/ErasureCodeShecTableCache.cc +++ b/ceph/src/erasure-code/shec/ErasureCodeShecTableCache.cc @@ -19,9 +19,9 @@ // ----------------------------------------------------------------------------- #include "ErasureCodeShecTableCache.h" -#include "ErasureCodeShec.h" #include "common/debug.h" // ----------------------------------------------------------------------------- +using namespace std; // ----------------------------------------------------------------------------- #define dout_context g_ceph_context diff --git a/ceph/src/fetch_config b/ceph/src/fetch_config deleted file mode 100644 index f0787b689..000000000 --- a/ceph/src/fetch_config +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -conf="$1" - -## fetch ceph.conf from some remote location and save it to $conf. -## -## make sure this script is executable (chmod +x fetch_config) - -## -## examples: -## - -## from a locally accessible file -# cp /path/to/ceph.conf $conf - -## from a URL: -# wget -q -O $conf http://somewhere.com/some/ceph.conf - -## via scp -# scp -i /path/to/id_dsa user@host:/path/to/ceph.conf $conf - diff --git a/ceph/src/include/atomic.h b/ceph/src/include/atomic.h deleted file mode 100644 index d5bc1c722..000000000 --- a/ceph/src/include/atomic.h +++ /dev/null @@ -1,157 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2004-2011 New Dream Network - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - * @author Sage Weil - */ - -#ifndef CEPH_ATOMIC_H -#define CEPH_ATOMIC_H - -#ifdef __CEPH__ -# include "acconfig.h" -#endif - -#include -#include "include/Spinlock.h" - -namespace ceph { - template - class atomic_spinlock_t { - mutable ceph_spinlock_t lock; - T val; - public: - atomic_spinlock_t(T i=0) - : val(i) { - ceph_spin_init(&lock); - } - ~atomic_spinlock_t() { - ceph_spin_destroy(&lock); - } - void set(T v) { - ceph_spin_lock(&lock); - val = v; - ceph_spin_unlock(&lock); - } - T inc() { - ceph_spin_lock(&lock); - T r = ++val; - ceph_spin_unlock(&lock); - return r; - } - T dec() { - ceph_spin_lock(&lock); - T r = --val; - ceph_spin_unlock(&lock); - return r; - } - void add(T d) { - ceph_spin_lock(&lock); - val += d; - ceph_spin_unlock(&lock); - } - void sub(T d) { - ceph_spin_lock(&lock); - val -= d; - ceph_spin_unlock(&lock); - } - T read() const { - T ret; - ceph_spin_lock(&lock); - ret = val; - ceph_spin_unlock(&lock); - return ret; - } - bool compare_and_swap(T o, T n) { - bool success = false; - ceph_spin_lock(&lock); - if (val == o) { - success = true; - val = n; - } - ceph_spin_unlock(&lock); - return success; - } - - private: - // forbid copying - atomic_spinlock_t(const atomic_spinlock_t &other); - atomic_spinlock_t &operator=(const atomic_spinlock_t &rhs); - }; -} - -#ifndef NO_ATOMIC_OPS - -// libatomic_ops implementation -#define AO_REQUIRE_CAS -#include - -// reinclude our assert to clobber the system one -#include "include/assert.h" - -namespace ceph { - class atomic_t { - AO_t val; - public: - atomic_t(AO_t i=0) : val(i) {} - void set(AO_t v) { - AO_store(&val, v); - } - AO_t inc() { - return AO_fetch_and_add1(&val) + 1; - } - AO_t dec() { - return AO_fetch_and_sub1_write(&val) - 1; - } - AO_t add(AO_t add_me) { - return AO_fetch_and_add(&val, add_me) + add_me; - } - AO_t sub(AO_t sub_me) { - AO_t negsub = 0 - sub_me; - return AO_fetch_and_add_write(&val, negsub) + negsub; - } - AO_t read() const { - // cast away const on the pointer. this is only needed to build - // on lenny, but not newer debians, so the atomic_ops.h got fixed - // at some point. this hack can go away someday... - return AO_load_full((AO_t *)&val); - } - bool compare_and_swap(AO_t o, AO_t n) { - return AO_compare_and_swap(&val, o, n); - } - - private: - // forbid copying - atomic_t(const atomic_t &other); - atomic_t &operator=(const atomic_t &rhs); - }; - -#if SIZEOF_AO_T == 8 - typedef atomic_t atomic64_t; -#else - typedef atomic_spinlock_t atomic64_t; -#endif - -} - -#else -/* - * crappy slow implementation that uses a pthreads spinlock. - */ -#include "include/Spinlock.h" - -namespace ceph { - typedef atomic_spinlock_t atomic_t; - typedef atomic_spinlock_t atomic64_t; -} - -#endif -#endif diff --git a/ceph/src/include/buffer.h b/ceph/src/include/buffer.h index d8f8999b6..d9c92ce64 100644 --- a/ceph/src/include/buffer.h +++ b/ceph/src/include/buffer.h @@ -136,6 +136,7 @@ namespace buffer CEPH_BUFFER_API { class raw_posix_aligned; class raw_hack_aligned; class raw_char; + class raw_claimed_char; class raw_pipe; class raw_unshareable; // diagnostic, unshareable char buffer class raw_combined; @@ -310,7 +311,7 @@ namespace buffer CEPH_BUFFER_API { bool can_zero_copy() const; int zero_copy_to_fd(int fd, int64_t *offset) const; - unsigned wasted(); + unsigned wasted() const; int cmp(const ptr& o) const; bool is_zero() const; @@ -347,6 +348,7 @@ namespace buffer CEPH_BUFFER_API { unsigned _len; unsigned _memcopy_count; //the total of memcopy using rebuild(). ptr append_buffer; // where i put small appends. + int _mempool = -1; public: class iterator; @@ -680,6 +682,7 @@ namespace buffer CEPH_BUFFER_API { _memcopy_count = other._memcopy_count; last_p = begin(); append_buffer.swap(other.append_buffer); + _mempool = other._mempool; other.clear(); return *this; } @@ -688,6 +691,13 @@ namespace buffer CEPH_BUFFER_API { const ptr& front() const { return _buffers.front(); } const ptr& back() const { return _buffers.back(); } + void reassign_to_mempool(int pool); + void try_assign_to_mempool(int pool); + + size_t get_append_buffer_unused_tail_length() const { + return append_buffer.unused_tail_length(); + } + unsigned get_memcopy_count() const {return _memcopy_count; } const std::list& buffers() const { return _buffers; } void swap(list& other); @@ -769,12 +779,7 @@ namespace buffer CEPH_BUFFER_API { unsigned align_memory); bool rebuild_page_aligned(); - void reserve(size_t prealloc) { - if (append_buffer.unused_tail_length() < prealloc) { - append_buffer = buffer::create(prealloc); - append_buffer.set_length(0); // unused, so far. - } - } + void reserve(size_t prealloc); // assignment-op with move semantics const static unsigned int CLAIM_DEFAULT = 0; @@ -783,6 +788,8 @@ namespace buffer CEPH_BUFFER_API { void claim(list& bl, unsigned int flags = CLAIM_DEFAULT); void claim_append(list& bl, unsigned int flags = CLAIM_DEFAULT); void claim_prepend(list& bl, unsigned int flags = CLAIM_DEFAULT); + // only for bl is bufferlist::page_aligned_appender + void claim_append_piecewise(list& bl); // clone non-shareable buffers (make shareable) void make_shareable() { @@ -883,6 +890,13 @@ namespace buffer CEPH_BUFFER_API { } uint32_t crc32c(uint32_t crc) const; void invalidate_crc(); + + // These functions return a bufferlist with a pointer to a single + // static buffer. They /must/ not outlive the memory they + // reference. + static list static_from_mem(char* c, size_t l); + static list static_from_cstring(char* c); + static list static_from_string(std::string& s); }; /* @@ -897,7 +911,7 @@ namespace buffer CEPH_BUFFER_API { // cppcheck-suppress noExplicitConstructor hash(uint32_t init) : crc(init) { } - void update(buffer::list& bl) { + void update(const buffer::list& bl) { crc = bl.crc32c(crc); } @@ -949,7 +963,7 @@ std::ostream& operator<<(std::ostream& out, const buffer::list& bl); std::ostream& operator<<(std::ostream& out, const buffer::error& e); -inline bufferhash& operator<<(bufferhash& l, bufferlist &r) { +inline bufferhash& operator<<(bufferhash& l, const bufferlist &r) { l.update(r); return l; } diff --git a/ceph/src/include/ceph_features.h b/ceph/src/include/ceph_features.h index 8b8933b7e..9decdaff3 100755 --- a/ceph/src/include/ceph_features.h +++ b/ceph/src/include/ceph_features.h @@ -101,7 +101,7 @@ DEFINE_CEPH_FEATURE(21, 2, SERVER_LUMINOUS) DEFINE_CEPH_FEATURE(21, 2, RESEND_ON_SPLIT) // overlap DEFINE_CEPH_FEATURE(21, 2, RADOS_BACKOFF) // overlap DEFINE_CEPH_FEATURE(21, 2, OSDMAP_PG_UPMAP) // overlap -DEFINE_CEPH_FEATURE(21, 2, CRUSH_CHOOSEARGS) // overlap +DEFINE_CEPH_FEATURE(21, 2, CRUSH_CHOOSE_ARGS) // overlap DEFINE_CEPH_FEATURE_RETIRED(22, 1, BACKFILL_RESERVATION, JEWEL, LUMINOUS) DEFINE_CEPH_FEATURE(23, 1, MSG_AUTH) @@ -253,7 +253,7 @@ DEFINE_CEPH_FEATURE_DEPRECATED(63, 1, RESERVED_BROKEN, LUMINOUS) // client-facin CEPH_FEATURE_CRUSH_TUNABLES5 | \ CEPH_FEATURE_CRUSH_V2 | \ CEPH_FEATURE_CRUSH_V4 | \ - CEPH_FEATURE_CRUSH_CHOOSEARGS) + CEPH_FEATURE_CRUSH_CHOOSE_ARGS) /* * make sure we don't try to use the reserved features diff --git a/ceph/src/include/ceph_fs.h b/ceph/src/include/ceph_fs.h index 726ee69d6..4188bff8b 100644 --- a/ceph/src/include/ceph_fs.h +++ b/ceph/src/include/ceph_fs.h @@ -305,7 +305,8 @@ enum { CEPH_SESSION_FORCE_RO, // A response to REQUEST_OPEN indicating that the client should // permanently desist from contacting the MDS - CEPH_SESSION_REJECT + CEPH_SESSION_REJECT, + CEPH_SESSION_REQUEST_FLUSH_MDLOG }; extern const char *ceph_session_op_name(int op); diff --git a/ceph/src/include/config-h.in.cmake b/ceph/src/include/config-h.in.cmake index 5569e2cf4..2847ceea2 100644 --- a/ceph/src/include/config-h.in.cmake +++ b/ceph/src/include/config-h.in.cmake @@ -84,8 +84,8 @@ /* Define if you have res_nquery */ #cmakedefine HAVE_RES_NQUERY -/* Defined if you don't have atomic_ops */ -#cmakedefine NO_ATOMIC_OPS +/* Defined if you have LZ4 */ +#cmakedefine HAVE_LZ4 /* Defined if you have libaio */ #cmakedefine HAVE_LIBAIO @@ -105,6 +105,9 @@ /* DPDK conditional compilation */ #cmakedefine HAVE_DPDK +/* PMEM conditional compilation */ +#cmakedefine HAVE_PMEM + /* Defined if LevelDB supports bloom filters */ #cmakedefine HAVE_LEVELDB_FILTER_POLICY @@ -169,6 +172,9 @@ /* Define if you want to use LTTng */ #cmakedefine WITH_LTTNG +/* Define if you want to OSD function instrumentation */ +#cmakedefine WITH_OSD_INSTRUMENT_FUNCTIONS + /* Define if you want to use Babeltrace */ #cmakedefine WITH_BABELTRACE @@ -199,24 +205,15 @@ /* LTTng is disabled, so define this macro to be nothing. */ #cmakedefine tracepoint -/* have boost::asio::coroutine */ -#cmakedefine HAVE_BOOST_ASIO_COROUTINE - /* Define to 1 if you have fdatasync. */ #cmakedefine HAVE_FDATASYNC 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_INTTYPES_H 1 - /* Defined if you have librocksdb enabled */ #cmakedefine HAVE_LIBROCKSDB /* Define to 1 if you have the header file. */ #cmakedefine HAVE_VALGRIND_HELGRIND_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDINT_H 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_PRCTL_H 1 @@ -321,4 +318,7 @@ #cmakedefine PYTHON_EXECUTABLE "@PYTHON_EXECUTABLE@" +/* Define to 1 if you have the `getprogname' function. */ +#cmakedefine HAVE_GETPROGNAME 1 + #endif /* CONFIG_H */ diff --git a/ceph/src/include/cpp-btree/btree_set.h b/ceph/src/include/cpp-btree/btree_set.h new file mode 100644 index 000000000..f9b2e75d8 --- /dev/null +++ b/ceph/src/include/cpp-btree/btree_set.h @@ -0,0 +1,121 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// A btree_set<> implements the STL unique sorted associative container +// interface (a.k.a set<>) using a btree. A btree_multiset<> implements the STL +// multiple sorted associative container interface (a.k.a multiset<>) using a +// btree. See btree.h for details of the btree implementation and caveats. + +#ifndef UTIL_BTREE_BTREE_SET_H__ +#define UTIL_BTREE_BTREE_SET_H__ + +#include +#include +#include + +#include "btree.h" +#include "btree_container.h" + +namespace btree { + +// The btree_set class is needed mainly for its constructors. +template , + typename Alloc = std::allocator, + int TargetNodeSize = 256> +class btree_set : public btree_unique_container< + btree > > { + + typedef btree_set self_type; + typedef btree_set_params params_type; + typedef btree btree_type; + typedef btree_unique_container super_type; + + public: + typedef typename btree_type::key_compare key_compare; + typedef typename btree_type::allocator_type allocator_type; + + public: + // Default constructor. + btree_set(const key_compare &comp = key_compare(), + const allocator_type &alloc = allocator_type()) + : super_type(comp, alloc) { + } + + // Copy constructor. + btree_set(const self_type &x) + : super_type(x) { + } + + // Range constructor. + template + btree_set(InputIterator b, InputIterator e, + const key_compare &comp = key_compare(), + const allocator_type &alloc = allocator_type()) + : super_type(b, e, comp, alloc) { + } +}; + +template +inline void swap(btree_set &x, btree_set &y) { + x.swap(y); +} + +// The btree_multiset class is needed mainly for its constructors. +template , + typename Alloc = std::allocator, + int TargetNodeSize = 256> +class btree_multiset : public btree_multi_container< + btree > > { + + typedef btree_multiset self_type; + typedef btree_set_params params_type; + typedef btree btree_type; + typedef btree_multi_container super_type; + + public: + typedef typename btree_type::key_compare key_compare; + typedef typename btree_type::allocator_type allocator_type; + + public: + // Default constructor. + btree_multiset(const key_compare &comp = key_compare(), + const allocator_type &alloc = allocator_type()) + : super_type(comp, alloc) { + } + + // Copy constructor. + btree_multiset(const self_type &x) + : super_type(x) { + } + + // Range constructor. + template + btree_multiset(InputIterator b, InputIterator e, + const key_compare &comp = key_compare(), + const allocator_type &alloc = allocator_type()) + : super_type(b, e, comp, alloc) { + } +}; + +template +inline void swap(btree_multiset &x, + btree_multiset &y) { + x.swap(y); +} + +} // namespace btree + +#endif // UTIL_BTREE_BTREE_SET_H__ diff --git a/ceph/src/include/crc32c.h b/ceph/src/include/crc32c.h index 35b6cafcc..dd4ede666 100644 --- a/ceph/src/include/crc32c.h +++ b/ceph/src/include/crc32c.h @@ -3,6 +3,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef uint32_t (*ceph_crc32c_func_t)(uint32_t crc, unsigned char const *data, unsigned length); /* @@ -13,6 +17,19 @@ extern ceph_crc32c_func_t ceph_crc32c_func; extern ceph_crc32c_func_t ceph_choose_crc32(void); +/** + * calculate crc32c for data that is entirely 0 (ZERO) + * + * Note: works the same as ceph_crc32c_func for data == nullptr, + * but faster than the optimized assembly on certain architectures. + * This is faster than intel optimized assembly, but not as fast as + * ppc64le optimized assembly. + * + * @param crc initial value + * @param length length of buffer + */ +uint32_t ceph_crc32c_zeros(uint32_t crc, unsigned length); + /** * calculate crc32c * @@ -25,7 +42,16 @@ extern ceph_crc32c_func_t ceph_choose_crc32(void); */ static inline uint32_t ceph_crc32c(uint32_t crc, unsigned char const *data, unsigned length) { - return ceph_crc32c_func(crc, data, length); +#ifndef HAVE_POWER8 + if (!data && length > 16) + return ceph_crc32c_zeros(crc, length); +#endif /* HAVE_POWER8 */ + + return ceph_crc32c_func(crc, data, length); } +#ifdef __cplusplus +} +#endif + #endif diff --git a/ceph/src/include/denc.h b/ceph/src/include/denc.h index d04f959d0..823da6408 100644 --- a/ceph/src/include/denc.h +++ b/ceph/src/include/denc.h @@ -37,6 +37,7 @@ #include #include +#include "include/assert.h" // boost clobbers this #include "include/intarith.h" #include "include/int_types.h" #include "include/memory.h" @@ -44,11 +45,12 @@ #include "buffer.h" #include "byteorder.h" -template +template struct denc_traits { static constexpr bool supported = false; static constexpr bool featured = false; static constexpr bool bounded = false; + static constexpr bool need_contiguous = true; }; @@ -138,6 +140,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool bounded = false; static constexpr bool featured = false; + static constexpr bool need_contiguous = true; static void bound_encode(const T &o, size_t& p, uint64_t f=0); static void encode(const T &o, buffer::list::contiguous_appender& p, uint64_t f=0); @@ -151,6 +154,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool bounded = false; static constexpr bool featured = true; + static constexpr bool need_contiguous = true; static void bound_encode(const T &o, size_t& p, uint64_t f); static void encode(const T &o, buffer::list::contiguous_appender& p, uint64_t f); @@ -190,6 +194,12 @@ struct denc_traits { declared via WRITE_CLASS_DENC, although you can also invoke them explicitly in your code. + - These methods are optimised for contiguous buffer, but denc() will try + rebuild a contigous one if the decoded bufferlist is segmented. If you are + concerned about the cost, you might want to define yet another method: + + void decode(buffer::list::iterator &p); + - These can be defined either explicitly (as above), or can be "magically" defined all in one go using the DENC macro and DENC_{START,FINISH} helpers (which work like the legacy {ENCODE,DECODE}_{START,FINISH} macros): @@ -212,35 +222,47 @@ struct denc_traits { // --------------------------------------------------------------------- // raw types +namespace _denc { + template struct is_any_of : std::false_type + {}; + template + struct is_any_of : std::conditional< + std::is_same::value, + std::true_type, + is_any_of>::type + {}; +} -#define WRITE_RAW_DENC(type) \ - template<> \ - struct denc_traits { \ - static constexpr bool supported = true; \ - static constexpr bool featured = false; \ - static constexpr bool bounded = true; \ - static void bound_encode(const type &o, size_t& p, uint64_t f=0) { \ - p += sizeof(type); \ - } \ - static void encode(const type &o, \ - buffer::list::contiguous_appender& p, \ - uint64_t f=0) { \ - p.append((const char*)&o, sizeof(o)); \ - } \ - static void decode(type& o, buffer::ptr::iterator &p, \ - uint64_t f=0) { \ - o = *(type *)p.get_pos_add(sizeof(o)); \ - } \ - }; -WRITE_RAW_DENC(ceph_le64) -WRITE_RAW_DENC(ceph_le32) -WRITE_RAW_DENC(ceph_le16) -WRITE_RAW_DENC(uint8_t); +template +struct denc_traits< + T, + typename std::enable_if< + _denc::is_any_of::value>::type> { + static constexpr bool supported = true; + static constexpr bool featured = false; + static constexpr bool bounded = true; + static constexpr bool need_contiguous = false; + static void bound_encode(const T &o, size_t& p, uint64_t f=0) { + p += sizeof(T); + } + static void encode(const T &o, + buffer::list::contiguous_appender& p, + uint64_t f=0) { + p.append((const char*)&o, sizeof(o)); + } + static void decode(T& o, buffer::ptr::iterator &p, + uint64_t f=0) { + o = *(T *)p.get_pos_add(sizeof(o)); + } + static void decode(T& o, buffer::list::iterator &p) { + p.copy(sizeof(T), reinterpret_cast(&o)); + } +}; // ----------------------------------------------------------------------- @@ -254,34 +276,65 @@ WRITE_RAW_DENC(int8_t); // template, and hence get selected. This machinary prevents these these from // getting glued into the legacy encode/decode methods; the overhead of setting // up a contiguous_appender etc is likely to be slower. +namespace _denc { -#define WRITE_INT_DENC(itype, etype) \ - template<> \ - struct denc_traits { \ - static constexpr bool supported = true; \ - static constexpr bool featured = false; \ - static constexpr bool bounded = true; \ - static void bound_encode(const itype &o, size_t& p, uint64_t f=0) { \ - p += sizeof(etype); \ - } \ - static void encode(const itype &o, buffer::list::contiguous_appender& p, \ - uint64_t f=0) { \ - *(etype *)p.get_pos_add(sizeof(etype)) = o; \ - } \ - static void decode(itype& o, buffer::ptr::iterator &p, \ - uint64_t f=0) { \ - o = *(etype*)p.get_pos_add(sizeof(etype)); \ - } \ - }; +template struct ExtType { + using type = void; +}; -WRITE_INT_DENC(uint16_t, __le16); -WRITE_INT_DENC(int16_t, __le16); -WRITE_INT_DENC(uint32_t, __le32); -WRITE_INT_DENC(int32_t, __le32); -WRITE_INT_DENC(uint64_t, __le64); -WRITE_INT_DENC(int64_t, __le64); -WRITE_INT_DENC(bool, uint8_t); +template struct ExtType< + T, + typename std::enable_if::value || + std::is_same::value>::type> { + using type = __le16; +}; + +template struct ExtType< + T, + typename std::enable_if::value || + std::is_same::value>::type> { + using type = __le32; +}; + +template struct ExtType< + T, + typename std::enable_if::value || + std::is_same::value>::type> { + using type = __le64; +}; +template<> struct ExtType { + using type = uint8_t; +}; +} // namespace _denc + +template +struct denc_traits< + T, + typename std::enable_if::type>::value>::type> +{ + static constexpr bool supported = true; + static constexpr bool featured = false; + static constexpr bool bounded = true; + static constexpr bool need_contiguous = false; + using etype = typename _denc::ExtType::type; + static void bound_encode(const T &o, size_t& p, uint64_t f=0) { + p += sizeof(etype); + } + static void encode(const T &o, buffer::list::contiguous_appender& p, + uint64_t f=0) { + *(etype *)p.get_pos_add(sizeof(etype)) = o; + } + static void decode(T& o, buffer::ptr::iterator &p, + uint64_t f=0) { + o = *(etype*)p.get_pos_add(sizeof(etype)); + } + static void decode(T& o, buffer::list::iterator &p) { + etype e; + p.copy(sizeof(etype), reinterpret_cast(&e)); + o = e; + } +}; // varint // @@ -561,6 +614,40 @@ inline typename std::enable_if + struct has_legacy_denc : std::false_type + {}; + template + struct has_legacy_denc() + .decode(std::declval()))> : std::true_type + { + static void decode(T& v, bufferlist::iterator& p) { + v.decode(p); + } + }; + template + struct has_legacy_denc::need_contiguous>::type> : std::true_type + { + static void decode(T& v, bufferlist::iterator& p) { + denc_traits::decode(v, p); + } + }; +} + +template, + typename has_legacy_denc=_denc::has_legacy_denc> +inline typename std::enable_if::type denc( + T& o, + buffer::list::iterator& p) +{ + has_legacy_denc::decode(o, p); +} // --------------------------------------------------------------------- // base types and containers @@ -577,6 +664,7 @@ public: static constexpr bool supported = true; static constexpr bool featured = false; static constexpr bool bounded = false; + static constexpr bool need_contiguous = false; static void bound_encode(const value_type& s, size_t& p, uint64_t f=0) { p += sizeof(uint32_t) + s.size(); @@ -594,6 +682,13 @@ public: ::denc(len, p); decode_nohead(len, s, p); } + static void decode(value_type& s, buffer::list::iterator& p) + { + uint32_t len; + ::denc(len, p); + s.clear(); + p.copy(len, s); + } static void decode_nohead(size_t len, value_type& s, buffer::ptr::iterator& p) { s.clear(); @@ -615,6 +710,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool featured = false; static constexpr bool bounded = false; + static constexpr bool need_contiguous = false; static void bound_encode(const bufferptr& v, size_t& p, uint64_t f=0) { p += sizeof(uint32_t) + v.length(); } @@ -628,6 +724,18 @@ struct denc_traits { ::denc(len, p); v = p.get_ptr(len); } + static void decode(bufferptr& v, buffer::list::iterator& p) { + uint32_t len; + ::denc(len, p); + bufferlist s; + p.copy(len, s); + if (len) { + if (s.get_num_buffers() == 1) + v = s.front(); + else + v = buffer::copy(s.c_str(), s.length()); + } + } }; // @@ -638,6 +746,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool featured = false; static constexpr bool bounded = false; + static constexpr bool need_contiguous = false; static void bound_encode(const bufferlist& v, size_t& p, uint64_t f=0) { p += sizeof(uint32_t) + v.length(); } @@ -652,6 +761,12 @@ struct denc_traits { v.clear(); v.push_back(p.get_ptr(len)); } + static void decode(bufferlist& v, buffer::list::iterator& p) { + uint32_t len; + ::denc(len, p); + v.clear(); + p.copy(len, v); + } static void encode_nohead(const bufferlist& v, buffer::list::contiguous_appender& p) { p.append(v); @@ -679,6 +794,8 @@ struct denc_traits< static constexpr bool supported = true; static constexpr bool featured = a_traits::featured || b_traits::featured ; static constexpr bool bounded = a_traits::bounded && b_traits::bounded; + static constexpr bool need_contiguous = (a_traits::need_contiguous || + b_traits::need_contiguous); template static typename std::enable_if + static typename std::enable_if::type + decode(std::pair& v, buffer::list::iterator& p, + uint64_t f = 0) { + denc(v.first, p); + denc(v.second, p); + } }; namespace _denc { @@ -730,6 +854,7 @@ namespace _denc { static constexpr bool supported = true; static constexpr bool featured = traits::featured; static constexpr bool bounded = false; + static constexpr bool need_contiguous = traits::need_contiguous; template static typename std::enable_if + static typename std::enable_if::type + decode(container& s, buffer::list::iterator& p) { + uint32_t num; + denc(num, p); + decode_nohead(num, s, p); + } // nohead template @@ -829,6 +961,18 @@ namespace _denc { Details::insert(s, std::move(t)); } } + template + static typename std::enable_if::type + decode_nohead(size_t num, container& s, + buffer::list::iterator& p) { + s.clear(); + Details::reserve(s, num); + while (num--) { + T t; + denc(t, p); + Details::insert(s, std::move(t)); + } + } }; template @@ -965,6 +1109,7 @@ public: static constexpr bool supported = true; static constexpr bool featured = traits::featured; static constexpr bool bounded = traits::bounded; + static constexpr bool need_contiguous = traits::need_contiguous; template static typename std::enable_if + static typename std::enable_if::type + decode(container& s, buffer::list::iterator& p) { + for (auto& e : s) { + denc(e, p); + } + } }; namespace _denc { @@ -1066,12 +1219,16 @@ namespace _denc { tuple_traits::bounded); static constexpr bool featured = (denc_traits::featured || tuple_traits::featured); + static constexpr bool need_contiguous = + (denc_traits::need_contiguous || + tuple_traits::need_contiguous); }; template<> struct tuple_traits<> { static constexpr bool supported = true; static constexpr bool bounded = true; static constexpr bool featured = false; + static constexpr bool need_contiguous = false; }; } @@ -1167,6 +1324,17 @@ private: _denc::indices) { denc(std::get(s), p); } + template + static void decode_helper(T& s, buffer::list::iterator& p, + _denc::indices) { + denc(std::get(s), p); + decode_helper(s, p, _denc::indices{}); + } + template + static void decode_helper(T& s, buffer::list::iterator& p, + _denc::indices) { + denc(std::get(s), p); + } public: using traits = _denc::tuple_traits; @@ -1174,6 +1342,7 @@ public: static constexpr bool supported = true; static constexpr bool featured = traits::featured; static constexpr bool bounded = traits::bounded; + static constexpr bool need_contiguous = traits::need_contiguous; template @@ -1222,6 +1391,12 @@ public: static void decode(container& s, buffer::ptr::iterator& p, uint64_t f = 0) { decode_helper(s, p, _denc::build_indices_t{}); } + template + static typename std::enable_if::type + decode(container& s, buffer::list::iterator& p, uint64_t f = 0) { + decode_helper(s, p, _denc::build_indices_t{}); + } }; // @@ -1236,6 +1411,7 @@ struct denc_traits< static constexpr bool supported = true; static constexpr bool featured = traits::featured; static constexpr bool bounded = false; + static constexpr bool need_contiguous = traits::need_contiguous; template static typename std::enable_if::type @@ -1280,6 +1456,19 @@ struct denc_traits< } } + template + static typename std::enable_if::type + decode(boost::optional& v, buffer::list::iterator& p) { + bool x; + denc(x, p); + if (x) { + v = T{}; + denc(*v, p); + } else { + v = boost::none; + } + } + template static typename std::enable_if::type encode_nohead(const boost::optional& v, @@ -1312,6 +1501,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool featured = false; static constexpr bool bounded = true; + static constexpr bool need_contiguous = false; static void bound_encode(const boost::none_t& v, size_t& p) { p += sizeof(bool); @@ -1336,6 +1526,7 @@ struct denc_traits { static constexpr bool supported = true; \ static constexpr bool featured = false; \ static constexpr bool bounded = b; \ + static constexpr bool need_contiguous = !_denc::has_legacy_denc::value;\ static void bound_encode(const T& v, size_t& p, uint64_t f=0) { \ v.bound_encode(p); \ } \ @@ -1355,6 +1546,7 @@ struct denc_traits { static constexpr bool supported = true; \ static constexpr bool featured = true; \ static constexpr bool bounded = b; \ + static constexpr bool need_contiguous = !_denc::has_legacy_denc::value;\ static void bound_encode(const T& v, size_t& p, uint64_t f) { \ v.bound_encode(p, f); \ } \ @@ -1399,34 +1591,48 @@ inline typename std::enable_if> +template> inline typename std::enable_if::type decode( + !traits::need_contiguous>::type decode( T& o, bufferlist::iterator& p) { if (p.end()) throw buffer::end_of_buffer(); - // ensure we get a contigous buffer... until the end of the - // bufferlist. we don't really know how much we'll need here, - // unfortunately. hopefully it is already contiguous and we're just - // bumping the raw ref and initializing the ptr tmp fields. - bufferptr tmp; - bufferlist::iterator t = p; - t.copy_shallow(p.get_bl().length() - p.get_off(), tmp); - auto cp = tmp.begin(); - traits::decode(o, cp); - p.advance((ssize_t)cp.get_offset()); + const auto& bl = p.get_bl(); + const auto remaining = bl.length() - p.get_off(); + // it is expensive to rebuild a contigous buffer and drop it, so avoid this. + if (p.get_current_ptr().get_raw() != bl.back().get_raw() && + remaining > CEPH_PAGE_SIZE) { + traits::decode(o, p); + } else { + // ensure we get a contigous buffer... until the end of the + // bufferlist. we don't really know how much we'll need here, + // unfortunately. hopefully it is already contiguous and we're just + // bumping the raw ref and initializing the ptr tmp fields. + bufferptr tmp; + bufferlist::iterator t = p; + t.copy_shallow(remaining, tmp); + auto cp = tmp.begin(); + traits::decode(o, cp); + p.advance((ssize_t)cp.get_offset()); + } } -template> +template> inline typename std::enable_if::type decode( + traits::need_contiguous>::type decode( T& o, bufferlist::iterator& p) { if (p.end()) throw buffer::end_of_buffer(); + // ensure we get a contigous buffer... until the end of the + // bufferlist. we don't really know how much we'll need here, + // unfortunately. hopefully it is already contiguous and we're just + // bumping the raw ref and initializing the ptr tmp fields. bufferptr tmp; bufferlist::iterator t = p; t.copy_shallow(p.get_bl().length() - p.get_off(), tmp); diff --git a/ceph/src/include/encoding.h b/ceph/src/include/encoding.h index 953420e89..0013728ef 100644 --- a/ceph/src/include/encoding.h +++ b/ceph/src/include/encoding.h @@ -512,6 +512,7 @@ decode(boost::container::flat_set& s, bufferlist::iterator& p) __u32 n; decode(n, p); s.clear(); + s.reserve(n); while (n--) { T v; decode(v, p); @@ -532,6 +533,7 @@ inline typename std::enable_if::type decode_nohead(int len, boost::container::flat_set& s, bufferlist::iterator& p) { + s.reserve(len); for (int i=0; i& m, { __u32 n; decode(n, p); + m.reserve(m.size() + n); while (n--) { T k; decode(k, p); diff --git a/ceph/src/include/frag.h b/ceph/src/include/frag.h index 7e0d4a8ee..3b1456cbb 100644 --- a/ceph/src/include/frag.h +++ b/ceph/src/include/frag.h @@ -148,7 +148,7 @@ class frag_t { } }; -inline std::ostream& operator<<(std::ostream& out, frag_t hb) +inline std::ostream& operator<<(std::ostream& out, const frag_t& hb) { //out << std::hex << hb.value() << std::dec << "/" << hb.bits() << '='; unsigned num = hb.bits(); diff --git a/ceph/src/include/fs_types.h b/ceph/src/include/fs_types.h index 161d44104..c6343fe1b 100644 --- a/ceph/src/include/fs_types.h +++ b/ceph/src/include/fs_types.h @@ -4,7 +4,6 @@ #define CEPH_INCLUDE_FS_TYPES_H #include "types.h" -#include "utime.h" // -------------------------------------- // ino @@ -33,6 +32,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool featured = false; static constexpr bool bounded = true; + static constexpr bool need_contiguous = true; static void bound_encode(const inodeno_t &o, size_t& p) { denc(o.val, p); } @@ -44,7 +44,7 @@ struct denc_traits { } }; -inline ostream& operator<<(ostream& out, inodeno_t ino) { +inline ostream& operator<<(ostream& out, const inodeno_t& ino) { return out << hex << ino.val << dec; } diff --git a/ceph/src/include/inline_memory.h b/ceph/src/include/inline_memory.h index f2166826b..f2433f03e 100644 --- a/ceph/src/include/inline_memory.h +++ b/ceph/src/include/inline_memory.h @@ -124,6 +124,15 @@ bool mem_is_zero(const char *data, size_t len) static inline bool mem_is_zero(const char *data, size_t len) { const char *end = data + len; + const char* end64 = data + (len / sizeof(uint64_t))*sizeof(uint64_t); + + while (data < end64) { + if (*(uint64_t*)data != 0) { + return false; + } + data += sizeof(uint64_t); + } + while (data < end) { if (*data != 0) { return false; diff --git a/ceph/src/include/int_types.h b/ceph/src/include/int_types.h index 2ffb162cc..61ad79713 100644 --- a/ceph/src/include/int_types.h +++ b/ceph/src/include/int_types.h @@ -3,62 +3,11 @@ #include "acconfig.h" -/* - * Get 64b integers either from inttypes.h or glib.h - */ -#ifdef HAVE_INTTYPES_H -# include -//#else -//# ifdef HAVE_GLIB -//# include -//# endif -#endif - -/* - * C99 says inttypes.h includes stdint.h, but that's not true on all - * systems. If it's there, include it always - just in case. - */ -#ifdef HAVE_STDINT_H -#include -#endif +#include -/* - * Include types.h after stdint.h to accomodate for older distributions - * - */ #ifdef HAVE_LINUX_TYPES_H #include -#endif - -/* - * Emergency replacements for PRI*64 modifiers. Some systems have - * an inttypes.h that doesn't define all the PRI[doxu]64 macros. - */ -#if !defined(PRIu64) -# if defined(HAVE_INTTYPES_H) || defined(HAVE_GLIB) -/* If we have inttypes or glib, assume we have 64-bit long long int */ -# define PRIu64 "llu" -# define PRIi64 "lli" -# define PRIx64 "llx" -# define PRIX64 "llX" -# define PRIo64 "llo" -# define PRId64 "lld" -# else -/* Assume that we don't have long long, so use long int modifiers */ -# define PRIu64 "lu" -# define PRIi64 "li" -# define PRIx64 "lx" -# define PRIX64 "lX" -# define PRIo64 "lo" -# define PRId64 "ld" -# endif -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#ifndef HAVE_LINUX_TYPES_H +#else #ifndef HAVE___U8 typedef uint8_t __u8; #endif diff --git a/ceph/src/include/interval_set.h b/ceph/src/include/interval_set.h index de7cf9308..b84d81870 100644 --- a/ceph/src/include/interval_set.h +++ b/ceph/src/include/interval_set.h @@ -249,15 +249,21 @@ class interval_set { denc_traits>::bound_encode(m, p); } void encode(bufferlist::contiguous_appender& p) const { - denc_traits>::encode(m, p); + denc(m, p); } void decode(bufferptr::iterator& p) { - denc_traits>::decode(m, p); + denc(m, p); _size = 0; - for (typename std::map::const_iterator i = m.begin(); - i != m.end(); - i++) - _size += i->second; + for (const auto& i : m) { + _size += i.second; + } + } + void decode(bufferlist::iterator& p) { + denc(m, p); + _size = 0; + for (const auto& i : m) { + _size += i.second; + } } void encode_nohead(bufferlist::contiguous_appender& p) const { @@ -266,10 +272,9 @@ class interval_set { void decode_nohead(int n, bufferptr::iterator& p) { denc_traits>::decode_nohead(n, m, p); _size = 0; - for (typename std::map::const_iterator i = m.begin(); - i != m.end(); - i++) - _size += i->second; + for (const auto& i : m) { + _size += i.second; + } } void clear() { @@ -576,6 +581,7 @@ struct denc_traits> { static constexpr bool supported = true; static constexpr bool bounded = false; static constexpr bool featured = false; + static constexpr bool need_contiguous = denc_traits::need_contiguous; static void bound_encode(const interval_set& v, size_t& p) { v.bound_encode(p); } @@ -586,6 +592,11 @@ struct denc_traits> { static void decode(interval_set& v, bufferptr::iterator& p) { v.decode(p); } + template + static typename std::enable_if::type + decode(interval_set& v, bufferlist::iterator& p) { + v.decode(p); + } static void encode_nohead(const interval_set& v, bufferlist::contiguous_appender& p) { v.encode_nohead(p); diff --git a/ceph/src/include/ipaddr.h b/ceph/src/include/ipaddr.h index bf1a08308..ac0dc620f 100644 --- a/ceph/src/include/ipaddr.h +++ b/ceph/src/include/ipaddr.h @@ -1,10 +1,6 @@ #ifndef CEPH_IPADDR_H #define CEPH_IPADDR_H -#include -#include -#include - /* Find an IP address that is in the wanted subnet. diff --git a/ceph/src/include/lru.h b/ceph/src/include/lru.h index 7dff441f7..e88cedc60 100644 --- a/ceph/src/include/lru.h +++ b/ceph/src/include/lru.h @@ -59,7 +59,7 @@ class LRUList { len = 0; } - uint32_t get_length() { return len; } + uint32_t get_length() const { return len; } LRUObject *get_head() { return head; @@ -136,12 +136,12 @@ class LRU { lru_max = max; } - uint32_t lru_get_size() { return lru_num; } - uint32_t lru_get_top() { return lru_top.get_length(); } - uint32_t lru_get_bot() { return lru_bot.get_length(); } - uint32_t lru_get_pintail() { return lru_pintail.get_length(); } - uint32_t lru_get_max() { return lru_max; } - uint32_t lru_get_num_pinned() { return lru_num_pinned; } + uint32_t lru_get_size() const { return lru_num; } + uint32_t lru_get_top() const { return lru_top.get_length(); } + uint32_t lru_get_bot() const{ return lru_bot.get_length(); } + uint32_t lru_get_pintail() const { return lru_pintail.get_length(); } + uint32_t lru_get_max() const { return lru_max; } + uint32_t lru_get_num_pinned() const { return lru_num_pinned; } void lru_set_max(uint32_t m) { lru_max = m; } void lru_set_midpoint(float f) { lru_midpoint = f; } diff --git a/ceph/src/include/mempool.h b/ceph/src/include/mempool.h index b995905b5..b0f29baa0 100644 --- a/ceph/src/include/mempool.h +++ b/ceph/src/include/mempool.h @@ -62,15 +62,15 @@ automatically created (name is same as in DEFINE_MEMORY_POOLS_HELPER). That namespace contains a set of common STL containers that are predefined with the appropriate allocators. -Thus for mempool "unittest_1" we have automatically available to us: +Thus for mempool "osd" we have automatically available to us: - mempool::unittest_1::map - mempool::unittest_1::multimap - mempool::unittest_1::set - mempool::unittest_1::multiset - mempool::unittest_1::list - mempool::unittest_1::vector - mempool::unittest_1::unordered_map + mempool::osd::map + mempool::osd::multimap + mempool::osd::set + mempool::osd::multiset + mempool::osd::list + mempool::osd::vector + mempool::osd::unordered_map Putting objects in a mempool @@ -88,7 +88,7 @@ For a class: Then, in an appropriate .cc file, - MEMPOOL_DEFINE_OBJECT_FACTORY(Foo, foo, unittest_1); + MEMPOOL_DEFINE_OBJECT_FACTORY(Foo, foo, osd); The second argument can generally be identical to the first, except when the type contains a nested scope. For example, for @@ -103,7 +103,7 @@ can't use :: in a variable name.) In order to use the STL containers, simply use the namespaced variant of the container type. For example, - mempool::unittest_1::map myvec; + mempool::osd::map myvec; Introspection ------------- @@ -137,16 +137,23 @@ namespace mempool { #define DEFINE_MEMORY_POOLS_HELPER(f) \ f(bloom_filter) \ - f(bluestore_meta_onode) \ - f(bluestore_meta_other) \ f(bluestore_alloc) \ + f(bluestore_cache_data) \ + f(bluestore_cache_onode) \ + f(bluestore_cache_other) \ f(bluestore_fsck) \ + f(bluestore_txc) \ + f(bluestore_writing_deferred) \ + f(bluestore_writing) \ f(bluefs) \ + f(buffer_anon) \ f(buffer_meta) \ - f(buffer_data) \ f(osd) \ + f(osd_mapbl) \ + f(osd_pglog) \ f(osdmap) \ f(osdmap_mapping) \ + f(pgmap) \ f(unittest_1) \ f(unittest_2) @@ -190,6 +197,12 @@ struct stats_t { f->dump_int("items", items); f->dump_int("bytes", bytes); } + + stats_t& operator+=(const stats_t& o) { + items += o.items; + bytes += o.bytes; + return *this; + } }; pool_t& get_pool(pool_index_t ix); @@ -220,6 +233,8 @@ public: size_t allocated_bytes() const; size_t allocated_items() const; + void adjust_count(ssize_t items, ssize_t bytes); + shard_t* pick_a_shard() { // Dirt cheap, see: // http://fossies.org/dox/glibc-2.24/pthread__self_8c_source.html @@ -244,7 +259,7 @@ public: void get_stats(stats_t *total, std::map *by_type) const; - void dump(ceph::Formatter *f) const; + void dump(ceph::Formatter *f, stats_t *ptotal=0) const; }; void dump(ceph::Formatter *f); diff --git a/ceph/src/include/object.h b/ceph/src/include/object.h index 672fbc4c3..50aa3fee2 100644 --- a/ceph/src/include/object.h +++ b/ceph/src/include/object.h @@ -127,6 +127,7 @@ struct denc_traits { static constexpr bool supported = true; static constexpr bool featured = false; static constexpr bool bounded = true; + static constexpr bool need_contiguous = true; static void bound_encode(const snapid_t& o, size_t& p) { denc(o.val, p); } @@ -138,7 +139,7 @@ struct denc_traits { } }; -inline ostream& operator<<(ostream& out, snapid_t s) { +inline ostream& operator<<(ostream& out, const snapid_t& s) { if (s == CEPH_NOSNAP) return out << "head"; else if (s == CEPH_SNAPDIR) diff --git a/ceph/src/include/rados.h b/ceph/src/include/rados.h index 4eb09b89c..2ee2dcca3 100644 --- a/ceph/src/include/rados.h +++ b/ceph/src/include/rados.h @@ -110,13 +110,18 @@ struct ceph_eversion { */ /* status bits */ -#define CEPH_OSD_EXISTS (1<<0) -#define CEPH_OSD_UP (1<<1) -#define CEPH_OSD_AUTOOUT (1<<2) /* osd was automatically marked out */ -#define CEPH_OSD_NEW (1<<3) /* osd is new, never marked in */ -#define CEPH_OSD_FULL (1<<4) /* osd is at or above full threshold */ -#define CEPH_OSD_NEARFULL (1<<5) /* osd is at or above nearfull threshold */ -#define CEPH_OSD_BACKFILLFULL (1<<6) /* osd is at or above backfillfull threshold */ +#define CEPH_OSD_EXISTS (1<<0) +#define CEPH_OSD_UP (1<<1) +#define CEPH_OSD_AUTOOUT (1<<2) /* osd was automatically marked out */ +#define CEPH_OSD_NEW (1<<3) /* osd is new, never marked in */ +#define CEPH_OSD_FULL (1<<4) /* osd is at or above full threshold */ +#define CEPH_OSD_NEARFULL (1<<5) /* osd is at or above nearfull threshold */ +#define CEPH_OSD_BACKFILLFULL (1<<6) /* osd is at or above backfillfull threshold */ +#define CEPH_OSD_DESTROYED (1<<7) /* osd has been destroyed */ +#define CEPH_OSD_NOUP (1<<8) /* osd can not be marked up */ +#define CEPH_OSD_NODOWN (1<<9) /* osd can not be marked down */ +#define CEPH_OSD_NOIN (1<<10) /* osd can not be marked in */ +#define CEPH_OSD_NOOUT (1<<11) /* osd can not be marked out */ extern const char *ceph_osd_state_name(int s); @@ -131,24 +136,24 @@ extern const char *ceph_osd_state_name(int s); /* * osd map flag bits */ -#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC) */ -#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC) */ -#define CEPH_OSDMAP_PAUSERD (1<<2) /* pause all reads */ -#define CEPH_OSDMAP_PAUSEWR (1<<3) /* pause all writes */ -#define CEPH_OSDMAP_PAUSEREC (1<<4) /* pause recovery */ -#define CEPH_OSDMAP_NOUP (1<<5) /* block osd boot */ -#define CEPH_OSDMAP_NODOWN (1<<6) /* block osd mark-down/failure */ -#define CEPH_OSDMAP_NOOUT (1<<7) /* block osd auto mark-out */ -#define CEPH_OSDMAP_NOIN (1<<8) /* block osd auto mark-in */ -#define CEPH_OSDMAP_NOBACKFILL (1<<9) /* block osd backfill */ -#define CEPH_OSDMAP_NORECOVER (1<<10) /* block osd recovery and backfill */ -#define CEPH_OSDMAP_NOSCRUB (1<<11) /* block periodic scrub */ -#define CEPH_OSDMAP_NODEEP_SCRUB (1<<12) /* block periodic deep-scrub */ -#define CEPH_OSDMAP_NOTIERAGENT (1<<13) /* disable tiering agent */ -#define CEPH_OSDMAP_NOREBALANCE (1<<14) /* block osd backfill unless pg is degraded */ -#define CEPH_OSDMAP_SORTBITWISE (1<<15) /* use bitwise hobject_t sort */ -#define CEPH_OSDMAP_REQUIRE_JEWEL (1<<16) /* require jewel for booting osds */ -#define CEPH_OSDMAP_REQUIRE_KRAKEN (1<<17) /* require kraken for booting osds */ +#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC) */ +#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC) */ +#define CEPH_OSDMAP_PAUSERD (1<<2) /* pause all reads */ +#define CEPH_OSDMAP_PAUSEWR (1<<3) /* pause all writes */ +#define CEPH_OSDMAP_PAUSEREC (1<<4) /* pause recovery */ +#define CEPH_OSDMAP_NOUP (1<<5) /* block osd boot */ +#define CEPH_OSDMAP_NODOWN (1<<6) /* block osd mark-down/failure */ +#define CEPH_OSDMAP_NOOUT (1<<7) /* block osd auto mark-out */ +#define CEPH_OSDMAP_NOIN (1<<8) /* block osd auto mark-in */ +#define CEPH_OSDMAP_NOBACKFILL (1<<9) /* block osd backfill */ +#define CEPH_OSDMAP_NORECOVER (1<<10) /* block osd recovery and backfill */ +#define CEPH_OSDMAP_NOSCRUB (1<<11) /* block periodic scrub */ +#define CEPH_OSDMAP_NODEEP_SCRUB (1<<12) /* block periodic deep-scrub */ +#define CEPH_OSDMAP_NOTIERAGENT (1<<13) /* disable tiering agent */ +#define CEPH_OSDMAP_NOREBALANCE (1<<14) /* block osd backfill unless pg is degraded */ +#define CEPH_OSDMAP_SORTBITWISE (1<<15) /* use bitwise hobject_t sort */ +#define CEPH_OSDMAP_REQUIRE_JEWEL (1<<16) /* require jewel for booting osds */ +#define CEPH_OSDMAP_REQUIRE_KRAKEN (1<<17) /* require kraken for booting osds */ #define CEPH_OSDMAP_REQUIRE_LUMINOUS (1<<18) /* require l for booting osds */ /* these are hidden in 'ceph status' view */ @@ -156,6 +161,32 @@ extern const char *ceph_osd_state_name(int s); CEPH_OSDMAP_REQUIRE_KRAKEN | \ CEPH_OSDMAP_REQUIRE_LUMINOUS | \ CEPH_OSDMAP_SORTBITWISE) +#define CEPH_OSDMAP_LEGACY_REQUIRE_FLAGS (CEPH_OSDMAP_REQUIRE_JEWEL | \ + CEPH_OSDMAP_REQUIRE_KRAKEN | \ + CEPH_OSDMAP_REQUIRE_LUMINOUS) + +/* + * major ceph release numbers + */ +#define CEPH_RELEASE_ARGONAUT 1 +#define CEPH_RELEASE_BOBTAIL 2 +#define CEPH_RELEASE_CUTTLEFISH 3 +#define CEPH_RELEASE_DUMPLING 4 +#define CEPH_RELEASE_EMPEROR 5 +#define CEPH_RELEASE_FIREFLY 6 +#define CEPH_RELEASE_GIANT 7 +#define CEPH_RELEASE_HAMMER 8 +#define CEPH_RELEASE_INFERNALIS 9 +#define CEPH_RELEASE_JEWEL 10 +#define CEPH_RELEASE_KRAKEN 11 +#define CEPH_RELEASE_LUMINOUS 12 +#define CEPH_RELEASE_MIMIC 13 +#define CEPH_RELEASE_MAX 14 /* highest + 1 */ + +extern const char *ceph_release_name(int r); +extern int ceph_release_from_name(const char *s); +extern uint64_t ceph_release_features(int r); +extern int ceph_release_from_features(uint64_t features); /* * The error code to return when an OSD can't handle a write @@ -272,6 +303,9 @@ extern const char *ceph_osd_state_name(int s); f(WRITESAME, __CEPH_OSD_OP(WR, DATA, 38), "write-same") \ f(CMPEXT, __CEPH_OSD_OP(RD, DATA, 32), "cmpext") \ \ + /* Extensible */ \ + f(SET_REDIRECT, __CEPH_OSD_OP(WR, DATA, 39), "set-redirect") \ + \ /** attrs **/ \ /* read */ \ f(GETXATTR, __CEPH_OSD_OP(RD, ATTR, 1), "getxattr") \ @@ -414,6 +448,7 @@ enum { CEPH_OSD_FLAG_KNOWN_REDIR = 0x400000, /* redirect bit is authoritative */ CEPH_OSD_FLAG_FULL_TRY = 0x800000, /* try op despite full flag */ CEPH_OSD_FLAG_FULL_FORCE = 0x1000000, /* force op despite full flag */ + CEPH_OSD_FLAG_IGNORE_REDIRECT = 0x2000000, /* ignore redirection */ }; enum { diff --git a/ceph/src/include/rados/librados.h b/ceph/src/include/rados/librados.h index e111380a0..8fa4b69f5 100644 --- a/ceph/src/include/rados/librados.h +++ b/ceph/src/include/rados/librados.h @@ -128,6 +128,7 @@ enum { * Mainly for delete op */ LIBRADOS_OPERATION_FULL_FORCE = 128, + LIBRADOS_OPERATION_IGNORE_REDIRECT = 256, }; /** @} */ @@ -742,7 +743,7 @@ CEPH_RADOS_API int rados_ioctx_create2(rados_t cluster, int64_t pool_id, CEPH_RADOS_API void rados_ioctx_destroy(rados_ioctx_t io); /** - * Get configuration hadnle for a pool handle + * Get configuration handle for a pool handle * * @param io pool handle * @returns rados_config_t for this cluster @@ -3652,8 +3653,40 @@ typedef void (*rados_log_callback_t)(void *arg, uint64_t seq, const char *level, const char *msg); +/* + * This is not a doxygen comment leadin, because doxygen breaks on + * a typedef with function params and returns, and I can't figure out + * how to fix it. + * + * Monitor cluster log + * + * Monitor events logged to the cluster log. The callback get each + * log entry both as a single formatted line and with each field in a + * separate arg. + * + * Calling with a cb argument of NULL will deregister any previously + * registered callback. + * + * @param cluster cluster handle + * @param level minimum log level (debug, info, warn|warning, err|error) + * @param cb callback to run for each log message. It MUST NOT block + * nor call back into librados. + * @param arg void argument to pass to cb + * + * @returns 0 on success, negative code on error + */ +typedef void (*rados_log_callback2_t)(void *arg, + const char *line, + const char *who, + const char *name, + uint64_t sec, uint64_t nsec, + uint64_t seq, const char *level, + const char *msg); + CEPH_RADOS_API int rados_monitor_log(rados_t cluster, const char *level, rados_log_callback_t cb, void *arg); +CEPH_RADOS_API int rados_monitor_log2(rados_t cluster, const char *level, + rados_log_callback2_t cb, void *arg); /** @} Mon/OSD/PG commands */ diff --git a/ceph/src/include/rados/librados.hpp b/ceph/src/include/rados/librados.hpp index 10e8f2030..e4eb2d250 100644 --- a/ceph/src/include/rados/librados.hpp +++ b/ceph/src/include/rados/librados.hpp @@ -267,6 +267,7 @@ namespace librados OPERATION_FULL_TRY = LIBRADOS_OPERATION_FULL_TRY, //mainly for delete OPERATION_FULL_FORCE = LIBRADOS_OPERATION_FULL_FORCE, + OPERATION_IGNORE_REDIRECT = LIBRADOS_OPERATION_IGNORE_REDIRECT, }; /* @@ -463,6 +464,14 @@ namespace librados void cache_pin(); void cache_unpin(); + /** + * Extensible tier + * + * Set redirect target + */ + void set_redirect(const std::string& tgt_obj, const IoCtx& tgt_ioctx, + uint64_t tgt_version); + friend class IoCtx; }; diff --git a/ceph/src/include/rados/objclass.h b/ceph/src/include/rados/objclass.h index 08c508694..ea07dfc79 100644 --- a/ceph/src/include/rados/objclass.h +++ b/ceph/src/include/rados/objclass.h @@ -78,7 +78,7 @@ extern int cls_register(const char *name, cls_handle_t *handle); * */ typedef int (*cls_method_cxx_call_t)(cls_method_context_t ctx, - class buffer::list *inbl, class buffer::list *outbl); + class ceph::buffer::list *inbl, class ceph::buffer::list *outbl); /** * Register a method. @@ -124,7 +124,7 @@ extern int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime * @param len * @param bl */ -extern int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, bufferlist *bl); +extern int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, ceph::bufferlist *bl); /** * Write to the object. @@ -134,7 +134,7 @@ extern int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, bufferlist * @param len * @param bl */ -extern int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist *bl); +extern int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, ceph::bufferlist *bl); /** * Get xattr of the object. @@ -144,7 +144,7 @@ extern int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist * @param outbl */ extern int cls_cxx_getxattr(cls_method_context_t hctx, const char *name, - bufferlist *outbl); + ceph::bufferlist *outbl); /** * Set xattr of the object. @@ -154,7 +154,7 @@ extern int cls_cxx_getxattr(cls_method_context_t hctx, const char *name, * @param inbl */ extern int cls_cxx_setxattr(cls_method_context_t hctx, const char *name, - bufferlist *inbl); + ceph::bufferlist *inbl); /** * Get value corresponding to a key from the map. @@ -164,7 +164,7 @@ extern int cls_cxx_setxattr(cls_method_context_t hctx, const char *name, * @param outbl */ extern int cls_cxx_map_get_val(cls_method_context_t hctx, - const std::string &key, bufferlist *outbl); + const std::string &key, ceph::bufferlist *outbl); /** * Set value corresponding to a key in the map. @@ -174,7 +174,7 @@ extern int cls_cxx_map_get_val(cls_method_context_t hctx, * @param inbl */ extern int cls_cxx_map_set_val(cls_method_context_t hctx, - const std::string &key, bufferlist *inbl); + const std::string &key, ceph::bufferlist *inbl); #endif diff --git a/ceph/src/include/rbd/librbd.h b/ceph/src/include/rbd/librbd.h index 87d04eb44..dca8f4237 100644 --- a/ceph/src/include/rbd/librbd.h +++ b/ceph/src/include/rbd/librbd.h @@ -364,6 +364,10 @@ CEPH_RBD_API int rbd_update_features(rbd_image_t image, uint64_t features, CEPH_RBD_API int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit); CEPH_RBD_API int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count); + +CEPH_RBD_API int rbd_get_create_timestamp(rbd_image_t image, + struct timespec *timestamp); + CEPH_RBD_API int rbd_get_overlap(rbd_image_t image, uint64_t *overlap); CEPH_RBD_API int rbd_get_id(rbd_image_t image, char *id, size_t id_len); CEPH_RBD_API int rbd_get_block_name_prefix(rbd_image_t image, diff --git a/ceph/src/include/rbd/librbd.hpp b/ceph/src/include/rbd/librbd.hpp index f03ca9f36..b8e745692 100644 --- a/ceph/src/include/rbd/librbd.hpp +++ b/ceph/src/include/rbd/librbd.hpp @@ -297,6 +297,8 @@ public: uint64_t get_stripe_unit() const; uint64_t get_stripe_count() const; + int get_create_timestamp(struct timespec *timestamp); + int flatten(); int flatten_with_progress(ProgressContext &prog_ctx); /** diff --git a/ceph/src/include/types.h b/ceph/src/include/types.h index 788fa9b3c..deb794cbd 100644 --- a/ceph/src/include/types.h +++ b/ceph/src/include/types.h @@ -90,6 +90,29 @@ typedef off_t loff_t; // -- io helpers -- +// Forward declare all the I/O helpers so strict ADL can find them in +// the case of containers of containers. I'm tempted to abstract this +// stuff using template templates like I did for denc. + +template +inline ostream& operator<<(ostream&out, const pair& v); +template +inline ostream& operator<<(ostream& out, const vector& v); +template +inline ostream& operator<<(ostream& out, const deque& v); +template +inline ostream& operator<<(ostream&out, const boost::tuple &t); +template +inline ostream& operator<<(ostream& out, const list& ilist); +template +inline ostream& operator<<(ostream& out, const set& iset); +template +inline ostream& operator<<(ostream& out, const multiset& iset); +template +inline ostream& operator<<(ostream& out, const map& m); +template +inline ostream& operator<<(ostream& out, const multimap& m); + template inline ostream& operator<<(ostream& out, const pair& v) { return out << v.first << "," << v.second; @@ -395,7 +418,7 @@ enum health_status_t { }; #ifdef __cplusplus -inline ostream& operator<<(ostream &oss, health_status_t status) { +inline ostream& operator<<(ostream &oss, const health_status_t status) { switch (status) { case HEALTH_ERR: oss << "HEALTH_ERR"; @@ -451,10 +474,12 @@ WRITE_EQ_OPERATORS_1(shard_id_t, id) WRITE_CMP_OPERATORS_1(shard_id_t, id) ostream &operator<<(ostream &lhs, const shard_id_t &rhs); -#if defined(__sun) || defined(_AIX) || defined(DARWIN) -__s32 ceph_to_host_errno(__s32 e); +#if defined(__sun) || defined(_AIX) || defined(DARWIN) || defined(__FreeBSD__) +__s32 ceph_to_hostos_errno(__s32 e); +__s32 hostos_to_ceph_errno(__s32 e); #else -#define ceph_to_host_errno(e) (e) +#define ceph_to_hostos_errno(e) (e) +#define hostos_to_ceph_errno(e) (e) #endif struct errorcode32_t { @@ -470,11 +495,12 @@ struct errorcode32_t { } void encode(bufferlist &bl) const { - ::encode(code, bl); + __s32 newcode = hostos_to_ceph_errno(code); + ::encode(newcode, bl); } void decode(bufferlist::iterator &bl) { ::decode(code, bl); - code = ceph_to_host_errno(code); + code = ceph_to_hostos_errno(code); } }; WRITE_CLASS_ENCODER(errorcode32_t) diff --git a/ceph/src/journal/JournalRecorder.cc b/ceph/src/journal/JournalRecorder.cc index d0c6406a3..9c38758fc 100644 --- a/ceph/src/journal/JournalRecorder.cc +++ b/ceph/src/journal/JournalRecorder.cc @@ -6,6 +6,8 @@ #include "journal/Entry.h" #include "journal/Utils.h" +#include + #define dout_subsys ceph_subsys_journaler #undef dout_prefix #define dout_prefix *_dout << "JournalRecorder: " << this << " " @@ -19,7 +21,7 @@ namespace { struct C_Flush : public Context { JournalMetadataPtr journal_metadata; Context *on_finish; - atomic_t pending_flushes; + std::atomic pending_flushes = { 0 }; int ret_val; C_Flush(JournalMetadataPtr _journal_metadata, Context *_on_finish, @@ -32,7 +34,7 @@ struct C_Flush : public Context { if (r < 0 && ret_val == 0) { ret_val = r; } - if (pending_flushes.dec() == 0) { + if (--pending_flushes == 0) { // ensure all prior callback have been flushed as well journal_metadata->queue(on_finish, ret_val); delete this; diff --git a/ceph/src/journal/JournalRecorder.h b/ceph/src/journal/JournalRecorder.h index e27a4ee8f..a16339fad 100644 --- a/ceph/src/journal/JournalRecorder.h +++ b/ceph/src/journal/JournalRecorder.h @@ -5,7 +5,6 @@ #define CEPH_JOURNAL_JOURNAL_RECORDER_H #include "include/int_types.h" -#include "include/atomic.h" #include "include/Context.h" #include "include/rados/librados.hpp" #include "common/Mutex.h" diff --git a/ceph/src/json_spirit/json_spirit_value.h b/ceph/src/json_spirit/json_spirit_value.h index 62167e397..a4126369f 100644 --- a/ceph/src/json_spirit/json_spirit_value.h +++ b/ceph/src/json_spirit/json_spirit_value.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/ceph/src/kv/KeyValueDB.h b/ceph/src/kv/KeyValueDB.h index 9f454ac97..37a78480f 100644 --- a/ceph/src/kv/KeyValueDB.h +++ b/ceph/src/kv/KeyValueDB.h @@ -304,6 +304,10 @@ public: return -EOPNOTSUPP; } + virtual int set_cache_size(uint64_t) { + return -EOPNOTSUPP; + } + virtual ~KeyValueDB() {} /// compact the underlying store diff --git a/ceph/src/kv/LevelDBStore.cc b/ceph/src/kv/LevelDBStore.cc index 53840319c..450bd59e3 100644 --- a/ceph/src/kv/LevelDBStore.cc +++ b/ceph/src/kv/LevelDBStore.cc @@ -5,12 +5,18 @@ #include #include #include -#include "include/memory.h" -#include +#include + using std::string; + +#include "include/memory.h" + #include "common/debug.h" #include "common/perf_counters.h" +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" + #define dout_context cct #define dout_subsys ceph_subsys_leveldb #undef dout_prefix diff --git a/ceph/src/kv/LevelDBStore.h b/ceph/src/kv/LevelDBStore.h index 7ce87ecc4..be344ff18 100644 --- a/ceph/src/kv/LevelDBStore.h +++ b/ceph/src/kv/LevelDBStore.h @@ -29,6 +29,9 @@ #include "common/ceph_context.h" +// reinclude our assert to clobber the system one +# include "include/assert.h" + class PerfCounters; enum { diff --git a/ceph/src/kv/RocksDBStore.cc b/ceph/src/kv/RocksDBStore.cc index a53517942..0ea96ca12 100644 --- a/ceph/src/kv/RocksDBStore.cc +++ b/ceph/src/kv/RocksDBStore.cc @@ -34,6 +34,17 @@ using std::string; #undef dout_prefix #define dout_prefix *_dout << "rocksdb: " +static rocksdb::SliceParts prepare_sliceparts(const bufferlist &bl, rocksdb::Slice *slices) +{ + unsigned n = 0; + for (std::list::const_iterator p = bl.buffers().begin(); + p != bl.buffers().end(); ++p, ++n) { + slices[n].data_ = p->c_str(); + slices[n].size_ = p->length(); + } + return rocksdb::SliceParts(slices, n); +} + // // One of these per rocksdb instance, implements the merge operator prefix stuff // @@ -286,18 +297,44 @@ int RocksDBStore::do_open(ostream &out, bool create_if_missing) opt.env = static_cast(priv); } - auto cache = rocksdb::NewLRUCache(g_conf->rocksdb_cache_size, g_conf->rocksdb_cache_shard_bits); + // caches + if (!cache_size) { + cache_size = g_conf->rocksdb_cache_size; + } + uint64_t row_cache_size = cache_size * g_conf->rocksdb_cache_row_ratio; + uint64_t block_cache_size = cache_size - row_cache_size; + if (g_conf->rocksdb_cache_type == "lru") { + bbt_opts.block_cache = rocksdb::NewLRUCache( + block_cache_size, + g_conf->rocksdb_cache_shard_bits); + } else if (g_conf->rocksdb_cache_type == "clock") { + bbt_opts.block_cache = rocksdb::NewClockCache( + block_cache_size, + g_conf->rocksdb_cache_shard_bits); + } else { + derr << "unrecognized rocksdb_cache_type '" << g_conf->rocksdb_cache_type + << "'" << dendl; + return -EINVAL; + } bbt_opts.block_size = g_conf->rocksdb_block_size; - bbt_opts.block_cache = cache; + + opt.row_cache = rocksdb::NewLRUCache(row_cache_size, + g_conf->rocksdb_cache_shard_bits); + if (g_conf->kstore_rocksdb_bloom_bits_per_key > 0) { dout(10) << __func__ << " set bloom filter bits per key to " << g_conf->kstore_rocksdb_bloom_bits_per_key << dendl; - bbt_opts.filter_policy.reset(rocksdb::NewBloomFilterPolicy(g_conf->kstore_rocksdb_bloom_bits_per_key)); + bbt_opts.filter_policy.reset(rocksdb::NewBloomFilterPolicy( + g_conf->kstore_rocksdb_bloom_bits_per_key)); } opt.table_factory.reset(rocksdb::NewBlockBasedTableFactory(bbt_opts)); - dout(10) << __func__ << " set block size to " << g_conf->rocksdb_block_size - << " cache size to " << g_conf->rocksdb_cache_size - << " num of cache shards to " << (1 << g_conf->rocksdb_cache_shard_bits) << dendl; + dout(10) << __func__ << " block size " << g_conf->rocksdb_block_size + << ", block_cache size " << prettybyte_t(block_cache_size) + << ", row_cache size " << prettybyte_t(row_cache_size) + << "; shards " + << (1 << g_conf->rocksdb_cache_shard_bits) + << ", type " << g_conf->rocksdb_cache_type + << dendl; opt.merge_operator.reset(new MergeOperatorRouter(*this)); status = rocksdb::DB::Open(opt, path, &db); @@ -561,10 +598,10 @@ void RocksDBStore::RocksDBTransactionImpl::set( rocksdb::Slice(to_set_bl.buffers().front().c_str(), to_set_bl.length())); } else { - // make a copy - bufferlist val = to_set_bl; - bat.Put(rocksdb::Slice(key), - rocksdb::Slice(val.c_str(), val.length())); + rocksdb::Slice key_slice(key); + rocksdb::Slice value_slices[to_set_bl.buffers().size()]; + bat.Put(nullptr, rocksdb::SliceParts(&key_slice, 1), + prepare_sliceparts(to_set_bl, value_slices)); } } @@ -582,10 +619,10 @@ void RocksDBStore::RocksDBTransactionImpl::set( rocksdb::Slice(to_set_bl.buffers().front().c_str(), to_set_bl.length())); } else { - // make a copy - bufferlist val = to_set_bl; - bat.Put(rocksdb::Slice(key), - rocksdb::Slice(val.c_str(), val.length())); + rocksdb::Slice key_slice(key); + rocksdb::Slice value_slices[to_set_bl.buffers().size()]; + bat.Put(nullptr, rocksdb::SliceParts(&key_slice, 1), + prepare_sliceparts(to_set_bl, value_slices)); } } @@ -612,11 +649,18 @@ void RocksDBStore::RocksDBTransactionImpl::rm_single_key(const string &prefix, void RocksDBStore::RocksDBTransactionImpl::rmkeys_by_prefix(const string &prefix) { - KeyValueDB::Iterator it = db->get_iterator(prefix); - for (it->seek_to_first(); - it->valid(); - it->next()) { - bat.Delete(combine_strings(prefix, it->key())); + if (db->enable_rmrange) { + string endprefix = prefix; + endprefix.push_back('\x01'); + bat.DeleteRange(combine_strings(prefix, string()), + combine_strings(endprefix, string())); + } else { + KeyValueDB::Iterator it = db->get_iterator(prefix); + for (it->seek_to_first(); + it->valid(); + it->next()) { + bat.Delete(combine_strings(prefix, it->key())); + } } } @@ -653,9 +697,10 @@ void RocksDBStore::RocksDBTransactionImpl::merge( to_set_bl.length())); } else { // make a copy - bufferlist val = to_set_bl; - bat.Merge(rocksdb::Slice(key), - rocksdb::Slice(val.c_str(), val.length())); + rocksdb::Slice key_slice(key); + rocksdb::Slice value_slices[to_set_bl.buffers().size()]; + bat.Merge(nullptr, rocksdb::SliceParts(&key_slice, 1), + prepare_sliceparts(to_set_bl, value_slices)); } } diff --git a/ceph/src/kv/RocksDBStore.h b/ceph/src/kv/RocksDBStore.h index 4d25408a5..c437badeb 100644 --- a/ceph/src/kv/RocksDBStore.h +++ b/ceph/src/kv/RocksDBStore.h @@ -75,6 +75,8 @@ class RocksDBStore : public KeyValueDB { rocksdb::BlockBasedTableOptions bbt_opts; string options_str; + uint64_t cache_size = 0; + int do_open(ostream &out, bool create_if_missing); // manage async compactions @@ -435,6 +437,10 @@ err: return total_size; } + int set_cache_size(uint64_t s) override { + cache_size = s; + return 0; + } protected: WholeSpaceIterator _get_iterator() override; diff --git a/ceph/src/librados/IoCtxImpl.cc b/ceph/src/librados/IoCtxImpl.cc index 4102df1c0..d0d5a1ae5 100644 --- a/ceph/src/librados/IoCtxImpl.cc +++ b/ceph/src/librados/IoCtxImpl.cc @@ -770,7 +770,7 @@ int librados::IoCtxImpl::aio_operate_read(const object_t &oid, AioCompletionImpl *c, int flags, bufferlist *pbl, - const blkin_trace_info *trace_info) + const blkin_trace_info *trace_info) { FUNCTRACE(); Context *oncomplete = new C_aio_Complete(c); @@ -782,8 +782,10 @@ int librados::IoCtxImpl::aio_operate_read(const object_t &oid, c->io = this; ZTracer::Trace trace; - if (trace_info) - trace.init("rados operate read", &objecter->trace_endpoint, trace_info); + if (trace_info) { + ZTracer::Trace parent_trace("", nullptr, trace_info); + trace.init("rados operate read", &objecter->trace_endpoint, &parent_trace); + } trace.event("init root span"); Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc, @@ -798,7 +800,7 @@ int librados::IoCtxImpl::aio_operate_read(const object_t &oid, int librados::IoCtxImpl::aio_operate(const object_t& oid, ::ObjectOperation *o, AioCompletionImpl *c, const SnapContext& snap_context, int flags, - const blkin_trace_info *trace_info) + const blkin_trace_info *trace_info) { FUNCTRACE(); OID_EVENT_TRACE(oid.name.c_str(), "RADOS_WRITE_OP_BEGIN"); @@ -816,8 +818,10 @@ int librados::IoCtxImpl::aio_operate(const object_t& oid, queue_aio_write(c); ZTracer::Trace trace; - if (trace_info) - trace.init("rados operate", &objecter->trace_endpoint, trace_info); + if (trace_info) { + ZTracer::Trace parent_trace("", nullptr, trace_info); + trace.init("rados operate", &objecter->trace_endpoint, &parent_trace); + } trace.event("init root span"); Objecter::Op *op = objecter->prepare_mutate_op( diff --git a/ceph/src/librados/IoCtxImpl.h b/ceph/src/librados/IoCtxImpl.h index 7870b8317..633cf9f7b 100644 --- a/ceph/src/librados/IoCtxImpl.h +++ b/ceph/src/librados/IoCtxImpl.h @@ -15,11 +15,12 @@ #ifndef CEPH_LIBRADOS_IOCTXIMPL_H #define CEPH_LIBRADOS_IOCTXIMPL_H +#include + #include "common/Cond.h" #include "common/Mutex.h" #include "common/snap_types.h" #include "common/zipkin_trace.h" -#include "include/atomic.h" #include "include/types.h" #include "include/rados/librados.h" #include "include/rados/librados.hpp" @@ -30,7 +31,7 @@ class RadosClient; struct librados::IoCtxImpl { - atomic_t ref_cnt; + std::atomic ref_cnt = { 0 }; RadosClient *client; int64_t poolid; snapid_t snap_seq; @@ -69,11 +70,11 @@ struct librados::IoCtxImpl { int set_snap_write_context(snapid_t seq, vector& snaps); void get() { - ref_cnt.inc(); + ref_cnt++; } void put() { - if (ref_cnt.dec() == 0) + if (--ref_cnt == 0) delete this; } diff --git a/ceph/src/librados/RadosClient.cc b/ceph/src/librados/RadosClient.cc index 3e0de3ade..e3215c96a 100644 --- a/ceph/src/librados/RadosClient.cc +++ b/ceph/src/librados/RadosClient.cc @@ -77,7 +77,7 @@ librados::RadosClient::RadosClient(CephContext *cct_) lock("librados::RadosClient::lock"), timer(cct, lock), refcnt(1), - log_last_version(0), log_cb(NULL), log_cb_arg(NULL), + log_last_version(0), log_cb(NULL), log_cb2(NULL), log_cb_arg(NULL), finisher(cct, "radosclient", "fn-radosclient") { } @@ -351,7 +351,7 @@ void librados::RadosClient::shutdown() } bool need_objecter = false; - if (objecter && objecter->initialized.read()) { + if (objecter && objecter->initialized) { need_objecter = true; } @@ -920,7 +920,10 @@ int librados::RadosClient::pg_command(pg_t pgid, vector& cmd, return ret; } -int librados::RadosClient::monitor_log(const string& level, rados_log_callback_t cb, void *arg) +int librados::RadosClient::monitor_log(const string& level, + rados_log_callback_t cb, + rados_log_callback2_t cb2, + void *arg) { Mutex::Locker l(lock); @@ -928,12 +931,14 @@ int librados::RadosClient::monitor_log(const string& level, rados_log_callback_t return -ENOTCONN; } - if (cb == NULL) { + if (cb == NULL && cb2 == NULL) { // stop watch - ldout(cct, 10) << __func__ << " removing cb " << (void*)log_cb << dendl; + ldout(cct, 10) << __func__ << " removing cb " << (void*)log_cb + << " " << (void*)log_cb2 << dendl; monclient.sub_unwant(log_watch); log_watch.clear(); log_cb = NULL; + log_cb2 = NULL; log_cb_arg = NULL; return 0; } @@ -954,15 +959,17 @@ int librados::RadosClient::monitor_log(const string& level, rados_log_callback_t return -EINVAL; } - if (log_cb) + if (log_cb || log_cb2) monclient.sub_unwant(log_watch); // (re)start watch - ldout(cct, 10) << __func__ << " add cb " << (void*)cb << " level " << level << dendl; + ldout(cct, 10) << __func__ << " add cb " << (void*)cb << " " << (void*)cb2 + << " level " << level << dendl; monclient.sub_want(watch_level, 0, 0); monclient.renew_subs(); log_cb = cb; + log_cb2 = cb2; log_cb_arg = arg; log_watch = watch_level; return 0; @@ -976,21 +983,27 @@ void librados::RadosClient::handle_log(MLog *m) if (log_last_version < m->version) { log_last_version = m->version; - if (log_cb) { + if (log_cb || log_cb2) { for (std::deque::iterator it = m->entries.begin(); it != m->entries.end(); ++it) { LogEntry e = *it; ostringstream ss; - ss << e.stamp << " " << e.who.name << " " << e.prio << " " << e.msg; + ss << e.stamp << " " << e.name << " " << e.prio << " " << e.msg; string line = ss.str(); string who = stringify(e.who); + string name = stringify(e.name); string level = stringify(e.prio); struct timespec stamp; e.stamp.to_timespec(&stamp); ldout(cct, 20) << __func__ << " delivering " << ss.str() << dendl; - log_cb(log_cb_arg, line.c_str(), who.c_str(), - stamp.tv_sec, stamp.tv_nsec, - e.seq, level.c_str(), e.msg.c_str()); + if (log_cb) + log_cb(log_cb_arg, line.c_str(), who.c_str(), + stamp.tv_sec, stamp.tv_nsec, + e.seq, level.c_str(), e.msg.c_str()); + if (log_cb2) + log_cb2(log_cb_arg, line.c_str(), who.c_str(), name.c_str(), + stamp.tv_sec, stamp.tv_nsec, + e.seq, level.c_str(), e.msg.c_str()); } } diff --git a/ceph/src/librados/RadosClient.h b/ceph/src/librados/RadosClient.h index 39e9a4957..b3f301631 100644 --- a/ceph/src/librados/RadosClient.h +++ b/ceph/src/librados/RadosClient.h @@ -74,6 +74,7 @@ private: version_t log_last_version; rados_log_callback_t log_cb; + rados_log_callback2_t log_cb2; void *log_cb_arg; string log_watch; @@ -144,7 +145,8 @@ public: bufferlist *poutbl, string *prs); void handle_log(MLog *m); - int monitor_log(const string& level, rados_log_callback_t cb, void *arg); + int monitor_log(const string& level, rados_log_callback_t cb, + rados_log_callback2_t cb2, void *arg); void get(); bool put(); diff --git a/ceph/src/librados/RadosXattrIter.h b/ceph/src/librados/RadosXattrIter.h index 35c870438..6b232bd58 100644 --- a/ceph/src/librados/RadosXattrIter.h +++ b/ceph/src/librados/RadosXattrIter.h @@ -18,7 +18,7 @@ #include #include -#include "include/buffer.h" +#include "include/buffer.h" // for bufferlist namespace librados { diff --git a/ceph/src/librados/librados.cc b/ceph/src/librados/librados.cc index e7e75605d..1438952f8 100644 --- a/ceph/src/librados/librados.cc +++ b/ceph/src/librados/librados.cc @@ -605,6 +605,15 @@ void librados::ObjectReadOperation::cache_evict() o->cache_evict(); } +void librados::ObjectWriteOperation::set_redirect(const std::string& tgt_obj, + const IoCtx& tgt_ioctx, + uint64_t tgt_version) +{ + ::ObjectOperation *o = &impl->o; + o->set_redirect(object_t(tgt_obj), tgt_ioctx.io_ctx_impl->snap_seq, + tgt_ioctx.io_ctx_impl->oloc, tgt_version); +} + void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl) { ::ObjectOperation *o = &impl->o; @@ -1472,6 +1481,8 @@ static int translate_flags(int flags) op_flags |= CEPH_OSD_FLAG_FULL_TRY; if (flags & librados::OPERATION_FULL_FORCE) op_flags |= CEPH_OSD_FLAG_FULL_FORCE; + if (flags & librados::OPERATION_IGNORE_REDIRECT) + op_flags |= CEPH_OSD_FLAG_IGNORE_REDIRECT; return op_flags; } @@ -3364,11 +3375,21 @@ extern "C" int rados_monitor_log(rados_t cluster, const char *level, rados_log_c { tracepoint(librados, rados_monitor_log_enter, cluster, level, cb, arg); librados::RadosClient *client = (librados::RadosClient *)cluster; - int retval = client->monitor_log(level, cb, arg); + int retval = client->monitor_log(level, cb, nullptr, arg); tracepoint(librados, rados_monitor_log_exit, retval); return retval; } +extern "C" int rados_monitor_log2(rados_t cluster, const char *level, + rados_log_callback2_t cb, void *arg) +{ + tracepoint(librados, rados_monitor_log2_enter, cluster, level, cb, arg); + librados::RadosClient *client = (librados::RadosClient *)cluster; + int retval = client->monitor_log(level, nullptr, cb, arg); + tracepoint(librados, rados_monitor_log2_exit, retval); + return retval; +} + extern "C" int rados_ioctx_create(rados_t cluster, const char *name, rados_ioctx_t *io) { tracepoint(librados, rados_ioctx_create_enter, cluster, name); diff --git a/ceph/src/libradosstriper/RadosStriperImpl.h b/ceph/src/libradosstriper/RadosStriperImpl.h index 9ac7da0e3..332c37536 100644 --- a/ceph/src/libradosstriper/RadosStriperImpl.h +++ b/ceph/src/libradosstriper/RadosStriperImpl.h @@ -17,8 +17,6 @@ #include -#include "include/atomic.h" - #include "include/rados/librados.h" #include "include/rados/librados.hpp" #include "include/radosstriper/libradosstriper.h" diff --git a/ceph/src/librbd/CMakeLists.txt b/ceph/src/librbd/CMakeLists.txt index 52cfbd8ac..e596bd5f4 100644 --- a/ceph/src/librbd/CMakeLists.txt +++ b/ceph/src/librbd/CMakeLists.txt @@ -6,7 +6,6 @@ add_library(rbd_types STATIC set(librbd_internal_srcs AsyncObjectThrottle.cc - AsyncOperation.cc AsyncRequest.cc ExclusiveLock.cc ImageCtx.cc @@ -44,6 +43,7 @@ set(librbd_internal_srcs image/SetSnapRequest.cc image_watcher/NotifyLockOwner.cc io/AioCompletion.cc + io/AsyncOperation.cc io/CopyupRequest.cc io/ImageRequest.cc io/ImageRequestWQ.cc diff --git a/ceph/src/librbd/ExclusiveLock.cc b/ceph/src/librbd/ExclusiveLock.cc index 19ca6e42e..a3d69fce8 100644 --- a/ceph/src/librbd/ExclusiveLock.cc +++ b/ceph/src/librbd/ExclusiveLock.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "librbd/ExclusiveLock.h" +#include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/ImageState.h" #include "librbd/exclusive_lock/PreAcquireRequest.h" @@ -42,12 +43,28 @@ bool ExclusiveLock::accept_requests(int *ret_val) const { bool accept_requests = (!ML::is_state_shutdown() && ML::is_state_locked() && m_request_blocked_count == 0); - *ret_val = m_request_blocked_ret_val; + if (ret_val != nullptr) { + *ret_val = m_request_blocked_ret_val; + } ldout(m_image_ctx.cct, 20) << "=" << accept_requests << dendl; return accept_requests; } +template +bool ExclusiveLock::accept_ops() const { + Mutex::Locker locker(ML::m_lock); + bool accept = accept_ops(ML::m_lock); + ldout(m_image_ctx.cct, 20) << "=" << accept << dendl; + return accept; +} + +template +bool ExclusiveLock::accept_ops(const Mutex &lock) const { + return (!ML::is_state_shutdown() && + (ML::is_state_locked() || ML::is_state_post_acquiring())); +} + template void ExclusiveLock::block_requests(int r) { Mutex::Locker locker(ML::m_lock); @@ -111,9 +128,24 @@ void ExclusiveLock::handle_peer_notification(int r) { ML::execute_next_action(); } +template +Context *ExclusiveLock::start_op() { + assert(m_image_ctx.owner_lock.is_locked()); + Mutex::Locker locker(ML::m_lock); + + if (!accept_ops(ML::m_lock)) { + return nullptr; + } + + m_async_op_tracker.start_op(); + return new FunctionContext([this](int r) { + m_async_op_tracker.finish_op(); + }); +} + template void ExclusiveLock::handle_init_complete(uint64_t features) { - ldout(m_image_ctx.cct, 10) << "features=" << features << dendl; + ldout(m_image_ctx.cct, 10) << ": features=" << features << dendl; if ((features & RBD_FEATURE_JOURNALING) != 0) { m_image_ctx.io_work_queue->set_require_lock_on_read(); @@ -251,7 +283,7 @@ void ExclusiveLock::pre_release_lock_handler(bool shutting_down, Mutex::Locker locker(ML::m_lock); PreReleaseRequest *req = PreReleaseRequest::create( - m_image_ctx, shutting_down, on_finish); + m_image_ctx, shutting_down, m_async_op_tracker, on_finish); m_image_ctx.op_work_queue->queue(new FunctionContext([req](int r) { req->send(); })); @@ -293,6 +325,16 @@ void ExclusiveLock::post_release_lock_handler(bool shutting_down, int r, on_finish->complete(r); } +template +void ExclusiveLock::post_reacquire_lock_handler(int r, Context *on_finish) { + ldout(m_image_ctx.cct, 10) << dendl; + if (r >= 0) { + m_image_ctx.image_watcher->notify_acquired_lock(); + } + + on_finish->complete(r); +} + template struct ExclusiveLock::C_InitComplete : public Context { ExclusiveLock *exclusive_lock; diff --git a/ceph/src/librbd/ExclusiveLock.h b/ceph/src/librbd/ExclusiveLock.h index 092f7094a..0aaad091e 100644 --- a/ceph/src/librbd/ExclusiveLock.h +++ b/ceph/src/librbd/ExclusiveLock.h @@ -5,7 +5,7 @@ #define CEPH_LIBRBD_EXCLUSIVE_LOCK_H #include "librbd/ManagedLock.h" -#include "librbd/ImageCtx.h" +#include "common/AsyncOpTracker.h" namespace librbd { @@ -18,7 +18,8 @@ public: ExclusiveLock(ImageCtxT &image_ctx); - bool accept_requests(int *ret_val) const; + bool accept_requests(int *ret_val = nullptr) const; + bool accept_ops() const; void block_requests(int r); void unblock_requests(); @@ -28,6 +29,8 @@ public: void handle_peer_notification(int r); + Context *start_op(); + protected: void shutdown_handler(int r, Context *on_finish) override; void pre_acquire_lock_handler(Context *on_finish) override; @@ -36,6 +39,7 @@ protected: Context *on_finish) override; void post_release_lock_handler(bool shutting_down, int r, Context *on_finish) override; + void post_reacquire_lock_handler(int r, Context *on_finish) override; private: @@ -82,11 +86,15 @@ private: ImageCtxT& m_image_ctx; Context *m_pre_post_callback = nullptr; + AsyncOpTracker m_async_op_tracker; + uint32_t m_request_blocked_count = 0; int m_request_blocked_ret_val = 0; int m_acquire_lock_peer_ret_val = 0; + bool accept_ops(const Mutex &lock) const; + void handle_init_complete(uint64_t features); void handle_post_acquiring_lock(int r); void handle_post_acquired_lock(int r); diff --git a/ceph/src/librbd/ImageCtx.cc b/ceph/src/librbd/ImageCtx.cc index 9ea00a1bc..fd2333ee1 100644 --- a/ceph/src/librbd/ImageCtx.cc +++ b/ceph/src/librbd/ImageCtx.cc @@ -11,7 +11,6 @@ #include "common/WorkQueue.h" #include "common/Timer.h" -#include "librbd/AsyncOperation.h" #include "librbd/AsyncRequest.h" #include "librbd/ExclusiveLock.h" #include "librbd/internal.h" @@ -28,6 +27,7 @@ #include "librbd/exclusive_lock/AutomaticPolicy.h" #include "librbd/exclusive_lock/StandardPolicy.h" #include "librbd/io/AioCompletion.h" +#include "librbd/io/AsyncOperation.h" #include "librbd/io/ImageRequestWQ.h" #include "librbd/journal/StandardPolicy.h" @@ -198,7 +198,8 @@ struct C_InvalidateCache : public Context { operations(new Operations<>(*this)), exclusive_lock(nullptr), object_map(nullptr), io_work_queue(nullptr), op_work_queue(nullptr), - asok_hook(nullptr) + asok_hook(nullptr), + trace_endpoint("librbd") { md_ctx.dup(p); data_ctx.dup(p); @@ -269,6 +270,7 @@ struct C_InvalidateCache : public Context { pname += snap_name; } + trace_endpoint.copy_name(pname); perf_start(pname); if (cache) { @@ -525,6 +527,11 @@ struct C_InvalidateCache : public Context { return stripe_count * (1ull << order); } + utime_t ImageCtx::get_create_timestamp() const + { + return create_timestamp; + } + int ImageCtx::is_snap_protected(snap_t in_snap_id, bool *is_protected) const { @@ -627,18 +634,23 @@ struct C_InvalidateCache : public Context { return -ENOENT; } - bool ImageCtx::test_flags(uint64_t flags) const + int ImageCtx::test_flags(uint64_t flags, bool *flags_set) const { RWLock::RLocker l(snap_lock); - return test_flags(flags, snap_lock); + return test_flags(flags, snap_lock, flags_set); } - bool ImageCtx::test_flags(uint64_t flags, const RWLock &in_snap_lock) const + int ImageCtx::test_flags(uint64_t flags, const RWLock &in_snap_lock, + bool *flags_set) const { assert(snap_lock.is_locked()); uint64_t snap_flags; - get_flags(snap_id, &snap_flags); - return ((snap_flags & flags) == flags); + int r = get_flags(snap_id, &snap_flags); + if (r < 0) { + return r; + } + *flags_set = ((snap_flags & flags) == flags); + return 0; } int ImageCtx::update_flags(snap_t in_snap_id, uint64_t flag, bool enabled) @@ -713,7 +725,7 @@ struct C_InvalidateCache : public Context { void ImageCtx::aio_read_from_cache(object_t o, uint64_t object_no, bufferlist *bl, size_t len, uint64_t off, Context *onfinish, - int fadvise_flags) { + int fadvise_flags, ZTracer::Trace *trace) { snap_lock.get_read(); ObjectCacher::OSDRead *rd = object_cacher->prepare_read(snap_id, bl, fadvise_flags); snap_lock.put_read(); @@ -722,7 +734,7 @@ struct C_InvalidateCache : public Context { extent.buffer_extents.push_back(make_pair(0, len)); rd->extents.push_back(extent); cache_lock.Lock(); - int r = object_cacher->readx(rd, object_set, onfinish); + int r = object_cacher->readx(rd, object_set, onfinish, trace); cache_lock.Unlock(); if (r != 0) onfinish->complete(r); @@ -730,7 +742,8 @@ struct C_InvalidateCache : public Context { void ImageCtx::write_to_cache(object_t o, const bufferlist& bl, size_t len, uint64_t off, Context *onfinish, - int fadvise_flags, uint64_t journal_tid) { + int fadvise_flags, uint64_t journal_tid, + ZTracer::Trace *trace) { snap_lock.get_read(); ObjectCacher::OSDWrite *wr = object_cacher->prepare_write( snapc, bl, ceph::real_time::min(), fadvise_flags, journal_tid); @@ -743,7 +756,7 @@ struct C_InvalidateCache : public Context { wr->extents.push_back(extent); { Mutex::Locker l(cache_lock); - object_cacher->writex(wr, object_set, onfinish); + object_cacher->writex(wr, object_set, onfinish, trace); } } diff --git a/ceph/src/librbd/ImageCtx.h b/ceph/src/librbd/ImageCtx.h index b85974224..99a02748e 100644 --- a/ceph/src/librbd/ImageCtx.h +++ b/ceph/src/librbd/ImageCtx.h @@ -15,6 +15,7 @@ #include "common/Readahead.h" #include "common/RWLock.h" #include "common/snap_types.h" +#include "common/zipkin_trace.h" #include "include/buffer_fwd.h" #include "include/rbd/librbd.hpp" @@ -37,7 +38,6 @@ class SafeTimer; namespace librbd { - class AsyncOperation; template class ExclusiveLock; template class ImageState; template class ImageWatcher; @@ -51,6 +51,7 @@ namespace librbd { namespace exclusive_lock { struct Policy; } namespace io { class AioCompletion; + class AsyncOperation; class ImageRequestWQ; class CopyupRequest; } @@ -127,6 +128,7 @@ namespace librbd { cls::rbd::GroupSpec group_spec; uint64_t stripe_unit, stripe_count; uint64_t flags; + utime_t create_timestamp; file_layout_t layout; @@ -140,7 +142,7 @@ namespace librbd { std::map copyup_list; - xlist async_ops; + xlist async_ops; xlist*> async_requests; std::list async_requests_waiters; @@ -200,6 +202,8 @@ namespace librbd { exclusive_lock::Policy *exclusive_lock_policy = nullptr; journal::Policy *journal_policy = nullptr; + ZTracer::Endpoint trace_endpoint; + static bool _filter_metadata_confs(const string &prefix, std::map &configs, const map &pairs, map *res); @@ -251,6 +255,7 @@ namespace librbd { uint64_t get_stripe_unit() const; uint64_t get_stripe_count() const; uint64_t get_stripe_period() const; + utime_t get_create_timestamp() const; void add_snap(cls::rbd::SnapshotNamespace in_snap_namespace, std::string in_snap_name, @@ -266,8 +271,9 @@ namespace librbd { bool test_features(uint64_t test_features, const RWLock &in_snap_lock) const; int get_flags(librados::snap_t in_snap_id, uint64_t *flags) const; - bool test_flags(uint64_t test_flags) const; - bool test_flags(uint64_t test_flags, const RWLock &in_snap_lock) const; + int test_flags(uint64_t test_flags, bool *flags_set) const; + int test_flags(uint64_t test_flags, const RWLock &in_snap_lock, + bool *flags_set) const; int update_flags(librados::snap_t in_snap_id, uint64_t flag, bool enabled); const ParentInfo* get_parent_info(librados::snap_t in_snap_id) const; @@ -278,10 +284,10 @@ namespace librbd { uint64_t *overlap) const; void aio_read_from_cache(object_t o, uint64_t object_no, bufferlist *bl, size_t len, uint64_t off, Context *onfinish, - int fadvise_flags); + int fadvise_flags, ZTracer::Trace *trace); void write_to_cache(object_t o, const bufferlist& bl, size_t len, uint64_t off, Context *onfinish, int fadvise_flags, - uint64_t journal_tid); + uint64_t journal_tid, ZTracer::Trace *trace); void user_flushed(); void flush_cache(Context *onfinish); void shut_down_cache(Context *on_finish); diff --git a/ceph/src/librbd/ImageWatcher.cc b/ceph/src/librbd/ImageWatcher.cc index 0e85a6a4c..ca612a9de 100644 --- a/ceph/src/librbd/ImageWatcher.cc +++ b/ceph/src/librbd/ImageWatcher.cc @@ -33,6 +33,32 @@ using librbd::watcher::util::HandlePayloadVisitor; static const double RETRY_DELAY_SECONDS = 1.0; +template +struct ImageWatcher::C_ProcessPayload : public Context { + ImageWatcher *image_watcher; + uint64_t notify_id; + uint64_t handle; + watch_notify::Payload payload; + + C_ProcessPayload(ImageWatcher *image_watcher_, uint64_t notify_id_, + uint64_t handle_, const watch_notify::Payload &payload) + : image_watcher(image_watcher_), notify_id(notify_id_), handle(handle_), + payload(payload) { + } + + void finish(int r) override { + image_watcher->m_async_op_tracker.start_op(); + if (image_watcher->notifications_blocked()) { + // requests are blocked -- just ack the notification + bufferlist bl; + image_watcher->acknowledge_notify(notify_id, handle, bl); + } else { + image_watcher->process_payload(notify_id, handle, payload); + } + image_watcher->m_async_op_tracker.finish_op(); + } +}; + template ImageWatcher::ImageWatcher(I &image_ctx) : Watcher(image_ctx.md_ctx, image_ctx.op_work_queue, image_ctx.header_oid), @@ -62,6 +88,18 @@ void ImageWatcher::unregister_watch(Context *on_finish) { Watcher::unregister_watch(ctx); } +template +void ImageWatcher::block_notifies(Context *on_finish) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + on_finish = new FunctionContext([this, on_finish](int r) { + cancel_async_requests(); + on_finish->complete(r); + }); + Watcher::block_notifies(on_finish); +} + template void ImageWatcher::schedule_async_progress(const AsyncRequestId &request, uint64_t offset, uint64_t total) { @@ -884,15 +922,9 @@ bool ImageWatcher::handle_payload(const UnknownPayload &payload, template void ImageWatcher::process_payload(uint64_t notify_id, uint64_t handle, - const Payload &payload, int r) { - if (r < 0) { - bufferlist out_bl; - this->acknowledge_notify(notify_id, handle, out_bl); - } else { - apply_visitor(HandlePayloadVisitor>(this, notify_id, - handle), - payload); - } + const Payload &payload) { + apply_visitor(HandlePayloadVisitor>(this, notify_id, handle), + payload); } template @@ -919,7 +951,7 @@ void ImageWatcher::handle_notify(uint64_t notify_id, uint64_t handle, m_image_ctx.state->refresh(new C_ProcessPayload(this, notify_id, handle, notify_message.payload)); } else { - process_payload(notify_id, handle, notify_message.payload, 0); + process_payload(notify_id, handle, notify_message.payload); } } diff --git a/ceph/src/librbd/ImageWatcher.h b/ceph/src/librbd/ImageWatcher.h index 838e0e3d0..5e30c8e5b 100644 --- a/ceph/src/librbd/ImageWatcher.h +++ b/ceph/src/librbd/ImageWatcher.h @@ -36,7 +36,8 @@ public: ImageWatcher(ImageCtxT& image_ctx); ~ImageWatcher() override; - void unregister_watch(Context *on_finish); + void unregister_watch(Context *on_finish) override; + void block_notifies(Context *on_finish) override; void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx, Context *on_finish); @@ -145,23 +146,7 @@ private: ProgressContext *m_prog_ctx; }; - struct C_ProcessPayload : public Context { - ImageWatcher *image_watcher; - uint64_t notify_id; - uint64_t handle; - watch_notify::Payload payload; - - C_ProcessPayload(ImageWatcher *image_watcher_, uint64_t notify_id_, - uint64_t handle_, const watch_notify::Payload &payload) - : image_watcher(image_watcher_), notify_id(notify_id_), handle(handle_), - payload(payload) { - } - - void finish(int r) override { - image_watcher->process_payload(notify_id, handle, payload, r); - } - }; - + struct C_ProcessPayload; struct C_ResponseMessage : public Context { C_NotifyAck *notify_ack; @@ -251,7 +236,7 @@ private: bool handle_payload(const watch_notify::UnknownPayload& payload, C_NotifyAck *ctx); void process_payload(uint64_t notify_id, uint64_t handle, - const watch_notify::Payload &payload, int r); + const watch_notify::Payload &payload); void handle_notify(uint64_t notify_id, uint64_t handle, uint64_t notifier_id, bufferlist &bl) override; diff --git a/ceph/src/librbd/Journal.cc b/ceph/src/librbd/Journal.cc index c19a6a80c..aa73cdedd 100644 --- a/ceph/src/librbd/Journal.cc +++ b/ceph/src/librbd/Journal.cc @@ -1332,9 +1332,11 @@ void Journal::handle_replay_process_safe(ReplayEntry replay_entry, int r) { ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl; if (r < 0) { - lderr(cct) << this << " " << __func__ << ": " - << "failed to commit journal event to disk: " << cpp_strerror(r) - << dendl; + if (r != -ECANCELED) { + lderr(cct) << this << " " << __func__ << ": " + << "failed to commit journal event to disk: " + << cpp_strerror(r) << dendl; + } if (m_state == STATE_REPLAYING) { // abort the replay if we have an error diff --git a/ceph/src/librbd/LibrbdWriteback.cc b/ceph/src/librbd/LibrbdWriteback.cc index f9292caba..d1dc08c31 100644 --- a/ceph/src/librbd/LibrbdWriteback.cc +++ b/ceph/src/librbd/LibrbdWriteback.cc @@ -70,8 +70,8 @@ namespace librbd { class C_OrderedWrite : public Context { public: C_OrderedWrite(CephContext *cct, LibrbdWriteback::write_result_d *result, - LibrbdWriteback *wb) - : m_cct(cct), m_result(result), m_wb_handler(wb) {} + const ZTracer::Trace &trace, LibrbdWriteback *wb) + : m_cct(cct), m_result(result), m_trace(trace), m_wb_handler(wb) {} ~C_OrderedWrite() override {} void finish(int r) override { ldout(m_cct, 20) << "C_OrderedWrite completing " << m_result << dendl; @@ -83,10 +83,12 @@ namespace librbd { m_wb_handler->complete_writes(m_result->oid); } ldout(m_cct, 20) << "C_OrderedWrite finished " << m_result << dendl; + m_trace.event("finish"); } private: CephContext *m_cct; LibrbdWriteback::write_result_d *m_result; + ZTracer::Trace m_trace; LibrbdWriteback *m_wb_handler; }; @@ -99,17 +101,19 @@ namespace librbd { uint64_t off; bufferlist bl; SnapContext snapc; - Context *req_comp; uint64_t journal_tid; - bool request_sent; + ZTracer::Trace trace; + Context *req_comp; + bool request_sent = false; C_WriteJournalCommit(ImageCtx *_image_ctx, const std::string &_oid, uint64_t _object_no, uint64_t _off, const bufferlist &_bl, const SnapContext& _snapc, - Context *_req_comp, uint64_t _journal_tid) + uint64_t _journal_tid, + const ZTracer::Trace &trace, Context *_req_comp) : image_ctx(_image_ctx), oid(_oid), object_no(_object_no), off(_off), - bl(_bl), snapc(_snapc), req_comp(_req_comp), journal_tid(_journal_tid), - request_sent(false) { + bl(_bl), snapc(_snapc), journal_tid(_journal_tid), + trace(trace), req_comp(_req_comp) { CephContext *cct = image_ctx->cct; ldout(cct, 20) << this << " C_WriteJournalCommit: " << "delaying write until journal tid " @@ -162,7 +166,7 @@ namespace librbd { request_sent = true; auto req = new io::ObjectWriteRequest(image_ctx, oid, object_no, off, - bl, snapc, this, 0); + bl, snapc, 0, trace, this); req->send(); } }; @@ -196,7 +200,9 @@ namespace librbd { const object_locator_t& oloc, uint64_t off, uint64_t len, snapid_t snapid, bufferlist *pbl, uint64_t trunc_size, - __u32 trunc_seq, int op_flags, Context *onfinish) + __u32 trunc_seq, int op_flags, + const ZTracer::Trace &parent_trace, + Context *onfinish) { // on completion, take the mutex and then call onfinish. Context *req = new C_ReadRequest(m_ictx->cct, onfinish, &m_lock); @@ -217,8 +223,9 @@ namespace librbd { librados::AioCompletion *rados_completion = util::create_rados_callback(req); - int r = m_ictx->data_ctx.aio_operate(oid.name, rados_completion, &op, - flags, NULL); + int r = m_ictx->data_ctx.aio_operate( + oid.name, rados_completion, &op, flags, nullptr, + (parent_trace.valid() ? parent_trace.get_info() : nullptr)); rados_completion->release(); assert(r >= 0); } @@ -254,25 +261,34 @@ namespace librbd { const bufferlist &bl, ceph::real_time mtime, uint64_t trunc_size, __u32 trunc_seq, ceph_tid_t journal_tid, + const ZTracer::Trace &parent_trace, Context *oncommit) { + ZTracer::Trace trace; + if (parent_trace.valid()) { + trace.init("", &m_ictx->trace_endpoint, &parent_trace); + trace.copy_name("writeback " + oid.name); + trace.event("start"); + } + uint64_t object_no = oid_to_object_no(oid.name, m_ictx->object_prefix); write_result_d *result = new write_result_d(oid.name, oncommit); m_writes[oid.name].push(result); ldout(m_ictx->cct, 20) << "write will wait for result " << result << dendl; - C_OrderedWrite *req_comp = new C_OrderedWrite(m_ictx->cct, result, this); + C_OrderedWrite *req_comp = new C_OrderedWrite(m_ictx->cct, result, trace, + this); // all IO operations are flushed prior to closing the journal assert(journal_tid == 0 || m_ictx->journal != NULL); if (journal_tid != 0) { m_ictx->journal->flush_event( - journal_tid, new C_WriteJournalCommit(m_ictx, oid.name, object_no, off, - bl, snapc, req_comp, - journal_tid)); + journal_tid, new C_WriteJournalCommit( + m_ictx, oid.name, object_no, off, bl, snapc, journal_tid, trace, + req_comp)); } else { - auto req = new io::ObjectWriteRequest(m_ictx, oid.name, object_no, - off, bl, snapc, req_comp, 0); + auto req = new io::ObjectWriteRequest( + m_ictx, oid.name, object_no, off, bl, snapc, 0, trace, req_comp); req->send(); } return ++m_tid; diff --git a/ceph/src/librbd/LibrbdWriteback.h b/ceph/src/librbd/LibrbdWriteback.h index 9c47f98bc..6ffba5119 100644 --- a/ceph/src/librbd/LibrbdWriteback.h +++ b/ceph/src/librbd/LibrbdWriteback.h @@ -24,7 +24,8 @@ namespace librbd { void read(const object_t& oid, uint64_t object_no, const object_locator_t& oloc, uint64_t off, uint64_t len, snapid_t snapid, bufferlist *pbl, uint64_t trunc_size, - __u32 trunc_seq, int op_flags, Context *onfinish) override; + __u32 trunc_seq, int op_flags, + const ZTracer::Trace &parent_trace, Context *onfinish) override; // Determine whether a read to this extent could be affected by a // write-triggered copy-on-write @@ -37,6 +38,7 @@ namespace librbd { const SnapContext& snapc, const bufferlist &bl, ceph::real_time mtime, uint64_t trunc_size, __u32 trunc_seq, ceph_tid_t journal_tid, + const ZTracer::Trace &parent_trace, Context *oncommit) override; using WritebackHandler::write; diff --git a/ceph/src/librbd/ManagedLock.cc b/ceph/src/librbd/ManagedLock.cc index 71f5dab4d..f584d6af5 100644 --- a/ceph/src/librbd/ManagedLock.cc +++ b/ceph/src/librbd/ManagedLock.cc @@ -256,8 +256,9 @@ void ManagedLock::break_lock(const managed_lock::Locker &locker, } else { on_finish = new C_Tracked(m_async_op_tracker, on_finish); auto req = managed_lock::BreakRequest::create( - m_ioctx, m_work_queue, m_oid, locker, m_blacklist_on_break_lock, - m_blacklist_expire_seconds, force_break_lock, on_finish); + m_ioctx, m_work_queue, m_oid, locker, m_mode == EXCLUSIVE, + m_blacklist_on_break_lock, m_blacklist_expire_seconds, force_break_lock, + on_finish); req->send(); return; } @@ -329,6 +330,11 @@ void ManagedLock::post_release_lock_handler(bool shutting_down, int r, on_finish->complete(r); } +template +void ManagedLock::post_reacquire_lock_handler(int r, Context *on_finish) { + on_finish->complete(r); +} + template bool ManagedLock::is_transition_state() const { switch (m_state) { @@ -565,11 +571,15 @@ void ManagedLock::send_reacquire_lock() { ldout(m_cct, 10) << dendl; m_state = STATE_REACQUIRING; + auto ctx = create_context_callback< + ManagedLock, &ManagedLock::handle_reacquire_lock>(this); + ctx = new FunctionContext([this, ctx](int r) { + post_reacquire_lock_handler(r, ctx); + }); + using managed_lock::ReacquireRequest; ReacquireRequest* req = ReacquireRequest::create(m_ioctx, m_oid, - m_cookie, m_new_cookie, m_mode == EXCLUSIVE, - create_context_callback< - ManagedLock, &ManagedLock::handle_reacquire_lock>(this)); + m_cookie, m_new_cookie, m_mode == EXCLUSIVE, ctx); m_work_queue->queue(new C_SendLockRequest>(req)); } diff --git a/ceph/src/librbd/ManagedLock.h b/ceph/src/librbd/ManagedLock.h index d18cfbef1..c619f4823 100644 --- a/ceph/src/librbd/ManagedLock.h +++ b/ceph/src/librbd/ManagedLock.h @@ -134,6 +134,7 @@ protected: Context *on_finish); virtual void post_release_lock_handler(bool shutting_down, int r, Context *on_finish); + virtual void post_reacquire_lock_handler(int r, Context *on_finish); void execute_next_action(); diff --git a/ceph/src/librbd/ObjectMap.cc b/ceph/src/librbd/ObjectMap.cc index 49c8280da..0930e6a56 100644 --- a/ceph/src/librbd/ObjectMap.cc +++ b/ceph/src/librbd/ObjectMap.cc @@ -91,9 +91,14 @@ bool ObjectMap::object_may_exist(uint64_t object_no) const // Fall back to default logic if object map is disabled or invalid if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP, - m_image_ctx.snap_lock) || - m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID, - m_image_ctx.snap_lock)) { + m_image_ctx.snap_lock)) { + return true; + } + + bool flags_set; + int r = m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID, + m_image_ctx.snap_lock, &flags_set); + if (r < 0 || flags_set) { return true; } @@ -242,7 +247,7 @@ void ObjectMap::detained_aio_update(UpdateOperation &&op) { handle_detained_aio_update(cell, r, on_finish); }); aio_update(CEPH_NOSNAP, op.start_object_no, op.end_object_no, op.new_state, - op.current_state, ctx); + op.current_state, op.parent_trace, ctx); } template @@ -269,6 +274,7 @@ template void ObjectMap::aio_update(uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, + const ZTracer::Trace &parent_trace, Context *on_finish) { assert(m_image_ctx.snap_lock.is_locked()); assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0); @@ -306,7 +312,7 @@ void ObjectMap::aio_update(uint64_t snap_id, uint64_t start_object_no, auto req = object_map::UpdateRequest::create( m_image_ctx, &m_object_map, snap_id, start_object_no, end_object_no, - new_state, current_state, on_finish); + new_state, current_state, parent_trace, on_finish); req->send(); } diff --git a/ceph/src/librbd/ObjectMap.h b/ceph/src/librbd/ObjectMap.h index fd43ae97d..427ecdf16 100644 --- a/ceph/src/librbd/ObjectMap.h +++ b/ceph/src/librbd/ObjectMap.h @@ -13,9 +13,8 @@ class Context; class RWLock; -namespace librados { - class IoCtx; -} +namespace librados { class IoCtx; } +namespace ZTracer { struct Trace; } namespace librbd { @@ -57,16 +56,17 @@ public: template bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint8_t new_state, const boost::optional ¤t_state, - T *callback_object) { + const ZTracer::Trace &parent_trace, T *callback_object) { return aio_update(snap_id, start_object_no, start_object_no + 1, - new_state, current_state, callback_object); + new_state, current_state, parent_trace, + callback_object); } template bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, - T *callback_object) { + const ZTracer::Trace &parent_trace, T *callback_object) { assert(start_object_no < end_object_no); if (snap_id == CEPH_NOSNAP) { uint64_t object_no; @@ -82,13 +82,13 @@ public: } UpdateOperation update_operation(start_object_no, end_object_no, - new_state, current_state, + new_state, current_state, parent_trace, util::create_context_callback( callback_object)); detained_aio_update(std::move(update_operation)); } else { aio_update(snap_id, start_object_no, end_object_no, new_state, - current_state, + current_state, parent_trace, util::create_context_callback(callback_object)); } return true; @@ -104,15 +104,16 @@ private: uint64_t end_object_no; uint8_t new_state; boost::optional current_state; + ZTracer::Trace parent_trace; Context *on_finish; UpdateOperation(uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, - Context *on_finish) + const ZTracer::Trace &parent_trace, Context *on_finish) : start_object_no(start_object_no), end_object_no(end_object_no), new_state(new_state), current_state(current_state), - on_finish(on_finish) { + parent_trace(parent_trace), on_finish(on_finish) { } }; @@ -131,7 +132,7 @@ private: void aio_update(uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, - Context *on_finish); + const ZTracer::Trace &parent_trace, Context *on_finish); bool update_required(uint64_t object_no, uint8_t new_state); }; diff --git a/ceph/src/librbd/Operations.cc b/ceph/src/librbd/Operations.cc index c70ff6f91..af0cb1220 100644 --- a/ceph/src/librbd/Operations.cc +++ b/ceph/src/librbd/Operations.cc @@ -192,9 +192,8 @@ struct C_InvokeAsyncRequest : public Context { return; } - int r; if (image_ctx.exclusive_lock->is_lock_owner() && - image_ctx.exclusive_lock->accept_requests(&r)) { + image_ctx.exclusive_lock->accept_requests()) { send_local_request(); owner_lock.put_read(); return; @@ -1473,7 +1472,6 @@ int Operations::prepare_image_update() { } // need to upgrade to a write lock - int r = 0; bool trying_lock = false; C_SaferCond ctx; m_image_ctx.owner_lock.put_read(); @@ -1481,12 +1479,13 @@ int Operations::prepare_image_update() { RWLock::WLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.exclusive_lock != nullptr && (!m_image_ctx.exclusive_lock->is_lock_owner() || - !m_image_ctx.exclusive_lock->accept_requests(&r))) { + !m_image_ctx.exclusive_lock->accept_requests())) { m_image_ctx.exclusive_lock->try_acquire_lock(&ctx); trying_lock = true; } } + int r = 0; if (trying_lock) { r = ctx.wait(); } diff --git a/ceph/src/librbd/Utils.h b/ceph/src/librbd/Utils.h index 9a3086053..f75d65c43 100644 --- a/ceph/src/librbd/Utils.h +++ b/ceph/src/librbd/Utils.h @@ -7,6 +7,7 @@ #include "include/rados/librados.hpp" #include "include/rbd_types.h" #include "include/Context.h" +#include "common/zipkin_trace.h" #include #include @@ -192,6 +193,16 @@ bool calc_sparse_extent(const bufferptr &bp, size_t *write_offset, size_t *write_length, size_t *offset); + +template +inline ZTracer::Trace create_trace(const I &image_ctx, const char *trace_name, + const ZTracer::Trace &parent_trace) { + if (parent_trace.valid()) { + return ZTracer::Trace(trace_name, &image_ctx.trace_endpoint, &parent_trace); + } + return ZTracer::Trace(); +} + } // namespace util } // namespace librbd diff --git a/ceph/src/librbd/Watcher.cc b/ceph/src/librbd/Watcher.cc index 98a0e7f0b..54a2246f1 100644 --- a/ceph/src/librbd/Watcher.cc +++ b/ceph/src/librbd/Watcher.cc @@ -174,6 +174,30 @@ void Watcher::unregister_watch(Context *on_finish) { on_finish->complete(0); } +bool Watcher::notifications_blocked() const { + RWLock::RLocker locker(m_watch_lock); + + bool blocked = (m_blocked_count > 0); + ldout(m_cct, 5) << "blocked=" << blocked << dendl; + return blocked; +} + +void Watcher::block_notifies(Context *on_finish) { + { + RWLock::WLocker locker(m_watch_lock); + ++m_blocked_count; + ldout(m_cct, 5) << "blocked_count=" << m_blocked_count << dendl; + } + m_async_op_tracker.wait_for_ops(on_finish); +} + +void Watcher::unblock_notifies() { + RWLock::WLocker locker(m_watch_lock); + assert(m_blocked_count > 0); + --m_blocked_count; + ldout(m_cct, 5) << "blocked_count=" << m_blocked_count << dendl; +} + void Watcher::flush(Context *on_finish) { m_notifier.flush(on_finish); } @@ -260,11 +284,18 @@ void Watcher::send_notify(bufferlist& payload, m_notifier.notify(payload, response, on_finish); } -void Watcher::WatchCtx::handle_notify(uint64_t notify_id, - uint64_t handle, - uint64_t notifier_id, - bufferlist& bl) { - watcher.handle_notify(notify_id, handle, notifier_id, bl); +void Watcher::WatchCtx::handle_notify(uint64_t notify_id, uint64_t handle, + uint64_t notifier_id, bufferlist& bl) { + // if notifications are blocked, finish the notification w/o + // bubbling the notification up to the derived class + watcher.m_async_op_tracker.start_op(); + if (watcher.notifications_blocked()) { + bufferlist bl; + watcher.acknowledge_notify(notify_id, handle, bl); + } else { + watcher.handle_notify(notify_id, handle, notifier_id, bl); + } + watcher.m_async_op_tracker.finish_op(); } void Watcher::WatchCtx::handle_error(uint64_t handle, int err) { diff --git a/ceph/src/librbd/Watcher.h b/ceph/src/librbd/Watcher.h index 01de69093..39009027d 100644 --- a/ceph/src/librbd/Watcher.h +++ b/ceph/src/librbd/Watcher.h @@ -4,6 +4,7 @@ #ifndef CEPH_LIBRBD_WATCHER_H #define CEPH_LIBRBD_WATCHER_H +#include "common/AsyncOpTracker.h" #include "common/Mutex.h" #include "common/RWLock.h" #include "include/rados/librados.hpp" @@ -36,9 +37,13 @@ public: virtual ~Watcher(); void register_watch(Context *on_finish); - void unregister_watch(Context *on_finish); + virtual void unregister_watch(Context *on_finish); void flush(Context *on_finish); + bool notifications_blocked() const; + virtual void block_notifies(Context *on_finish); + void unblock_notifies(); + std::string get_oid() const; void set_oid(const string& oid); @@ -73,6 +78,7 @@ protected: uint64_t m_watch_handle; watcher::Notifier m_notifier; WatchState m_watch_state; + AsyncOpTracker m_async_op_tracker; void send_notify(bufferlist &payload, watcher::NotifyResponse *response = nullptr, @@ -149,6 +155,8 @@ private: WatchCtx m_watch_ctx; Context *m_unregister_watch_ctx = nullptr; + uint32_t m_blocked_count = 0; + void handle_register_watch(int r, Context *on_finish); void rewatch(); diff --git a/ceph/src/librbd/api/Group.cc b/ceph/src/librbd/api/Group.cc index 22339ea4e..090a98074 100644 --- a/ceph/src/librbd/api/Group.cc +++ b/ceph/src/librbd/api/Group.cc @@ -137,8 +137,12 @@ int Group::list(IoCtx& io_ctx, vector *names) r = cls_client::group_dir_list(&io_ctx, RBD_GROUP_DIRECTORY, last_read, max_read, &groups); if (r < 0) { - lderr(cct) << "error listing group in directory: " - << cpp_strerror(r) << dendl; + if (r != -ENOENT) { + lderr(cct) << "error listing group in directory: " + << cpp_strerror(r) << dendl; + } else { + r = 0; + } return r; } for (pair group : groups) { diff --git a/ceph/src/librbd/cache/ImageWriteback.cc b/ceph/src/librbd/cache/ImageWriteback.cc index 83c3b5bb1..cff7a531d 100644 --- a/ceph/src/librbd/cache/ImageWriteback.cc +++ b/ceph/src/librbd/cache/ImageWriteback.cc @@ -30,7 +30,7 @@ void ImageWriteback::aio_read(Extents &&image_extents, bufferlist *bl, auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, io::AIO_TYPE_READ); io::ImageReadRequest req(m_image_ctx, aio_comp, std::move(image_extents), - io::ReadResult{bl}, fadvise_flags); + io::ReadResult{bl}, fadvise_flags, {}); req.set_bypass_image_cache(); req.send(); } @@ -46,14 +46,15 @@ void ImageWriteback::aio_write(Extents &&image_extents, auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, io::AIO_TYPE_WRITE); io::ImageWriteRequest req(m_image_ctx, aio_comp, std::move(image_extents), - std::move(bl), fadvise_flags); + std::move(bl), fadvise_flags, {}); req.set_bypass_image_cache(); req.send(); } template void ImageWriteback::aio_discard(uint64_t offset, uint64_t length, - bool skip_partial_discard, Context *on_finish) { + bool skip_partial_discard, + Context *on_finish) { CephContext *cct = m_image_ctx.cct; ldout(cct, 20) << "offset=" << offset << ", " << "length=" << length << ", " @@ -62,7 +63,7 @@ void ImageWriteback::aio_discard(uint64_t offset, uint64_t length, auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, io::AIO_TYPE_DISCARD); io::ImageDiscardRequest req(m_image_ctx, aio_comp, offset, length, - skip_partial_discard); + skip_partial_discard, {}); req.set_bypass_image_cache(); req.send(); } @@ -74,7 +75,7 @@ void ImageWriteback::aio_flush(Context *on_finish) { auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, io::AIO_TYPE_FLUSH); - io::ImageFlushRequest req(m_image_ctx, aio_comp); + io::ImageFlushRequest req(m_image_ctx, aio_comp, {}); req.set_bypass_image_cache(); req.send(); } @@ -92,7 +93,7 @@ void ImageWriteback::aio_writesame(uint64_t offset, uint64_t length, auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx, io::AIO_TYPE_WRITESAME); io::ImageWriteSameRequest req(m_image_ctx, aio_comp, offset, length, - std::move(bl), fadvise_flags); + std::move(bl), fadvise_flags, {}); req.set_bypass_image_cache(); req.send(); } diff --git a/ceph/src/librbd/exclusive_lock/PreReleaseRequest.cc b/ceph/src/librbd/exclusive_lock/PreReleaseRequest.cc index ee29a9858..5a37acc96 100644 --- a/ceph/src/librbd/exclusive_lock/PreReleaseRequest.cc +++ b/ceph/src/librbd/exclusive_lock/PreReleaseRequest.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "librbd/exclusive_lock/PreReleaseRequest.h" +#include "common/AsyncOpTracker.h" #include "common/dout.h" #include "common/errno.h" #include "librbd/ExclusiveLock.h" @@ -24,19 +25,20 @@ using util::create_async_context_callback; using util::create_context_callback; template -PreReleaseRequest* PreReleaseRequest::create(I &image_ctx, - bool shutting_down, - Context *on_finish) { - return new PreReleaseRequest(image_ctx, shutting_down, on_finish); +PreReleaseRequest* PreReleaseRequest::create( + I &image_ctx, bool shutting_down, AsyncOpTracker &async_op_tracker, + Context *on_finish) { + return new PreReleaseRequest(image_ctx, shutting_down, async_op_tracker, + on_finish); } template PreReleaseRequest::PreReleaseRequest(I &image_ctx, bool shutting_down, + AsyncOpTracker &async_op_tracker, Context *on_finish) - : m_image_ctx(image_ctx), - m_on_finish(create_async_context_callback(image_ctx, on_finish)), - m_shutting_down(shutting_down), m_error_result(0), m_object_map(nullptr), - m_journal(nullptr) { + : m_image_ctx(image_ctx), m_shutting_down(shutting_down), + m_async_op_tracker(async_op_tracker), + m_on_finish(create_async_context_callback(image_ctx, on_finish)) { } template @@ -131,6 +133,24 @@ void PreReleaseRequest::handle_block_writes(int r) { return; } + send_wait_for_ops(); +} + +template +void PreReleaseRequest::send_wait_for_ops() { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << dendl; + + Context *ctx = create_context_callback< + PreReleaseRequest, &PreReleaseRequest::handle_wait_for_ops>(this); + m_async_op_tracker.wait_for_ops(ctx); +} + +template +void PreReleaseRequest::handle_wait_for_ops(int r) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << dendl; + send_invalidate_cache(false); } diff --git a/ceph/src/librbd/exclusive_lock/PreReleaseRequest.h b/ceph/src/librbd/exclusive_lock/PreReleaseRequest.h index 98e3a1e9d..34ac07ab2 100644 --- a/ceph/src/librbd/exclusive_lock/PreReleaseRequest.h +++ b/ceph/src/librbd/exclusive_lock/PreReleaseRequest.h @@ -7,6 +7,7 @@ #include "librbd/ImageCtx.h" #include +class AsyncOpTracker; class Context; namespace librbd { @@ -19,6 +20,7 @@ template class PreReleaseRequest { public: static PreReleaseRequest* create(ImageCtxT &image_ctx, bool shutting_down, + AsyncOpTracker &async_op_tracker, Context *on_finish); ~PreReleaseRequest(); @@ -40,6 +42,9 @@ private: * BLOCK_WRITES * | * v + * WAIT_FOR_OPS + * | + * v * INVALIDATE_CACHE * | * v @@ -58,16 +63,17 @@ private: */ PreReleaseRequest(ImageCtxT &image_ctx, bool shutting_down, - Context *on_finish); + AsyncOpTracker &async_op_tracker, Context *on_finish); ImageCtxT &m_image_ctx; - Context *m_on_finish; bool m_shutting_down; + AsyncOpTracker &m_async_op_tracker; + Context *m_on_finish; - int m_error_result; + int m_error_result = 0; - decltype(m_image_ctx.object_map) m_object_map; - decltype(m_image_ctx.journal) m_journal; + decltype(m_image_ctx.object_map) m_object_map = nullptr; + decltype(m_image_ctx.journal) m_journal = nullptr; void send_prepare_lock(); void handle_prepare_lock(int r); @@ -78,6 +84,9 @@ private: void send_block_writes(); void handle_block_writes(int r); + void send_wait_for_ops(); + void handle_wait_for_ops(int r); + void send_invalidate_cache(bool purge_on_error); void handle_invalidate_cache(int r); diff --git a/ceph/src/librbd/image/CloseRequest.cc b/ceph/src/librbd/image/CloseRequest.cc index 900164fcc..ee1519bf7 100644 --- a/ceph/src/librbd/image/CloseRequest.cc +++ b/ceph/src/librbd/image/CloseRequest.cc @@ -31,56 +31,50 @@ CloseRequest::CloseRequest(I *image_ctx, Context *on_finish) template void CloseRequest::send() { - send_shut_down_update_watchers(); + send_block_image_watcher(); } template -void CloseRequest::send_shut_down_update_watchers() { +void CloseRequest::send_block_image_watcher() { + if (m_image_ctx->image_watcher == nullptr) { + send_shut_down_update_watchers(); + return; + } + CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << this << " " << __func__ << dendl; - m_image_ctx->state->shut_down_update_watchers(create_async_context_callback( - *m_image_ctx, create_context_callback< - CloseRequest, &CloseRequest::handle_shut_down_update_watchers>(this))); + // prevent incoming requests from our peers + m_image_ctx->image_watcher->block_notifies(create_context_callback< + CloseRequest, &CloseRequest::handle_block_image_watcher>(this)); } template -void CloseRequest::handle_shut_down_update_watchers(int r) { +void CloseRequest::handle_block_image_watcher(int r) { CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; - save_result(r); - if (r < 0) { - lderr(cct) << "failed to shut down update watchers: " << cpp_strerror(r) - << dendl; - } - - send_unregister_image_watcher(); + send_shut_down_update_watchers(); } template -void CloseRequest::send_unregister_image_watcher() { - if (m_image_ctx->image_watcher == nullptr) { - send_shut_down_io_queue(); - return; - } - +void CloseRequest::send_shut_down_update_watchers() { CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << this << " " << __func__ << dendl; - // prevent incoming requests from our peers - m_image_ctx->image_watcher->unregister_watch(create_context_callback< - CloseRequest, &CloseRequest::handle_unregister_image_watcher>(this)); + m_image_ctx->state->shut_down_update_watchers(create_async_context_callback( + *m_image_ctx, create_context_callback< + CloseRequest, &CloseRequest::handle_shut_down_update_watchers>(this))); } template -void CloseRequest::handle_unregister_image_watcher(int r) { +void CloseRequest::handle_shut_down_update_watchers(int r) { CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; save_result(r); if (r < 0) { - lderr(cct) << "failed to unregister image watcher: " << cpp_strerror(r) + lderr(cct) << "failed to shut down update watchers: " << cpp_strerror(r) << dendl; } @@ -156,7 +150,8 @@ void CloseRequest::handle_shut_down_exclusive_lock(int r) { lderr(cct) << "failed to shut down exclusive lock: " << cpp_strerror(r) << dendl; } - send_flush_readahead(); + + send_unregister_image_watcher(); } template @@ -178,6 +173,34 @@ void CloseRequest::handle_flush(int r) { if (r < 0) { lderr(cct) << "failed to flush IO: " << cpp_strerror(r) << dendl; } + send_unregister_image_watcher(); +} + +template +void CloseRequest::send_unregister_image_watcher() { + if (m_image_ctx->image_watcher == nullptr) { + send_flush_readahead(); + return; + } + + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + m_image_ctx->image_watcher->unregister_watch(create_context_callback< + CloseRequest, &CloseRequest::handle_unregister_image_watcher>(this)); +} + +template +void CloseRequest::handle_unregister_image_watcher(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; + + save_result(r); + if (r < 0) { + lderr(cct) << "failed to unregister image watcher: " << cpp_strerror(r) + << dendl; + } + send_flush_readahead(); } diff --git a/ceph/src/librbd/image/CloseRequest.h b/ceph/src/librbd/image/CloseRequest.h index c5cf2e173..812e91d72 100644 --- a/ceph/src/librbd/image/CloseRequest.h +++ b/ceph/src/librbd/image/CloseRequest.h @@ -30,19 +30,21 @@ private: * * | * v - * SHUT_DOWN_UPDATE_WATCHERS + * BLOCK_IMAGE_WATCHER (skip if R/O) * | * v - * UNREGISTER_IMAGE_WATCHER + * SHUT_DOWN_UPDATE_WATCHERS * | * v * SHUT_DOWN_AIO_WORK_QUEUE . . . - * | . - * v . - * SHUT_DOWN_EXCLUSIVE_LOCK . (exclusive lock - * | . disabled) + * | . (exclusive lock disabled) * v v - * FLUSH < . . . . . . . . . . . + * SHUT_DOWN_EXCLUSIVE_LOCK FLUSH + * | . + * | . . . . . . . . . . . + * | . + * v v + * UNREGISTER_IMAGE_WATCHER (skip if R/O) * | * v * FLUSH_READAHEAD @@ -74,12 +76,12 @@ private: decltype(m_image_ctx->exclusive_lock) m_exclusive_lock; + void send_block_image_watcher(); + void handle_block_image_watcher(int r); + void send_shut_down_update_watchers(); void handle_shut_down_update_watchers(int r); - void send_unregister_image_watcher(); - void handle_unregister_image_watcher(int r); - void send_shut_down_io_queue(); void handle_shut_down_io_queue(int r); @@ -89,6 +91,9 @@ private: void send_flush(); void handle_flush(int r); + void send_unregister_image_watcher(); + void handle_unregister_image_watcher(int r); + void send_flush_readahead(); void handle_flush_readahead(int r); diff --git a/ceph/src/librbd/image/OpenRequest.cc b/ceph/src/librbd/image/OpenRequest.cc index 579088b3c..5b13f5196 100644 --- a/ceph/src/librbd/image/OpenRequest.cc +++ b/ceph/src/librbd/image/OpenRequest.cc @@ -322,6 +322,45 @@ Context *OpenRequest::handle_v2_get_stripe_unit_count(int *result) { return nullptr; } + send_v2_get_create_timestamp(); + return nullptr; +} + +template +void OpenRequest::send_v2_get_create_timestamp() { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + librados::ObjectReadOperation op; + cls_client::get_create_timestamp_start(&op); + + using klass = OpenRequest; + librados::AioCompletion *comp = create_rados_callback< + klass, &klass::handle_v2_get_create_timestamp>(this); + m_out_bl.clear(); + m_image_ctx->md_ctx.aio_operate(m_image_ctx->header_oid, comp, &op, + &m_out_bl); + comp->release(); +} + +template +Context *OpenRequest::handle_v2_get_create_timestamp(int *result) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl; + + if (*result == 0) { + bufferlist::iterator it = m_out_bl.begin(); + *result = cls_client::get_create_timestamp_finish(&it, + &m_image_ctx->create_timestamp); + } + if (*result < 0 && *result != -EOPNOTSUPP) { + lderr(cct) << "failed to retrieve create_timestamp: " + << cpp_strerror(*result) + << dendl; + send_close_image(*result); + return nullptr; + } + send_v2_get_data_pool(); return nullptr; } diff --git a/ceph/src/librbd/image/OpenRequest.h b/ceph/src/librbd/image/OpenRequest.h index 3ae8602fb..5dd088770 100644 --- a/ceph/src/librbd/image/OpenRequest.h +++ b/ceph/src/librbd/image/OpenRequest.h @@ -52,6 +52,9 @@ private: * V2_GET_STRIPE_UNIT_COUNT | * | | * v | + * V2_GET_CREATE_TIMESTAMP | + * | | + * v | * V2_GET_DATA_POOL | * | | * v | @@ -105,6 +108,9 @@ private: void send_v2_get_stripe_unit_count(); Context *handle_v2_get_stripe_unit_count(int *result); + void send_v2_get_create_timestamp(); + Context *handle_v2_get_create_timestamp(int *result); + void send_v2_get_data_pool(); Context *handle_v2_get_data_pool(int *result); diff --git a/ceph/src/librbd/image/RemoveRequest.cc b/ceph/src/librbd/image/RemoveRequest.cc index 629fc7c79..5782702d7 100644 --- a/ceph/src/librbd/image/RemoveRequest.cc +++ b/ceph/src/librbd/image/RemoveRequest.cc @@ -17,7 +17,7 @@ #define dout_subsys ceph_subsys_rbd #undef dout_prefix #define dout_prefix *_dout << "librbd::image::RemoveRequest: " << this << " " \ - << __func__ << " " + << __func__ << ": " namespace librbd { namespace image { @@ -62,20 +62,21 @@ void RemoveRequest::open_image() { } template -Context *RemoveRequest::handle_open_image(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_open_image(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0) { + if (r < 0) { m_image_ctx->destroy(); m_image_ctx = nullptr; - if (*result != -ENOENT) { - lderr(m_cct) << "error opening image: " << cpp_strerror(*result) << dendl; - return m_on_finish; + if (r != -ENOENT) { + lderr(m_cct) << "error opening image: " << cpp_strerror(r) << dendl; + finish(r); + return; } remove_image(); - return nullptr; + return; } m_image_id = m_image_ctx->id; @@ -85,7 +86,6 @@ Context *RemoveRequest::handle_open_image(int *result) { m_unknown_format = false; check_exclusive_lock(); - return nullptr; } template @@ -107,7 +107,8 @@ void RemoveRequest::acquire_exclusive_lock() { if (m_force) { Context *ctx = create_context_callback< klass, &klass::handle_exclusive_lock_force>(this); - m_image_ctx->exclusive_lock->shut_down(ctx); + m_exclusive_lock = m_image_ctx->exclusive_lock; + m_exclusive_lock->shut_down(ctx); } else { Context *ctx = create_context_callback< klass, &klass::handle_exclusive_lock>(this); @@ -117,33 +118,34 @@ void RemoveRequest::acquire_exclusive_lock() { } template -Context *RemoveRequest::handle_exclusive_lock_force(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_exclusive_lock_force(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0) { + delete m_exclusive_lock; + m_exclusive_lock = nullptr; + + if (r < 0) { lderr(m_cct) << "error shutting down exclusive lock: " - << cpp_strerror(*result) << dendl; - send_close_image(*result); - return nullptr; + << cpp_strerror(r) << dendl; + send_close_image(r); + return; } assert(m_image_ctx->exclusive_lock == nullptr); validate_image_removal(); - return nullptr; } template -Context *RemoveRequest::handle_exclusive_lock(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_exclusive_lock(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) || !m_image_ctx->exclusive_lock->is_lock_owner()) { + if (r < 0 || !m_image_ctx->exclusive_lock->is_lock_owner()) { lderr(m_cct) << "cannot obtain exclusive lock - not removing" << dendl; send_close_image(-EBUSY); - return nullptr; + return; } validate_image_removal(); - return nullptr; } template @@ -163,11 +165,11 @@ void RemoveRequest::check_image_snaps() { return; } - check_image_watchers(); + list_image_watchers(); } template -void RemoveRequest::check_image_watchers() { +void RemoveRequest::list_image_watchers() { ldout(m_cct, 20) << dendl; librados::ObjectReadOperation op; @@ -175,7 +177,7 @@ void RemoveRequest::check_image_watchers() { using klass = RemoveRequest; librados::AioCompletion *rados_completion = - create_rados_callback(this); + create_rados_callback(this); int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, &op, &m_out_bl); @@ -184,74 +186,109 @@ void RemoveRequest::check_image_watchers() { } template -void RemoveRequest::filter_out_mirror_watchers() { - if (m_watchers.empty()) { - return; - } +void RemoveRequest::handle_list_image_watchers(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0) { - return; + if (r == 0 && m_ret_val < 0) { + r = m_ret_val; } - - cls::rbd::MirrorImage mirror_image; - int r = cls_client::mirror_image_get(&m_image_ctx->md_ctx, m_image_ctx->id, - &mirror_image); if (r < 0) { - if (r != -ENOENT) { - lderr(m_cct) << "failed to retrieve mirroring state: " - << cpp_strerror(r) << dendl; - } + lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r) + << dendl; + send_close_image(r); return; } - if (mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) { + get_mirror_image(); +} + +template +void RemoveRequest::get_mirror_image() { + ldout(m_cct, 20) << dendl; + if ((m_watchers.empty()) || + ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0)) { + check_image_watchers(); return; } - std::list mirror_watchers; - r = m_image_ctx->md_ctx.list_watchers(RBD_MIRRORING, &mirror_watchers); - if (r < 0) { - if (r != -ENOENT) { - lderr(m_cct) << "error listing mirroring watchers: " - << cpp_strerror(r) << dendl; - } + librados::ObjectReadOperation op; + cls_client::mirror_image_get_start(&op, m_image_id); + + using klass = RemoveRequest; + librados::AioCompletion *comp = + create_rados_callback(this); + m_out_bl.clear(); + int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl); + assert(r == 0); + comp->release(); +} + +template +void RemoveRequest::handle_get_mirror_image(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + if (r == -ENOENT || r == -EOPNOTSUPP) { + check_image_watchers(); return; + } else if (r < 0) { + ldout(m_cct, 5) << "error retrieving mirror image: " << cpp_strerror(r) + << dendl; } - for (auto &watcher : mirror_watchers) { - m_watchers.remove_if([watcher] (obj_watch_t &w) { - return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0); - }); - } + + list_mirror_watchers(); } template -Context *RemoveRequest::handle_check_image_watchers(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::list_mirror_watchers() { + ldout(m_cct, 20) << dendl; - if (*result < 0) { - lderr(m_cct) << "error listing image watchers: " << cpp_strerror(*result) - << dendl; - send_close_image(*result); - return nullptr; + librados::ObjectReadOperation op; + op.list_watchers(&m_mirror_watchers, &m_ret_val); + + using klass = RemoveRequest; + librados::AioCompletion *rados_completion = + create_rados_callback(this); + m_out_bl.clear(); + int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, rados_completion, + &op, &m_out_bl); + assert(r == 0); + rados_completion->release(); +} + +template +void RemoveRequest::handle_list_mirror_watchers(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + if (r == 0 && m_ret_val < 0) { + r = m_ret_val; + } + if (r < 0 && r != -ENOENT) { + ldout(m_cct, 5) << "error listing mirror watchers: " << cpp_strerror(r) + << dendl; + } + + for (auto &watcher : m_mirror_watchers) { + m_watchers.remove_if([watcher] (obj_watch_t &w) { + return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0); + }); } - // If an image is being bootstrapped by rbd-mirror, it implies - // that the rbd-mirror daemon currently has the image open. - // Permit removal if this is the case. - filter_out_mirror_watchers(); + check_image_watchers(); +} +template +void RemoveRequest::check_image_watchers() { if (m_watchers.size() > 1) { lderr(m_cct) << "image has watchers - not removing" << dendl; send_close_image(-EBUSY); - return nullptr; + return; } - check_image_consistency_group(); - return nullptr; + check_group(); } template -void RemoveRequest::check_image_consistency_group() { +void RemoveRequest::check_group() { ldout(m_cct, 20) << dendl; librados::ObjectReadOperation op; @@ -259,7 +296,7 @@ void RemoveRequest::check_image_consistency_group() { using klass = RemoveRequest; librados::AioCompletion *rados_completion = create_rados_callback< - klass, &klass::handle_check_image_consistency_group>(this); + klass, &klass::handle_check_group>(this); m_out_bl.clear(); int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, &op, &m_out_bl); @@ -268,32 +305,28 @@ void RemoveRequest::check_image_consistency_group() { } template -Context *RemoveRequest::handle_check_image_consistency_group(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; - - if (*result < 0) { - lderr(m_cct) << "error fetching consistency group for image: " - << cpp_strerror(*result) << dendl; - send_close_image(*result); - return nullptr; - } +void RemoveRequest::handle_check_group(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; cls::rbd::GroupSpec s; - bufferlist::iterator it = m_out_bl.begin(); - *result = librbd::cls_client::image_get_group_finish(&it, &s); - if (*result < 0) { - send_close_image(*result); - return nullptr; + if (r == 0) { + bufferlist::iterator it = m_out_bl.begin(); + r = librbd::cls_client::image_get_group_finish(&it, &s); + } + if (r < 0 && r != -EOPNOTSUPP) { + lderr(m_cct) << "error fetching group for image: " + << cpp_strerror(r) << dendl; + send_close_image(r); + return; } + if (s.is_valid()) { lderr(m_cct) << "image is in a group - not removing" << dendl; send_close_image(-EMLINK); - return nullptr; + return; } trim_image(); - - return nullptr; } template @@ -312,21 +345,20 @@ void RemoveRequest::trim_image() { } template -Context *RemoveRequest::handle_trim_image(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_trim_image(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0) { + if (r < 0) { lderr(m_cct) << "warning: failed to remove some object(s): " - << cpp_strerror(*result) << dendl; + << cpp_strerror(r) << dendl; } if (m_old_format) { - send_close_image(*result); - return nullptr; + send_close_image(r); + return; } remove_child(); - return nullptr; } template @@ -349,21 +381,20 @@ void RemoveRequest::remove_child() { } template -Context *RemoveRequest::handle_remove_child(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_remove_child(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result == -ENOENT) { - *result = 0; - } else if (*result < 0) { + if (r == -ENOENT) { + r = 0; + } else if (r < 0) { lderr(m_cct) << "error removing child from children list: " - << cpp_strerror(*result) << dendl; - send_close_image(*result); - return nullptr; + << cpp_strerror(r) << dendl; + send_close_image(r); + return; } send_disable_mirror(); - return nullptr; } template @@ -380,18 +411,17 @@ void RemoveRequest::send_disable_mirror() { } template -Context *RemoveRequest::handle_disable_mirror(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_disable_mirror(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result == -EOPNOTSUPP) { - *result = 0; - } else if (*result < 0) { + if (r == -EOPNOTSUPP) { + r = 0; + } else if (r < 0) { lderr(m_cct) << "error disabling image mirroring: " - << cpp_strerror(*result) << dendl; + << cpp_strerror(r) << dendl; } - send_close_image(*result); - return nullptr; + send_close_image(r); } template @@ -407,23 +437,23 @@ void RemoveRequest::send_close_image(int r) { } template -Context *RemoveRequest::handle_send_close_image(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_send_close_image(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0) { + if (r < 0) { lderr(m_cct) << "error encountered while closing image: " - << cpp_strerror(*result) << dendl; + << cpp_strerror(r) << dendl; } m_image_ctx->destroy(); m_image_ctx = nullptr; if (m_ret_val < 0) { - *result = m_ret_val; - return m_on_finish; + r = m_ret_val; + finish(r); + return; } remove_header(); - return nullptr; } template @@ -439,16 +469,15 @@ void RemoveRequest::remove_header() { } template -Context *RemoveRequest::handle_remove_header(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_remove_header(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) && (*result != -ENOENT)) { - lderr(m_cct) << "error removing header: " << cpp_strerror(*result) << dendl; - m_ret_val = *result; + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl; + m_ret_val = r; } remove_image(); - return nullptr; } template @@ -468,16 +497,16 @@ void RemoveRequest::remove_header_v2() { } template -Context *RemoveRequest::handle_remove_header_v2(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_remove_header_v2(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) && (*result != -ENOENT)) { - lderr(m_cct) << "error removing header: " << cpp_strerror(*result) << dendl; - return m_on_finish; + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl; + finish(r); + return; } send_journal_remove(); - return nullptr; } template @@ -494,19 +523,19 @@ void RemoveRequest::send_journal_remove() { } template -Context *RemoveRequest::handle_journal_remove(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_journal_remove(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0 && *result != -ENOENT) { - lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(*result) + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r) << dendl; - return m_on_finish; + finish(r); + return; } else { - *result = 0; + r = 0; } send_object_map_remove(); - return nullptr; } template @@ -525,19 +554,19 @@ void RemoveRequest::send_object_map_remove() { } template -Context *RemoveRequest::handle_object_map_remove(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_object_map_remove(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0 && *result != -ENOENT) { - lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(*result) + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r) << dendl; - return m_on_finish; + finish(r); + return; } else { - *result = 0; + r = 0; } mirror_image_remove(); - return nullptr; } template @@ -556,27 +585,24 @@ void RemoveRequest::mirror_image_remove() { } template -Context *RemoveRequest::handle_mirror_image_remove(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_mirror_image_remove(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if (*result < 0 && *result != -ENOENT && *result != -EOPNOTSUPP) { + if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) { lderr(m_cct) << "failed to remove mirror image state: " - << cpp_strerror(*result) << dendl; - return m_on_finish; - } else { - *result = 0; + << cpp_strerror(r) << dendl; + finish(r); + return; } if (m_from_trash_remove) { // both the id object and the directory entry have been removed in // a previous call to trash_move. - - *result = 0; - return m_on_finish; + finish(0); + return; } remove_id_object(); - return nullptr; } template @@ -604,11 +630,11 @@ void RemoveRequest::remove_v1_image() { template void RemoveRequest::handle_remove_v1_image(int r) { - ldout(m_cct, 20) << ": r=" << r << dendl; + ldout(m_cct, 20) << "r=" << r << dendl; m_old_format = (r == 0); - if ((r == 0) || ((r < 0) && !m_unknown_format)) { - if ((r < 0) && (r != -ENOENT)) { + if (r == 0 || (r < 0 && !m_unknown_format)) { + if (r < 0 && r != -ENOENT) { lderr(m_cct) << "error removing image from v1 directory: " << cpp_strerror(r) << dendl; } @@ -656,25 +682,26 @@ void RemoveRequest::dir_get_image_id() { } template -Context *RemoveRequest::handle_dir_get_image_id(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_dir_get_image_id(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) && (*result != -ENOENT)) { - lderr(m_cct) << "error fetching image id: " << cpp_strerror(*result) + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "error fetching image id: " << cpp_strerror(r) << dendl; - return m_on_finish; + finish(r); + return; } - if (!*result) { + if (r == 0) { bufferlist::iterator iter = m_out_bl.begin(); - *result = librbd::cls_client::dir_get_id_finish(&iter, &m_image_id); - if (*result < 0) { - return m_on_finish; + r = librbd::cls_client::dir_get_id_finish(&iter, &m_image_id); + if (r < 0) { + finish(r); + return; } } remove_header_v2(); - return nullptr; } template @@ -694,25 +721,26 @@ void RemoveRequest::dir_get_image_name() { } template -Context *RemoveRequest::handle_dir_get_image_name(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_dir_get_image_name(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) && (*result != -ENOENT)) { - lderr(m_cct) << "error fetching image name: " << cpp_strerror(*result) + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "error fetching image name: " << cpp_strerror(r) << dendl; - return m_on_finish; + finish(r); + return; } - if (!*result) { + if (r == 0) { bufferlist::iterator iter = m_out_bl.begin(); - *result = librbd::cls_client::dir_get_name_finish(&iter, &m_image_name); - if (*result < 0) { - return m_on_finish; + r = librbd::cls_client::dir_get_name_finish(&iter, &m_image_name); + if (r < 0) { + finish(r); + return; } } remove_header_v2(); - return nullptr; } template @@ -728,17 +756,17 @@ void RemoveRequest::remove_id_object() { } template -Context *RemoveRequest::handle_remove_id_object(int *result) { - ldout(m_cct, 20) << ": r=" << *result << dendl; +void RemoveRequest::handle_remove_id_object(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) && (*result != -ENOENT)) { - lderr(m_cct) << "error removing id object: " << cpp_strerror(*result) + if (r < 0 && r != -ENOENT) { + lderr(m_cct) << "error removing id object: " << cpp_strerror(r) << dendl; - return m_on_finish; + finish(r); + return; } dir_remove_image(); - return nullptr; } template @@ -757,15 +785,23 @@ void RemoveRequest::dir_remove_image() { } template -Context *RemoveRequest::handle_dir_remove_image(int *result) { - ldout(m_cct, 20) << ":r =" << *result << dendl; +void RemoveRequest::handle_dir_remove_image(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((*result < 0) && (*result != -ENOENT)) { + if (r < 0 && r != -ENOENT) { lderr(m_cct) << "error removing image from v2 directory: " - << cpp_strerror(*result) << dendl; + << cpp_strerror(r) << dendl; } - return m_on_finish; + finish(r); +} + +template +void RemoveRequest::finish(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + m_on_finish->complete(r); + delete this; } } // namespace image diff --git a/ceph/src/librbd/image/RemoveRequest.h b/ceph/src/librbd/image/RemoveRequest.h index 939abd49d..05adeaa18 100644 --- a/ceph/src/librbd/image/RemoveRequest.h +++ b/ceph/src/librbd/image/RemoveRequest.h @@ -118,55 +118,65 @@ private: bool m_unknown_format = true; ImageCtxT *m_image_ctx; + decltype(m_image_ctx->exclusive_lock) m_exclusive_lock = nullptr; + int m_ret_val = 0; bufferlist m_out_bl; std::list m_watchers; + std::list m_mirror_watchers; void open_image(); - Context *handle_open_image(int *result); + void handle_open_image(int r); void send_journal_remove(); - Context* handle_journal_remove(int *result); + void handle_journal_remove(int r); void send_object_map_remove(); - Context* handle_object_map_remove(int *result); + void handle_object_map_remove(int r); void mirror_image_remove(); - Context* handle_mirror_image_remove(int *result); + void handle_mirror_image_remove(int r); void check_exclusive_lock(); void acquire_exclusive_lock(); - Context *handle_exclusive_lock(int *result); - Context *handle_exclusive_lock_force(int *result); + void handle_exclusive_lock(int r); + void handle_exclusive_lock_force(int r); void validate_image_removal(); void check_image_snaps(); - void filter_out_mirror_watchers(); + void list_image_watchers(); + void handle_list_image_watchers(int r); + + void get_mirror_image(); + void handle_get_mirror_image(int r); + + void list_mirror_watchers(); + void handle_list_mirror_watchers(int r); + void check_image_watchers(); - Context *handle_check_image_watchers(int *result); - void check_image_consistency_group(); - Context *handle_check_image_consistency_group(int *result); + void check_group(); + void handle_check_group(int r); void trim_image(); - Context *handle_trim_image(int *result); + void handle_trim_image(int r); void remove_child(); - Context *handle_remove_child(int *result); + void handle_remove_child(int r); void send_disable_mirror(); - Context *handle_disable_mirror(int *result); + void handle_disable_mirror(int r); void send_close_image(int r); - Context *handle_send_close_image(int *result); + void handle_send_close_image(int r); void remove_header(); - Context *handle_remove_header(int *result); + void handle_remove_header(int r); void remove_header_v2(); - Context *handle_remove_header_v2(int *result); + void handle_remove_header_v2(int r); void remove_image(); @@ -176,16 +186,18 @@ private: void remove_v2_image(); void dir_get_image_id(); - Context *handle_dir_get_image_id(int *result); + void handle_dir_get_image_id(int r); void dir_get_image_name(); - Context *handle_dir_get_image_name(int *result); + void handle_dir_get_image_name(int r); void remove_id_object(); - Context *handle_remove_id_object(int *result); + void handle_remove_id_object(int r); void dir_remove_image(); - Context *handle_dir_remove_image(int *result); + void handle_dir_remove_image(int r); + + void finish(int r); }; } // namespace image diff --git a/ceph/src/librbd/internal.cc b/ceph/src/librbd/internal.cc index 64ebf9545..a712851c8 100644 --- a/ceph/src/librbd/internal.cc +++ b/ceph/src/librbd/internal.cc @@ -327,23 +327,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { } } - std::ostream &operator<<(std::ostream &os, rbd_image_options_t &opts) { - image_options_ref* opts_ = static_cast(opts); - - os << "["; - - for (image_options_t::const_iterator i = (*opts_)->begin(); - i != (*opts_)->end(); ++i) { - os << (i == (*opts_)->begin() ? "" : ", ") << image_option_name(i->first) - << "=" << i->second; - } - - os << "]"; - - return os; - } - - std::ostream &operator<<(std::ostream &os, ImageOptions &opts) { + std::ostream &operator<<(std::ostream &os, const ImageOptions &opts) { os << "["; const char *delimiter = ""; @@ -546,8 +530,12 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { bufferlist bl; int r = io_ctx.read(RBD_DIRECTORY, bl, 0, 0); - if (r < 0) + if (r < 0) { + if (r == -ENOENT) { + r = 0; + } return r; + } // old format images are in a tmap if (bl.length()) { @@ -1144,7 +1132,9 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { // might have been blacklisted by peer -- ensure we still own // the lock by pinging the OSD int r = ictx->exclusive_lock->assert_header_locked(); - if (r < 0) { + if (r == -EBUSY || r == -ENOENT) { + return 0; + } else if (r < 0) { return r; } @@ -1394,12 +1384,14 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { ictx->exclusive_lock->is_lock_owner(); if (is_locked) { C_SaferCond ctx; - ictx->exclusive_lock->shut_down(&ctx); + auto exclusive_lock = ictx->exclusive_lock; + exclusive_lock->shut_down(&ctx); ictx->owner_lock.put_read(); int r = ctx.wait(); if (r < 0) { lderr(cct) << "error shutting down exclusive lock" << dendl; } + delete exclusive_lock; } else { ictx->owner_lock.put_read(); } @@ -1479,6 +1471,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { if (r != -ENOENT) { lderr(cct) << "error listing rbd_trash entries: " << cpp_strerror(r) << dendl; + } else { + r = 0; } return r; } @@ -1848,7 +1842,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { m_dest->io_work_queue->aio_write(comp, m_offset + write_offset, write_length, std::move(*write_bl), - LIBRADOS_OP_FLAG_FADVISE_DONTNEED); + LIBRADOS_OP_FLAG_FADVISE_DONTNEED, + std::move(read_trace)); write_offset = offset; write_length = 0; } @@ -1858,6 +1853,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { gather_ctx->activate(); } + ZTracer::Trace read_trace; + private: SimpleThrottle *m_throttle; ImageCtx *m_dest; @@ -1897,10 +1894,16 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { } } + ZTracer::Trace trace; + if (cct->_conf->rbd_blkin_trace_all) { + trace.init("copy", &src->trace_endpoint); + } + RWLock::RLocker owner_lock(src->owner_lock); SimpleThrottle throttle(src->concurrent_management_ops, false); uint64_t period = src->get_stripe_period(); - unsigned fadvise_flags = LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL | LIBRADOS_OP_FLAG_FADVISE_NOCACHE; + unsigned fadvise_flags = LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL | + LIBRADOS_OP_FLAG_FADVISE_NOCACHE; for (uint64_t offset = 0; offset < src_size; offset += period) { if (throttle.pending_error()) { return throttle.wait_for_ret(); @@ -1908,11 +1911,16 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { uint64_t len = min(period, src_size - offset); bufferlist *bl = new bufferlist(); - Context *ctx = new C_CopyRead(&throttle, dest, offset, bl, sparse_size); - auto comp = io::AioCompletion::create_and_start(ctx, src, - io::AIO_TYPE_READ); - io::ImageRequest<>::aio_read(src, comp, {{offset, len}}, - io::ReadResult{bl}, fadvise_flags); + auto ctx = new C_CopyRead(&throttle, dest, offset, bl, sparse_size); + auto comp = io::AioCompletion::create_and_start( + ctx, src, io::AIO_TYPE_READ); + + io::ImageReadRequest<> req(*src, comp, {{offset, len}}, + io::ReadResult{bl}, fadvise_flags, + std::move(trace)); + ctx->read_trace = req.get_trace(); + + req.send(); prog_ctx.update_progress(offset, src_size); } @@ -2127,6 +2135,11 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { uint64_t period = ictx->get_stripe_period(); uint64_t left = mylen; + ZTracer::Trace trace; + if (ictx->cct->_conf->rbd_blkin_trace_all) { + trace.init("read_iterate", &ictx->trace_endpoint); + } + RWLock::RLocker owner_locker(ictx->owner_lock); start_time = ceph_clock_now(); while (left > 0) { @@ -2139,7 +2152,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { auto c = io::AioCompletion::create_and_start(&ctx, ictx, io::AIO_TYPE_READ); io::ImageRequest<>::aio_read(ictx, c, {{off, read_len}}, - io::ReadResult{&bl}, 0); + io::ReadResult{&bl}, 0, std::move(trace)); int ret = ctx.wait(); if (ret < 0) { @@ -2324,7 +2337,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { ictx->readahead.inc_pending(); ictx->aio_read_from_cache(q->oid, q->objectno, NULL, q->length, q->offset, - req_comp, 0); + req_comp, 0, nullptr); } } ictx->perfcounter->inc(l_librbd_readahead); diff --git a/ceph/src/librbd/io/AioCompletion.h b/ceph/src/librbd/io/AioCompletion.h index 0433ac945..a3edb1414 100644 --- a/ceph/src/librbd/io/AioCompletion.h +++ b/ceph/src/librbd/io/AioCompletion.h @@ -10,8 +10,8 @@ #include "include/utime.h" #include "include/rbd/librbd.hpp" -#include "librbd/AsyncOperation.h" #include "librbd/ImageCtx.h" +#include "librbd/io/AsyncOperation.h" #include "librbd/io/ReadResult.h" #include "librbd/io/Types.h" diff --git a/ceph/src/librbd/AsyncOperation.cc b/ceph/src/librbd/io/AsyncOperation.cc similarity index 94% rename from ceph/src/librbd/AsyncOperation.cc rename to ceph/src/librbd/io/AsyncOperation.cc index d6581c9e9..ca8daa4c0 100644 --- a/ceph/src/librbd/AsyncOperation.cc +++ b/ceph/src/librbd/io/AsyncOperation.cc @@ -1,6 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include "librbd/AsyncOperation.h" + +#include "librbd/io/AsyncOperation.h" #include "librbd/ImageCtx.h" #include "common/dout.h" #include "common/WorkQueue.h" @@ -8,9 +9,10 @@ #define dout_subsys ceph_subsys_rbd #undef dout_prefix -#define dout_prefix *_dout << "librbd::AsyncOperation: " +#define dout_prefix *_dout << "librbd::io::AsyncOperation: " namespace librbd { +namespace io { namespace { @@ -78,4 +80,5 @@ void AsyncOperation::add_flush_context(Context *on_finish) { m_flush_contexts.push_back(on_finish); } +} // namespace io } // namespace librbd diff --git a/ceph/src/librbd/AsyncOperation.h b/ceph/src/librbd/io/AsyncOperation.h similarity index 83% rename from ceph/src/librbd/AsyncOperation.h rename to ceph/src/librbd/io/AsyncOperation.h index e6c884970..5839a6964 100644 --- a/ceph/src/librbd/AsyncOperation.h +++ b/ceph/src/librbd/io/AsyncOperation.h @@ -1,7 +1,8 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#ifndef LIBRBD_ASYNC_OPERATION_H -#define LIBRBD_ASYNC_OPERATION_H + +#ifndef LIBRBD_IO_ASYNC_OPERATION_H +#define LIBRBD_IO_ASYNC_OPERATION_H #include "include/assert.h" #include "include/xlist.h" @@ -13,6 +14,8 @@ namespace librbd { class ImageCtx; +namespace io { + class AsyncOperation { public: @@ -43,6 +46,7 @@ private: }; +} // namespace io } // namespace librbd -#endif // LIBRBD_ASYNC_OPERATION_H +#endif // LIBRBD_IO_ASYNC_OPERATION_H diff --git a/ceph/src/librbd/io/CopyupRequest.cc b/ceph/src/librbd/io/CopyupRequest.cc index 0f1d34f20..aee2f14d7 100644 --- a/ceph/src/librbd/io/CopyupRequest.cc +++ b/ceph/src/librbd/io/CopyupRequest.cc @@ -35,9 +35,9 @@ class UpdateObjectMap : public C_AsyncObjectThrottle<> { public: UpdateObjectMap(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, uint64_t object_no, const std::vector *snap_ids, - size_t snap_id_idx) - : C_AsyncObjectThrottle(throttle, *image_ctx), - m_object_no(object_no), m_snap_ids(*snap_ids), m_snap_id_idx(snap_id_idx) + const ZTracer::Trace &trace, size_t snap_id_idx) + : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_no(object_no), + m_snap_ids(*snap_ids), m_trace(trace), m_snap_id_idx(snap_id_idx) { } @@ -49,7 +49,7 @@ public: assert(m_image_ctx.exclusive_lock->is_lock_owner()); assert(m_image_ctx.object_map != nullptr); bool sent = m_image_ctx.object_map->aio_update( - CEPH_NOSNAP, m_object_no, OBJECT_EXISTS, {}, this); + CEPH_NOSNAP, m_object_no, OBJECT_EXISTS, {}, m_trace, this); return (sent ? 0 : 1); } @@ -66,7 +66,7 @@ public: } bool sent = m_image_ctx.object_map->aio_update( - snap_id, m_object_no, state, {}, this); + snap_id, m_object_no, state, {}, m_trace, this); assert(sent); return 0; } @@ -74,6 +74,7 @@ public: private: uint64_t m_object_no; const std::vector &m_snap_ids; + const ZTracer::Trace &m_trace; size_t m_snap_id_idx; }; @@ -81,9 +82,12 @@ private: CopyupRequest::CopyupRequest(ImageCtx *ictx, const std::string &oid, - uint64_t objectno, Extents &&image_extents) + uint64_t objectno, Extents &&image_extents, + const ZTracer::Trace &parent_trace) : m_ictx(ictx), m_oid(oid), m_object_no(objectno), - m_image_extents(image_extents), m_state(STATE_READ_FROM_PARENT) + m_image_extents(image_extents), + m_trace(util::create_trace(*m_ictx, "copy-up", parent_trace)), + m_state(STATE_READ_FROM_PARENT) { m_async_op.start_op(*m_ictx); } @@ -151,7 +155,9 @@ bool CopyupRequest::send_copyup() { r = rados.ioctx_create2(m_ictx->data_ctx.get_id(), m_data_ctx); assert(r == 0); - r = m_data_ctx.aio_operate(m_oid, comp, ©up_op, 0, snaps); + r = m_data_ctx.aio_operate( + m_oid, comp, ©up_op, 0, snaps, + (m_trace.valid() ? m_trace.get_info() : nullptr)); assert(r == 0); comp->release(); } @@ -167,13 +173,16 @@ bool CopyupRequest::send_copyup() { for (size_t i=0; i *req = m_pending_requests[i]; ldout(m_ictx->cct, 20) << "add_copyup_ops " << req << dendl; - req->add_copyup_ops(&write_op); + bool set_hints = (i == 0); + req->add_copyup_ops(&write_op, set_hints); } assert(write_op.size() != 0); snaps.insert(snaps.end(), snapc.snaps.begin(), snapc.snaps.end()); librados::AioCompletion *comp = util::create_rados_callback(this); - r = m_ictx->data_ctx.aio_operate(m_oid, comp, &write_op); + r = m_ictx->data_ctx.aio_operate( + m_oid, comp, &write_op, snapc.seq, snaps, + (m_trace.valid() ? m_trace.get_info() : nullptr)); assert(r == 0); comp->release(); } @@ -203,7 +212,7 @@ void CopyupRequest::send() << ", extents " << m_image_extents << dendl; ImageRequest<>::aio_read(m_ictx->parent, comp, std::move(m_image_extents), - ReadResult{&m_copyup_data}, 0); + ReadResult{&m_copyup_data}, 0, m_trace); } void CopyupRequest::complete(int r) @@ -327,7 +336,8 @@ bool CopyupRequest::send_object_map_head() { if (may_update && (new_state != current_state) && m_ictx->object_map->aio_update( - CEPH_NOSNAP, m_object_no, new_state, current_state, this)) { + CEPH_NOSNAP, m_object_no, new_state, current_state, m_trace, + this)) { return false; } } @@ -349,7 +359,7 @@ bool CopyupRequest::send_object_map() { RWLock::RLocker owner_locker(m_ictx->owner_lock); AsyncObjectThrottle<>::ContextFactory context_factory( boost::lambda::bind(boost::lambda::new_ptr(), - boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids, + boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids, m_trace, boost::lambda::_2)); AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( NULL, *m_ictx, context_factory, util::create_context_callback(this), diff --git a/ceph/src/librbd/io/CopyupRequest.h b/ceph/src/librbd/io/CopyupRequest.h index d2902029c..c4aa6a259 100644 --- a/ceph/src/librbd/io/CopyupRequest.h +++ b/ceph/src/librbd/io/CopyupRequest.h @@ -4,16 +4,19 @@ #ifndef CEPH_LIBRBD_IO_COPYUP_REQUEST_H #define CEPH_LIBRBD_IO_COPYUP_REQUEST_H -#include "librbd/AsyncOperation.h" #include "include/int_types.h" #include "include/rados/librados.hpp" #include "include/buffer.h" +#include "common/zipkin_trace.h" +#include "librbd/io/AsyncOperation.h" #include "librbd/io/Types.h" #include #include #include +namespace ZTracer { struct Trace; } + namespace librbd { struct ImageCtx; @@ -26,7 +29,7 @@ template class ObjectRequest; class CopyupRequest { public: CopyupRequest(ImageCtx *ictx, const std::string &oid, uint64_t objectno, - Extents &&image_extents); + Extents &&image_extents, const ZTracer::Trace &parent_trace); ~CopyupRequest(); void append_request(ObjectRequest *req); @@ -77,6 +80,8 @@ private: std::string m_oid; uint64_t m_object_no; Extents m_image_extents; + ZTracer::Trace m_trace; + State m_state; ceph::bufferlist m_copyup_data; std::vector *> m_pending_requests; diff --git a/ceph/src/librbd/io/ImageRequest.cc b/ceph/src/librbd/io/ImageRequest.cc index e1a5ae1ca..80c7208a1 100644 --- a/ceph/src/librbd/io/ImageRequest.cc +++ b/ceph/src/librbd/io/ImageRequest.cc @@ -111,41 +111,47 @@ private: template void ImageRequest::aio_read(I *ictx, AioCompletion *c, Extents &&image_extents, - ReadResult &&read_result, int op_flags) { + ReadResult &&read_result, int op_flags, + const ZTracer::Trace &parent_trace) { ImageReadRequest req(*ictx, c, std::move(image_extents), - std::move(read_result), op_flags); + std::move(read_result), op_flags, parent_trace); req.send(); } template void ImageRequest::aio_write(I *ictx, AioCompletion *c, Extents &&image_extents, bufferlist &&bl, - int op_flags) { + int op_flags, + const ZTracer::Trace &parent_trace) { ImageWriteRequest req(*ictx, c, std::move(image_extents), std::move(bl), - op_flags); + op_flags, parent_trace); req.send(); } template void ImageRequest::aio_discard(I *ictx, AioCompletion *c, uint64_t off, uint64_t len, - bool skip_partial_discard) { - ImageDiscardRequest req(*ictx, c, off, len, skip_partial_discard); + bool skip_partial_discard, + const ZTracer::Trace &parent_trace) { + ImageDiscardRequest req(*ictx, c, off, len, skip_partial_discard, + parent_trace); req.send(); } template -void ImageRequest::aio_flush(I *ictx, AioCompletion *c) { - ImageFlushRequest req(*ictx, c); +void ImageRequest::aio_flush(I *ictx, AioCompletion *c, + const ZTracer::Trace &parent_trace) { + ImageFlushRequest req(*ictx, c, parent_trace); req.send(); } template void ImageRequest::aio_writesame(I *ictx, AioCompletion *c, uint64_t off, uint64_t len, - bufferlist &&bl, - int op_flags) { - ImageWriteSameRequest req(*ictx, c, off, len, std::move(bl), op_flags); + bufferlist &&bl, int op_flags, + const ZTracer::Trace &parent_trace) { + ImageWriteSameRequest req(*ictx, c, off, len, std::move(bl), op_flags, + parent_trace); req.send(); } @@ -204,9 +210,10 @@ void ImageRequest::fail(int r) { template ImageReadRequest::ImageReadRequest(I &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, - ReadResult &&read_result, - int op_flags) - : ImageRequest(image_ctx, aio_comp, std::move(image_extents)), + ReadResult &&read_result, int op_flags, + const ZTracer::Trace &parent_trace) + : ImageRequest(image_ctx, aio_comp, std::move(image_extents), "read", + parent_trace), m_op_flags(op_flags) { aio_comp->read_result = std::move(read_result); } @@ -279,16 +286,17 @@ void ImageReadRequest::send_request() { aio_comp); ObjectReadRequest *req = ObjectReadRequest::create( &image_ctx, extent.oid.name, extent.objectno, extent.offset, - extent.length, extent.buffer_extents, snap_id, true, req_comp, - m_op_flags); + extent.length, extent.buffer_extents, snap_id, true, m_op_flags, + this->m_trace, req_comp); req_comp->request = req; if (image_ctx.object_cacher) { C_ObjectCacheRead *cache_comp = new C_ObjectCacheRead(image_ctx, req); - image_ctx.aio_read_from_cache(extent.oid, extent.objectno, - &req->data(), extent.length, - extent.offset, cache_comp, m_op_flags); + image_ctx.aio_read_from_cache( + extent.oid, extent.objectno, &req->data(), extent.length, + extent.offset, cache_comp, m_op_flags, + (this->m_trace.valid() ? &this->m_trace : nullptr)); } else { req->send(); } @@ -469,9 +477,10 @@ void ImageWriteRequest::send_object_cache_requests( AioCompletion *aio_comp = this->m_aio_comp; C_AioRequest *req_comp = new C_AioRequest(aio_comp); - image_ctx.write_to_cache(object_extent.oid, bl, object_extent.length, - object_extent.offset, req_comp, m_op_flags, - journal_tid); + image_ctx.write_to_cache( + object_extent.oid, bl, object_extent.length, object_extent.offset, + req_comp, m_op_flags, journal_tid, + (this->m_trace.valid() ? &this->m_trace : nullptr)); } } @@ -499,7 +508,7 @@ ObjectRequestHandle *ImageWriteRequest::create_object_request( assemble_extent(object_extent, &bl); ObjectRequest *req = ObjectRequest::create_write( &image_ctx, object_extent.oid.name, object_extent.objectno, - object_extent.offset, bl, snapc, on_finish, m_op_flags); + object_extent.offset, bl, snapc, m_op_flags, this->m_trace, on_finish); return req; } @@ -600,16 +609,17 @@ ObjectRequestHandle *ImageDiscardRequest::create_object_request( if (object_extent.length == image_ctx.layout.object_size) { req = ObjectRequest::create_remove( &image_ctx, object_extent.oid.name, object_extent.objectno, snapc, - on_finish); + this->m_trace, on_finish); } else if (object_extent.offset + object_extent.length == image_ctx.layout.object_size) { req = ObjectRequest::create_truncate( &image_ctx, object_extent.oid.name, object_extent.objectno, - object_extent.offset, snapc, on_finish); + object_extent.offset, snapc, this->m_trace, on_finish); } else { req = ObjectRequest::create_zero( &image_ctx, object_extent.oid.name, object_extent.objectno, - object_extent.offset, object_extent.length, snapc, on_finish); + object_extent.offset, object_extent.length, snapc, + this->m_trace, on_finish); } return req; } @@ -774,9 +784,10 @@ void ImageWriteSameRequest::send_object_cache_requests( AioCompletion *aio_comp = this->m_aio_comp; C_AioRequest *req_comp = new C_AioRequest(aio_comp); - image_ctx.write_to_cache(object_extent.oid, bl, object_extent.length, - object_extent.offset, req_comp, m_op_flags, - journal_tid); + image_ctx.write_to_cache( + object_extent.oid, bl, object_extent.length, object_extent.offset, + req_comp, m_op_flags, journal_tid, + (this->m_trace.valid() ? &this->m_trace : nullptr)); } } @@ -807,13 +818,12 @@ ObjectRequestHandle *ImageWriteSameRequest::create_object_request( req = ObjectRequest::create_writesame( &image_ctx, object_extent.oid.name, object_extent.objectno, object_extent.offset, object_extent.length, - bl, snapc, on_finish, m_op_flags); + bl, snapc, m_op_flags, this->m_trace, on_finish); return req; } req = ObjectRequest::create_write( &image_ctx, object_extent.oid.name, object_extent.objectno, - object_extent.offset, - bl, snapc, on_finish, m_op_flags); + object_extent.offset, bl, snapc, m_op_flags, this->m_trace, on_finish); return req; } diff --git a/ceph/src/librbd/io/ImageRequest.h b/ceph/src/librbd/io/ImageRequest.h index 6ae7c289c..21b88b098 100644 --- a/ceph/src/librbd/io/ImageRequest.h +++ b/ceph/src/librbd/io/ImageRequest.h @@ -7,7 +7,9 @@ #include "include/int_types.h" #include "include/buffer_fwd.h" #include "common/snap_types.h" +#include "common/zipkin_trace.h" #include "osd/osd_types.h" +#include "librbd/Utils.h" #include "librbd/io/Types.h" #include #include @@ -27,18 +29,24 @@ class ImageRequest { public: typedef std::vector > Extents; - virtual ~ImageRequest() {} + virtual ~ImageRequest() { + m_trace.event("finish"); + } static void aio_read(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, ReadResult &&read_result, - int op_flags); + int op_flags, const ZTracer::Trace &parent_trace); static void aio_write(ImageCtxT *ictx, AioCompletion *c, - Extents &&image_extents, bufferlist &&bl, int op_flags); + Extents &&image_extents, bufferlist &&bl, int op_flags, + const ZTracer::Trace &parent_trace); static void aio_discard(ImageCtxT *ictx, AioCompletion *c, uint64_t off, - uint64_t len, bool skip_partial_discard); - static void aio_flush(ImageCtxT *ictx, AioCompletion *c); + uint64_t len, bool skip_partial_discard, + const ZTracer::Trace &parent_trace); + static void aio_flush(ImageCtxT *ictx, AioCompletion *c, + const ZTracer::Trace &parent_trace); static void aio_writesame(ImageCtxT *ictx, AioCompletion *c, uint64_t off, - uint64_t len, bufferlist &&bl, int op_flags); + uint64_t len, bufferlist &&bl, int op_flags, + const ZTracer::Trace &parent_trace); virtual bool is_write_op() const { return false; @@ -53,19 +61,28 @@ public: m_bypass_image_cache = true; } + inline const ZTracer::Trace &get_trace() const { + return m_trace; + } + protected: typedef std::list ObjectRequests; ImageCtxT &m_image_ctx; AioCompletion *m_aio_comp; Extents m_image_extents; + ZTracer::Trace m_trace; bool m_bypass_image_cache = false; ImageRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, - Extents &&image_extents) + Extents &&image_extents, const char *trace_name, + const ZTracer::Trace &parent_trace) : m_image_ctx(image_ctx), m_aio_comp(aio_comp), - m_image_extents(image_extents) { + m_image_extents(std::move(image_extents)), + m_trace(util::create_trace(image_ctx, trace_name, parent_trace)) { + m_trace.event("start"); } + virtual int clip_request(); virtual void send_request() = 0; @@ -82,7 +99,7 @@ public: ImageReadRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, ReadResult &&read_result, - int op_flags); + int op_flags, const ZTracer::Trace &parent_trace); protected: int clip_request() override; @@ -120,8 +137,10 @@ protected: typedef std::vector ObjectExtents; AbstractImageWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, - Extents &&image_extents) - : ImageRequest(image_ctx, aio_comp, std::move(image_extents)), + Extents &&image_extents, const char *trace_name, + const ZTracer::Trace &parent_trace) + : ImageRequest(image_ctx, aio_comp, std::move(image_extents), + trace_name, parent_trace), m_synchronous(false) { } @@ -156,9 +175,10 @@ public: using typename ImageRequest::Extents; ImageWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, - Extents &&image_extents, bufferlist &&bl, int op_flags) - : AbstractImageWriteRequest(image_ctx, aio_comp, - std::move(image_extents)), + Extents &&image_extents, bufferlist &&bl, int op_flags, + const ZTracer::Trace &parent_trace) + : AbstractImageWriteRequest( + image_ctx, aio_comp, std::move(image_extents), "write", parent_trace), m_bl(std::move(bl)), m_op_flags(op_flags) { } @@ -201,8 +221,10 @@ template class ImageDiscardRequest : public AbstractImageWriteRequest { public: ImageDiscardRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, - uint64_t off, uint64_t len, bool skip_partial_discard) - : AbstractImageWriteRequest(image_ctx, aio_comp, {{off, len}}), + uint64_t off, uint64_t len, bool skip_partial_discard, + const ZTracer::Trace &parent_trace) + : AbstractImageWriteRequest( + image_ctx, aio_comp, {{off, len}}, "discard", parent_trace), m_skip_partial_discard(skip_partial_discard) { } @@ -239,8 +261,9 @@ private: template class ImageFlushRequest : public ImageRequest { public: - ImageFlushRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp) - : ImageRequest(image_ctx, aio_comp, {}) { + ImageFlushRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, + const ZTracer::Trace &parent_trace) + : ImageRequest(image_ctx, aio_comp, {}, "flush", parent_trace) { } bool is_write_op() const override { @@ -269,8 +292,9 @@ class ImageWriteSameRequest : public AbstractImageWriteRequest { public: ImageWriteSameRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, uint64_t len, bufferlist &&bl, - int op_flags) - : AbstractImageWriteRequest(image_ctx, aio_comp, {{off, len}}), + int op_flags, const ZTracer::Trace &parent_trace) + : AbstractImageWriteRequest( + image_ctx, aio_comp, {{off, len}}, "writesame", parent_trace), m_data_bl(std::move(bl)), m_op_flags(op_flags) { } diff --git a/ceph/src/librbd/io/ImageRequestWQ.cc b/ceph/src/librbd/io/ImageRequestWQ.cc index d7c9fa352..2758790eb 100644 --- a/ceph/src/librbd/io/ImageRequestWQ.cc +++ b/ceph/src/librbd/io/ImageRequestWQ.cc @@ -3,6 +3,7 @@ #include "librbd/io/ImageRequestWQ.h" #include "common/errno.h" +#include "common/zipkin_trace.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageState.h" @@ -122,8 +123,14 @@ ssize_t ImageRequestWQ::writesame(uint64_t off, uint64_t len, bufferlist &&bl, void ImageRequestWQ::aio_read(AioCompletion *c, uint64_t off, uint64_t len, ReadResult &&read_result, int op_flags, bool native_async) { - c->init_time(&m_image_ctx, AIO_TYPE_READ); CephContext *cct = m_image_ctx.cct; + ZTracer::Trace trace; + if (cct->_conf->rbd_blkin_trace_all) { + trace.init("wq: read", &m_image_ctx.trace_endpoint); + trace.event("start"); + } + + c->init_time(&m_image_ctx, AIO_TYPE_READ); ldout(cct, 20) << "ictx=" << &m_image_ctx << ", " << "completion=" << c << ", off=" << off << ", " << "len=" << len << ", " << "flags=" << op_flags << dendl; @@ -149,20 +156,27 @@ void ImageRequestWQ::aio_read(AioCompletion *c, uint64_t off, uint64_t len, if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty() || lock_required) { queue(new ImageReadRequest<>(m_image_ctx, c, {{off, len}}, - std::move(read_result), op_flags)); + std::move(read_result), op_flags, trace)); } else { c->start_op(); ImageRequest<>::aio_read(&m_image_ctx, c, {{off, len}}, - std::move(read_result), op_flags); + std::move(read_result), op_flags, trace); finish_in_flight_op(); } + trace.event("finish"); } void ImageRequestWQ::aio_write(AioCompletion *c, uint64_t off, uint64_t len, bufferlist &&bl, int op_flags, bool native_async) { - c->init_time(&m_image_ctx, AIO_TYPE_WRITE); CephContext *cct = m_image_ctx.cct; + ZTracer::Trace trace; + if (cct->_conf->rbd_blkin_trace_all) { + trace.init("wq: write", &m_image_ctx.trace_endpoint); + trace.event("init"); + } + + c->init_time(&m_image_ctx, AIO_TYPE_WRITE); ldout(cct, 20) << "ictx=" << &m_image_ctx << ", " << "completion=" << c << ", off=" << off << ", " << "len=" << len << ", flags=" << op_flags << dendl; @@ -178,20 +192,27 @@ void ImageRequestWQ::aio_write(AioCompletion *c, uint64_t off, uint64_t len, RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked()) { queue(new ImageWriteRequest<>(m_image_ctx, c, {{off, len}}, - std::move(bl), op_flags)); + std::move(bl), op_flags, trace)); } else { c->start_op(); ImageRequest<>::aio_write(&m_image_ctx, c, {{off, len}}, - std::move(bl), op_flags); + std::move(bl), op_flags, trace); finish_in_flight_op(); } + trace.event("finish"); } void ImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off, uint64_t len, bool skip_partial_discard, bool native_async) { - c->init_time(&m_image_ctx, AIO_TYPE_DISCARD); CephContext *cct = m_image_ctx.cct; + ZTracer::Trace trace; + if (cct->_conf->rbd_blkin_trace_all) { + trace.init("wq: discard", &m_image_ctx.trace_endpoint); + trace.event("init"); + } + + c->init_time(&m_image_ctx, AIO_TYPE_DISCARD); ldout(cct, 20) << "ictx=" << &m_image_ctx << ", " << "completion=" << c << ", off=" << off << ", len=" << len << dendl; @@ -206,17 +227,26 @@ void ImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off, RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked()) { - queue(new ImageDiscardRequest<>(m_image_ctx, c, off, len, skip_partial_discard)); + queue(new ImageDiscardRequest<>(m_image_ctx, c, off, len, + skip_partial_discard, trace)); } else { c->start_op(); - ImageRequest<>::aio_discard(&m_image_ctx, c, off, len, skip_partial_discard); + ImageRequest<>::aio_discard(&m_image_ctx, c, off, len, + skip_partial_discard, trace); finish_in_flight_op(); } + trace.event("finish"); } void ImageRequestWQ::aio_flush(AioCompletion *c, bool native_async) { - c->init_time(&m_image_ctx, AIO_TYPE_FLUSH); CephContext *cct = m_image_ctx.cct; + ZTracer::Trace trace; + if (cct->_conf->rbd_blkin_trace_all) { + trace.init("wq: flush", &m_image_ctx.trace_endpoint); + trace.event("init"); + } + + c->init_time(&m_image_ctx, AIO_TYPE_FLUSH); ldout(cct, 20) << "ictx=" << &m_image_ctx << ", " << "completion=" << c << dendl; @@ -230,18 +260,25 @@ void ImageRequestWQ::aio_flush(AioCompletion *c, bool native_async) { RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty()) { - queue(new ImageFlushRequest<>(m_image_ctx, c)); + queue(new ImageFlushRequest<>(m_image_ctx, c, trace)); } else { - ImageRequest<>::aio_flush(&m_image_ctx, c); + ImageRequest<>::aio_flush(&m_image_ctx, c, trace); finish_in_flight_op(); } + trace.event("finish"); } void ImageRequestWQ::aio_writesame(AioCompletion *c, uint64_t off, uint64_t len, bufferlist &&bl, int op_flags, bool native_async) { - c->init_time(&m_image_ctx, AIO_TYPE_WRITESAME); CephContext *cct = m_image_ctx.cct; + ZTracer::Trace trace; + if (cct->_conf->rbd_blkin_trace_all) { + trace.init("wq: writesame", &m_image_ctx.trace_endpoint); + trace.event("init"); + } + + c->init_time(&m_image_ctx, AIO_TYPE_WRITESAME); ldout(cct, 20) << "ictx=" << &m_image_ctx << ", " << "completion=" << c << ", off=" << off << ", " << "len=" << len << ", data_len = " << bl.length() << ", " @@ -258,13 +295,14 @@ void ImageRequestWQ::aio_writesame(AioCompletion *c, uint64_t off, uint64_t len, RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked()) { queue(new ImageWriteSameRequest<>(m_image_ctx, c, off, len, std::move(bl), - op_flags)); + op_flags, trace)); } else { c->start_op(); ImageRequest<>::aio_writesame(&m_image_ctx, c, off, len, std::move(bl), - op_flags); + op_flags, trace); finish_in_flight_op(); } + trace.event("finish"); } void ImageRequestWQ::shut_down(Context *on_shutdown) { diff --git a/ceph/src/librbd/io/ObjectRequest.cc b/ceph/src/librbd/io/ObjectRequest.cc index 97cd2e408..6e16d8024 100644 --- a/ceph/src/librbd/io/ObjectRequest.cc +++ b/ceph/src/librbd/io/ObjectRequest.cc @@ -35,9 +35,10 @@ ObjectRequest* ObjectRequest::create_remove(I *ictx, const std::string &oid, uint64_t object_no, const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion) { return new ObjectRemoveRequest(util::get_image_ctx(ictx), oid, object_no, - snapc, completion); + snapc, parent_trace, completion); } template @@ -45,9 +46,10 @@ ObjectRequest* ObjectRequest::create_truncate(I *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, const ::SnapContext &snapc, - Context *completion) { + const ZTracer::Trace &parent_trace, + Context *completion) { return new ObjectTruncateRequest(util::get_image_ctx(ictx), oid, object_no, - object_off, snapc, completion); + object_off, snapc, parent_trace, completion); } template @@ -55,10 +57,12 @@ ObjectRequest* ObjectRequest::create_write(I *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, const ceph::bufferlist &data, - const ::SnapContext &snapc, - Context *completion, int op_flags) { + const ::SnapContext &snapc, int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion) { return new ObjectWriteRequest(util::get_image_ctx(ictx), oid, object_no, - object_off, data, snapc, completion, op_flags); + object_off, data, snapc, op_flags, parent_trace, + completion); } template @@ -67,9 +71,11 @@ ObjectRequest::create_zero(I *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, uint64_t object_len, const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion) { return new ObjectZeroRequest(util::get_image_ctx(ictx), oid, object_no, - object_off, object_len, snapc, completion); + object_off, object_len, snapc, parent_trace, + completion); } template @@ -78,21 +84,29 @@ ObjectRequest::create_writesame(I *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, uint64_t object_len, const ceph::bufferlist &data, - const ::SnapContext &snapc, - Context *completion, int op_flags) { + const ::SnapContext &snapc, int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion) { return new ObjectWriteSameRequest(util::get_image_ctx(ictx), oid, object_no, object_off, object_len, data, snapc, - completion, op_flags); + op_flags, parent_trace, completion); } template ObjectRequest::ObjectRequest(ImageCtx *ictx, const std::string &oid, uint64_t objectno, uint64_t off, uint64_t len, librados::snap_t snap_id, - Context *completion, bool hide_enoent) + bool hide_enoent, const char *trace_name, + const ZTracer::Trace &trace, + Context *completion) : m_ictx(ictx), m_oid(oid), m_object_no(objectno), m_object_off(off), m_object_len(len), m_snap_id(snap_id), m_completion(completion), - m_hide_enoent(hide_enoent) { + m_hide_enoent(hide_enoent), + m_trace(util::create_trace(*ictx, "", trace)) { + if (m_trace.valid()) { + m_trace.copy_name(trace_name + std::string(" ") + oid); + m_trace.event("start"); + } Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no, 0, m_ictx->layout.object_size, m_parent_extents); @@ -159,9 +173,11 @@ ObjectReadRequest::ObjectReadRequest(I *ictx, const std::string &oid, uint64_t objectno, uint64_t offset, uint64_t len, Extents& be, librados::snap_t snap_id, bool sparse, - Context *completion, int op_flags) + int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion) : ObjectRequest(util::get_image_ctx(ictx), oid, objectno, offset, len, - snap_id, completion, false), + snap_id, false, "read", parent_trace, completion), m_buffer_extents(be), m_tried_parent(false), m_sparse(sparse), m_op_flags(op_flags), m_state(LIBRBD_AIO_READ_FLAT) { guard_read(); @@ -201,8 +217,6 @@ bool ObjectReadRequest::should_complete(int r) RWLock::RLocker parent_locker(image_ctx->parent_lock); if (image_ctx->parent == NULL) { ldout(image_ctx->cct, 20) << "parent is gone; do nothing" << dendl; - m_state = LIBRBD_AIO_READ_FLAT; - finished = false; break; } @@ -289,8 +303,9 @@ void ObjectReadRequest::send() { librados::AioCompletion *rados_completion = util::create_rados_callback(this); - int r = image_ctx->data_ctx.aio_operate(this->m_oid, rados_completion, &op, - flags, nullptr); + int r = image_ctx->data_ctx.aio_operate( + this->m_oid, rados_completion, &op, flags, nullptr, + (this->m_trace.valid() ? this->m_trace.get_info() : nullptr)); assert(r == 0); rados_completion->release(); @@ -320,7 +335,7 @@ void ObjectReadRequest::send_copyup() // create and kick off a CopyupRequest CopyupRequest *new_req = new CopyupRequest( image_ctx, this->m_oid, this->m_object_no, - std::move(this->m_parent_extents)); + std::move(this->m_parent_extents), this->m_trace); this->m_parent_extents.clear(); image_ctx->copyup_list[this->m_object_no] = new_req; @@ -339,7 +354,7 @@ void ObjectReadRequest::read_from_parent(Extents&& parent_extents) << " extents " << parent_extents << dendl; ImageRequest<>::aio_read(image_ctx->parent, parent_completion, std::move(parent_extents), - ReadResult{&m_read_data}, 0); + ReadResult{&m_read_data}, 0, this->m_trace); } /** write **/ @@ -350,10 +365,12 @@ AbstractObjectWriteRequest::AbstractObjectWriteRequest(ImageCtx *ictx, uint64_t object_off, uint64_t len, const ::SnapContext &snapc, - Context *completion, - bool hide_enoent) + bool hide_enoent, + const char *trace_name, + const ZTracer::Trace &parent_trace, + Context *completion) : ObjectRequest(ictx, oid, object_no, object_off, len, CEPH_NOSNAP, - completion, hide_enoent), + hide_enoent, trace_name, parent_trace, completion), m_state(LIBRBD_AIO_WRITE_FLAT), m_snap_seq(snapc.seq.val) { m_snaps.insert(m_snaps.end(), snapc.snaps.begin(), snapc.snaps.end()); @@ -470,7 +487,7 @@ void AbstractObjectWriteRequest::send_pre_object_map_update() { m_state = LIBRBD_AIO_WRITE_PRE; if (m_ictx->object_map->aio_update( - CEPH_NOSNAP, m_object_no, new_state, {}, this)) { + CEPH_NOSNAP, m_object_no, new_state, {}, this->m_trace, this)) { return; } } @@ -496,7 +513,8 @@ bool AbstractObjectWriteRequest::send_post_object_map_update() { m_state = LIBRBD_AIO_WRITE_POST; if (m_ictx->object_map->aio_update( - CEPH_NOSNAP, m_object_no, OBJECT_NONEXISTENT, OBJECT_PENDING, this)) { + CEPH_NOSNAP, m_object_no, OBJECT_NONEXISTENT, OBJECT_PENDING, + this->m_trace, this)) { return false; } @@ -527,7 +545,8 @@ void AbstractObjectWriteRequest::send_copyup() if (it == m_ictx->copyup_list.end()) { CopyupRequest *new_req = new CopyupRequest(m_ictx, m_oid, m_object_no, - std::move(m_parent_extents)); + std::move(m_parent_extents), + this->m_trace); m_parent_extents.clear(); // make sure to wait on this CopyupRequest @@ -548,13 +567,14 @@ void AbstractObjectWriteRequest::send_write_op() guard_write(); } - add_write_ops(&m_write); + add_write_ops(&m_write, true); assert(m_write.size() != 0); librados::AioCompletion *rados_completion = util::create_rados_callback(this); - int r = m_ictx->data_ctx.aio_operate(m_oid, rados_completion, &m_write, - m_snap_seq, m_snaps); + int r = m_ictx->data_ctx.aio_operate( + m_oid, rados_completion, &m_write, m_snap_seq, m_snaps, + (this->m_trace.valid() ? this->m_trace.get_info() : nullptr)); assert(r == 0); rados_completion->release(); } @@ -577,9 +597,10 @@ void AbstractObjectWriteRequest::handle_write_guard() } } -void ObjectWriteRequest::add_write_ops(librados::ObjectWriteOperation *wr) { +void ObjectWriteRequest::add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) { RWLock::RLocker snap_locker(m_ictx->snap_lock); - if (m_ictx->enable_alloc_hint && + if (set_hints && m_ictx->enable_alloc_hint && (m_ictx->object_map == nullptr || !m_object_exist)) { wr->set_alloc_hint(m_ictx->get_object_size(), m_ictx->get_object_size()); } @@ -612,14 +633,34 @@ void ObjectRemoveRequest::guard_write() { } } void ObjectRemoveRequest::send_write() { - ldout(m_ictx->cct, 20) << m_oid << " " << m_object_off - << "~" << m_object_len << dendl; - send_pre_object_map_update(); + ldout(m_ictx->cct, 20) << m_oid << " remove " << " object exist " + << m_object_exist << dendl; + if (!m_object_exist && !has_parent()) { + m_state = LIBRBD_AIO_WRITE_FLAT; + Context *ctx = util::create_context_callback(this); + m_ictx->op_work_queue->queue(ctx, 0); + } else { + send_pre_object_map_update(); + } } void ObjectTruncateRequest::send_write() { - ldout(m_ictx->cct, 20) << m_oid << " truncate " << m_object_off << dendl; - if (!m_object_exist && ! has_parent()) { + ldout(m_ictx->cct, 20) << m_oid << " truncate " << m_object_off + << " object exist " << m_object_exist << dendl; + if (!m_object_exist && !has_parent()) { + m_state = LIBRBD_AIO_WRITE_FLAT; + Context *ctx = util::create_context_callback(this); + m_ictx->op_work_queue->queue(ctx, 0); + } else { + AbstractObjectWriteRequest::send_write(); + } +} + +void ObjectZeroRequest::send_write() { + ldout(m_ictx->cct, 20) << m_oid << " zero " << m_object_off << "~" + << m_object_len << " object exist " << m_object_exist + << dendl; + if (!m_object_exist && !has_parent()) { m_state = LIBRBD_AIO_WRITE_FLAT; Context *ctx = util::create_context_callback(this); m_ictx->op_work_queue->queue(ctx, 0); @@ -628,9 +669,10 @@ void ObjectTruncateRequest::send_write() { } } -void ObjectWriteSameRequest::add_write_ops(librados::ObjectWriteOperation *wr) { +void ObjectWriteSameRequest::add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) { RWLock::RLocker snap_locker(m_ictx->snap_lock); - if (m_ictx->enable_alloc_hint && + if (set_hints && m_ictx->enable_alloc_hint && (m_ictx->object_map == nullptr || !m_object_exist)) { wr->set_alloc_hint(m_ictx->get_object_size(), m_ictx->get_object_size()); } diff --git a/ceph/src/librbd/io/ObjectRequest.h b/ceph/src/librbd/io/ObjectRequest.h index f57bbe0b7..a236778c6 100644 --- a/ceph/src/librbd/io/ObjectRequest.h +++ b/ceph/src/librbd/io/ObjectRequest.h @@ -5,13 +5,12 @@ #define CEPH_LIBRBD_IO_OBJECT_REQUEST_H #include "include/int_types.h" - -#include - -#include "common/snap_types.h" #include "include/buffer.h" #include "include/rados/librados.hpp" +#include "common/snap_types.h" +#include "common/zipkin_trace.h" #include "librbd/ObjectMap.h" +#include class Context; @@ -50,23 +49,27 @@ public: const std::string &oid, uint64_t object_no, const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion); static ObjectRequest* create_truncate(ImageCtxT *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion); static ObjectRequest* create_write(ImageCtxT *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, const ceph::bufferlist &data, - const ::SnapContext &snapc, - Context *completion, int op_flags); + const ::SnapContext &snapc, int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion); static ObjectRequest* create_zero(ImageCtxT *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, uint64_t object_len, const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion); static ObjectRequest* create_writesame(ImageCtxT *ictx, const std::string &oid, @@ -75,15 +78,22 @@ public: uint64_t object_len, const ceph::bufferlist &data, const ::SnapContext &snapc, - Context *completion, int op_flags); + int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion); ObjectRequest(ImageCtx *ictx, const std::string &oid, uint64_t objectno, uint64_t off, uint64_t len, - librados::snap_t snap_id, - Context *completion, bool hide_enoent); - ~ObjectRequest() override {} + librados::snap_t snap_id, bool hide_enoent, + const char *trace_name, const ZTracer::Trace &parent_trace, + Context *completion); + ~ObjectRequest() override { + m_trace.event("finish"); + } - virtual void add_copyup_ops(librados::ObjectWriteOperation *wr) {}; + virtual void add_copyup_ops(librados::ObjectWriteOperation *wr, + bool set_hints) { + }; void complete(int r) override; @@ -111,6 +121,7 @@ protected: Context *m_completion; Extents m_parent_extents; bool m_hide_enoent; + ZTracer::Trace m_trace; private: bool m_has_parent = false; @@ -126,16 +137,19 @@ public: uint64_t objectno, uint64_t offset, uint64_t len, Extents &buffer_extents, librados::snap_t snap_id, bool sparse, - Context *completion, int op_flags) { + int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion) { return new ObjectReadRequest(ictx, oid, objectno, offset, len, - buffer_extents, snap_id, sparse, completion, - op_flags); + buffer_extents, snap_id, sparse, op_flags, + parent_trace, completion); } ObjectReadRequest(ImageCtxT *ictx, const std::string &oid, uint64_t objectno, uint64_t offset, uint64_t len, Extents& buffer_extents, librados::snap_t snap_id, - bool sparse, Context *completion, int op_flags); + bool sparse, int op_flags, + const ZTracer::Trace &parent_trace, Context *completion); bool should_complete(int r) override; void send() override; @@ -207,11 +221,14 @@ public: AbstractObjectWriteRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, uint64_t len, const ::SnapContext &snapc, - Context *completion, bool hide_enoent); + bool hide_enoent, const char *trace_name, + const ZTracer::Trace &parent_trace, + Context *completion); - void add_copyup_ops(librados::ObjectWriteOperation *wr) override + void add_copyup_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override { - add_write_ops(wr); + add_write_ops(wr, set_hints); } bool should_complete(int r) override; @@ -270,7 +287,8 @@ protected: bool m_object_exist; bool m_guard = true; - virtual void add_write_ops(librados::ObjectWriteOperation *wr) = 0; + virtual void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) = 0; virtual void guard_write(); virtual bool post_object_map_update() { return false; @@ -290,10 +308,11 @@ class ObjectWriteRequest : public AbstractObjectWriteRequest { public: ObjectWriteRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, const ceph::bufferlist &data, - const ::SnapContext &snapc, Context *completion, - int op_flags) + const ::SnapContext &snapc, int op_flags, + const ZTracer::Trace &parent_trace, Context *completion) : AbstractObjectWriteRequest(ictx, oid, object_no, object_off, - data.length(), snapc, completion, false), + data.length(), snapc, false, "write", + parent_trace, completion), m_write_data(data), m_op_flags(op_flags) { } @@ -311,7 +330,8 @@ public: } protected: - void add_write_ops(librados::ObjectWriteOperation *wr) override; + void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override; void send_write() override; @@ -324,9 +344,9 @@ class ObjectRemoveRequest : public AbstractObjectWriteRequest { public: ObjectRemoveRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, const ::SnapContext &snapc, - Context *completion) - : AbstractObjectWriteRequest(ictx, oid, object_no, 0, 0, snapc, completion, - true), + const ZTracer::Trace &parent_trace, Context *completion) + : AbstractObjectWriteRequest(ictx, oid, object_no, 0, 0, snapc, true, + "remote", parent_trace, completion), m_object_state(OBJECT_NONEXISTENT) { } @@ -358,7 +378,8 @@ public: void send_write() override; protected: - void add_write_ops(librados::ObjectWriteOperation *wr) override { + void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override { if (has_parent()) { wr->truncate(0); } else { @@ -376,10 +397,10 @@ public: // update is needed. pre update is decided as usual (by checking // the state of the object in the map). ObjectTrimRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, - const ::SnapContext &snapc, Context *completion, - bool post_object_map_update) - : AbstractObjectWriteRequest(ictx, oid, object_no, 0, 0, snapc, completion, - true), + const ::SnapContext &snapc, bool post_object_map_update, + Context *completion) + : AbstractObjectWriteRequest(ictx, oid, object_no, 0, 0, snapc, true, + "trim", {}, completion), m_post_object_map_update(post_object_map_update) { } @@ -397,7 +418,8 @@ public: } protected: - void add_write_ops(librados::ObjectWriteOperation *wr) override { + void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override { wr->remove(); } @@ -409,9 +431,10 @@ class ObjectTruncateRequest : public AbstractObjectWriteRequest { public: ObjectTruncateRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, - const ::SnapContext &snapc, Context *completion) + const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion) : AbstractObjectWriteRequest(ictx, oid, object_no, object_off, 0, snapc, - completion, true) { + true, "truncate", parent_trace, completion) { } const char* get_op_type() const override { @@ -429,7 +452,8 @@ public: void send_write() override; protected: - void add_write_ops(librados::ObjectWriteOperation *wr) override { + void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override { wr->truncate(m_object_off); } }; @@ -438,9 +462,11 @@ class ObjectZeroRequest : public AbstractObjectWriteRequest { public: ObjectZeroRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, uint64_t object_off, uint64_t object_len, - const ::SnapContext &snapc, Context *completion) + const ::SnapContext &snapc, + const ZTracer::Trace &parent_trace, Context *completion) : AbstractObjectWriteRequest(ictx, oid, object_no, object_off, object_len, - snapc, completion, true) { + snapc, true, "zero", parent_trace, + completion) { } const char* get_op_type() const override { @@ -452,21 +478,26 @@ public: return true; } + void send_write() override; + protected: - void add_write_ops(librados::ObjectWriteOperation *wr) override { + void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override { wr->zero(m_object_off, m_object_len); } }; class ObjectWriteSameRequest : public AbstractObjectWriteRequest { public: - ObjectWriteSameRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no, - uint64_t object_off, uint64_t object_len, - const ceph::bufferlist &data, - const ::SnapContext &snapc, Context *completion, - int op_flags) + ObjectWriteSameRequest(ImageCtx *ictx, const std::string &oid, + uint64_t object_no, uint64_t object_off, + uint64_t object_len, const ceph::bufferlist &data, + const ::SnapContext &snapc, int op_flags, + const ZTracer::Trace &parent_trace, + Context *completion) : AbstractObjectWriteRequest(ictx, oid, object_no, object_off, - object_len, snapc, completion, false), + object_len, snapc, false, "writesame", + parent_trace, completion), m_write_data(data), m_op_flags(op_flags) { } @@ -480,7 +511,8 @@ public: } protected: - void add_write_ops(librados::ObjectWriteOperation *wr) override; + void add_write_ops(librados::ObjectWriteOperation *wr, + bool set_hints) override; void send_write() override; diff --git a/ceph/src/librbd/journal/Replay.cc b/ceph/src/librbd/journal/Replay.cc index 624b213b8..29289ac58 100644 --- a/ceph/src/librbd/journal/Replay.cc +++ b/ceph/src/librbd/journal/Replay.cc @@ -5,6 +5,7 @@ #include "common/dout.h" #include "common/errno.h" #include "common/WorkQueue.h" +#include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" #include "librbd/ImageState.h" #include "librbd/internal.h" @@ -118,6 +119,14 @@ struct ExecuteOp : public Context { ldout(cct, 20) << ": ExecuteOp::" << __func__ << dendl; RWLock::RLocker owner_locker(image_ctx.owner_lock); + + if (image_ctx.exclusive_lock == nullptr || + !image_ctx.exclusive_lock->accept_ops()) { + ldout(cct, 5) << ": lost exclusive lock -- skipping op" << dendl; + on_op_complete->complete(-ECANCELED); + return; + } + execute(event); } }; @@ -197,6 +206,14 @@ void Replay::process(const EventEntry &event_entry, on_ready = util::create_async_context_callback(m_image_ctx, on_ready); RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + if (m_image_ctx.exclusive_lock == nullptr || + !m_image_ctx.exclusive_lock->accept_ops()) { + ldout(cct, 5) << ": lost exclusive lock -- skipping event" << dendl; + m_image_ctx.op_work_queue->queue(on_safe, -ECANCELED); + on_ready->complete(0); + return; + } + boost::apply_visitor(EventVisitor(this, on_ready, on_safe), event_entry.event); } @@ -216,6 +233,7 @@ void Replay::shut_down(bool cancel_ops, Context *on_finish) { // safely commit any remaining AIO modify operations if ((m_in_flight_aio_flush + m_in_flight_aio_modify) != 0) { flush_comp = create_aio_flush_completion(nullptr); + assert(flush_comp != nullptr); } for (auto &op_event_pair : m_op_events) { @@ -240,6 +258,9 @@ void Replay::shut_down(bool cancel_ops, Context *on_finish) { } } + assert(!m_shut_down); + m_shut_down = true; + assert(m_flush_ctx == nullptr); if (m_in_flight_op_events > 0 || flush_comp != nullptr) { std::swap(m_flush_ctx, on_finish); @@ -249,7 +270,7 @@ void Replay::shut_down(bool cancel_ops, Context *on_finish) { // execute the following outside of lock scope if (flush_comp != nullptr) { RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - io::ImageRequest::aio_flush(&m_image_ctx, flush_comp); + io::ImageRequest::aio_flush(&m_image_ctx, flush_comp, {}); } if (on_finish != nullptr) { on_finish->complete(0); @@ -263,10 +284,13 @@ void Replay::flush(Context *on_finish) { Mutex::Locker locker(m_lock); aio_comp = create_aio_flush_completion( util::create_async_context_callback(m_image_ctx, on_finish)); + if (aio_comp == nullptr) { + return; + } } RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - io::ImageRequest::aio_flush(&m_image_ctx, aio_comp); + io::ImageRequest::aio_flush(&m_image_ctx, aio_comp, {}); } template @@ -318,14 +342,21 @@ void Replay::handle_event(const journal::AioDiscardEvent &event, auto aio_comp = create_aio_modify_completion(on_ready, on_safe, io::AIO_TYPE_DISCARD, &flush_required); + if (aio_comp == nullptr) { + return; + } + io::ImageRequest::aio_discard(&m_image_ctx, aio_comp, event.offset, - event.length, event.skip_partial_discard); + event.length, event.skip_partial_discard, + {}); if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); m_lock.Unlock(); - io::ImageRequest::aio_flush(&m_image_ctx, flush_comp); + if (flush_comp != nullptr) { + io::ImageRequest::aio_flush(&m_image_ctx, flush_comp, {}); + } } } @@ -340,15 +371,21 @@ void Replay::handle_event(const journal::AioWriteEvent &event, auto aio_comp = create_aio_modify_completion(on_ready, on_safe, io::AIO_TYPE_WRITE, &flush_required); + if (aio_comp == nullptr) { + return; + } + io::ImageRequest::aio_write(&m_image_ctx, aio_comp, {{event.offset, event.length}}, - std::move(data), 0); + std::move(data), 0, {}); if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); m_lock.Unlock(); - io::ImageRequest::aio_flush(&m_image_ctx, flush_comp); + if (flush_comp != nullptr) { + io::ImageRequest::aio_flush(&m_image_ctx, flush_comp, {}); + } } } @@ -363,8 +400,10 @@ void Replay::handle_event(const journal::AioFlushEvent &event, Mutex::Locker locker(m_lock); aio_comp = create_aio_flush_completion(on_safe); } - io::ImageRequest::aio_flush(&m_image_ctx, aio_comp); + if (aio_comp != nullptr) { + io::ImageRequest::aio_flush(&m_image_ctx, aio_comp, {}); + } on_ready->complete(0); } @@ -379,14 +418,20 @@ void Replay::handle_event(const journal::AioWriteSameEvent &event, auto aio_comp = create_aio_modify_completion(on_ready, on_safe, io::AIO_TYPE_WRITESAME, &flush_required); + if (aio_comp == nullptr) { + return; + } + io::ImageRequest::aio_writesame(&m_image_ctx, aio_comp, event.offset, - event.length, std::move(data), 0); + event.length, std::move(data), 0, {}); if (flush_required) { m_lock.Lock(); auto flush_comp = create_aio_flush_completion(nullptr); m_lock.Unlock(); - io::ImageRequest::aio_flush(&m_image_ctx, flush_comp); + if (flush_comp != nullptr) { + io::ImageRequest::aio_flush(&m_image_ctx, flush_comp, {}); + } } } @@ -860,6 +905,12 @@ Context *Replay::create_op_context_callback(uint64_t op_tid, Context *on_safe, OpEvent **op_event) { CephContext *cct = m_image_ctx.cct; + if (m_shut_down) { + ldout(cct, 5) << ": ignoring event after shut down" << dendl; + on_ready->complete(0); + m_image_ctx.op_work_queue->queue(on_safe, -ESHUTDOWN); + return nullptr; + } assert(m_lock.is_locked()); if (m_op_events.count(op_tid) != 0) { @@ -897,7 +948,10 @@ void Replay::handle_op_complete(uint64_t op_tid, int r) { op_event = std::move(op_it->second); m_op_events.erase(op_it); - shutting_down = (m_flush_ctx != nullptr); + if (m_shut_down) { + assert(m_flush_ctx != nullptr); + shutting_down = true; + } } assert(op_event.on_start_ready == nullptr || (r < 0 && r != -ERESTART)); @@ -957,6 +1011,13 @@ Replay::create_aio_modify_completion(Context *on_ready, Context *on_safe, CephContext *cct = m_image_ctx.cct; assert(m_on_aio_ready == nullptr); + if (m_shut_down) { + ldout(cct, 5) << ": ignoring event after shut down" << dendl; + on_ready->complete(0); + m_image_ctx.op_work_queue->queue(on_safe, -ESHUTDOWN); + return nullptr; + } + ++m_in_flight_aio_modify; m_aio_modify_unsafe_contexts.push_back(on_safe); @@ -996,6 +1057,15 @@ template io::AioCompletion *Replay::create_aio_flush_completion(Context *on_safe) { assert(m_lock.is_locked()); + CephContext *cct = m_image_ctx.cct; + if (m_shut_down) { + ldout(cct, 5) << ": ignoring event after shut down" << dendl; + if (on_safe != nullptr) { + m_image_ctx.op_work_queue->queue(on_safe, -ESHUTDOWN); + } + return nullptr; + } + ++m_in_flight_aio_flush; // associate all prior write/discard ops to this flush request diff --git a/ceph/src/librbd/journal/Replay.h b/ceph/src/librbd/journal/Replay.h index d4a65e089..5b2219851 100644 --- a/ceph/src/librbd/journal/Replay.h +++ b/ceph/src/librbd/journal/Replay.h @@ -126,6 +126,7 @@ private: OpEvents m_op_events; uint64_t m_in_flight_op_events = 0; + bool m_shut_down = false; Context *m_flush_ctx = nullptr; Context *m_on_aio_ready = nullptr; diff --git a/ceph/src/librbd/librbd.cc b/ceph/src/librbd/librbd.cc index 77d272283..1d5920fcc 100644 --- a/ceph/src/librbd/librbd.cc +++ b/ceph/src/librbd/librbd.cc @@ -1011,6 +1011,17 @@ namespace librbd { return stripe_count; } + int Image::get_create_timestamp(struct timespec *timestamp) + { + ImageCtx *ictx = (ImageCtx *)ctx; + tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(), + ictx->read_only); + utime_t time = ictx->get_create_timestamp(); + time.to_timespec(timestamp); + tracepoint(librbd, get_create_timestamp_exit, 0, timestamp); + return 0; + } + int Image::overlap(uint64_t *overlap) { ImageCtx *ictx = (ImageCtx *)ctx; @@ -2141,11 +2152,6 @@ extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size) tracepoint(librbd, list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id()); vector cpp_names; int r = librbd::list(io_ctx, cpp_names); - if (r == -ENOENT) { - tracepoint(librbd, list_exit, 0, *size); - return 0; - } - if (r < 0) { tracepoint(librbd, list_exit, r, *size); return r; @@ -2822,6 +2828,18 @@ extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count) return 0; } +extern "C" int rbd_get_create_timestamp(rbd_image_t image, + struct timespec *timestamp) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(), + ictx->read_only); + utime_t time = ictx->get_create_timestamp(); + time.to_timespec(timestamp); + tracepoint(librbd, get_create_timestamp_exit, 0, timestamp); + return 0; +} + extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; @@ -4038,14 +4056,6 @@ extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size) vector cpp_names; int r = librbd::list(io_ctx, cpp_names); - - if (r == -ENOENT) { - *size = 0; - *names = '\0'; - tracepoint(librbd, group_list_exit, 0); - return 0; - } - if (r < 0) { tracepoint(librbd, group_list_exit, r); return r; diff --git a/ceph/src/librbd/managed_lock/AcquireRequest.cc b/ceph/src/librbd/managed_lock/AcquireRequest.cc index 0249be2a1..83f5dbac1 100644 --- a/ceph/src/librbd/managed_lock/AcquireRequest.cc +++ b/ceph/src/librbd/managed_lock/AcquireRequest.cc @@ -146,8 +146,8 @@ void AcquireRequest::send_break_lock() { Context *ctx = create_context_callback< AcquireRequest, &AcquireRequest::handle_break_lock>(this); auto req = BreakRequest::create( - m_ioctx, m_work_queue, m_oid, m_locker, m_blacklist_on_break_lock, - m_blacklist_expire_seconds, false, ctx); + m_ioctx, m_work_queue, m_oid, m_locker, m_exclusive, + m_blacklist_on_break_lock, m_blacklist_expire_seconds, false, ctx); req->send(); } @@ -165,7 +165,8 @@ void AcquireRequest::handle_break_lock(int r) { return; } - send_get_locker(); + m_locker = {}; + send_lock(); } template diff --git a/ceph/src/librbd/managed_lock/AcquireRequest.h b/ceph/src/librbd/managed_lock/AcquireRequest.h index 16a5be36c..20af06933 100644 --- a/ceph/src/librbd/managed_lock/AcquireRequest.h +++ b/ceph/src/librbd/managed_lock/AcquireRequest.h @@ -47,15 +47,17 @@ private: * * | * v - * GET_LOCKER <---------------------------------------\ - * | ^ | - * | . (EBUSY && no cached locker) | - * | . | - * | . (EBUSY && cached locker) | - * \--> LOCK_IMAGE * * * * * * * * > BREAK_LOCK ---/ - * | - * v - * + * GET_LOCKER + * | ^ + * | . (EBUSY && no cached locker) + * | . + * | . (EBUSY && cached locker) + * \--> LOCK_IMAGE * * * * * * * * > BREAK_LOCK . . . . . + * | ^ | . + * | | | (success) . + * | \-------------------------/ . + * v . + * < . . . . . . . . . . . . . . . . . . . * * @endverbatim */ diff --git a/ceph/src/librbd/managed_lock/BreakRequest.cc b/ceph/src/librbd/managed_lock/BreakRequest.cc index 6c4d4d208..9a7fe10f3 100644 --- a/ceph/src/librbd/managed_lock/BreakRequest.cc +++ b/ceph/src/librbd/managed_lock/BreakRequest.cc @@ -10,6 +10,7 @@ #include "cls/lock/cls_lock_types.h" #include "librbd/ImageCtx.h" #include "librbd/Utils.h" +#include "librbd/managed_lock/GetLockerRequest.h" #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -48,12 +49,12 @@ struct C_BlacklistClient : public Context { template BreakRequest::BreakRequest(librados::IoCtx& ioctx, ContextWQ *work_queue, const std::string& oid, const Locker &locker, - bool blacklist_locker, + bool exclusive, bool blacklist_locker, uint32_t blacklist_expire_seconds, bool force_break_lock, Context *on_finish) : m_ioctx(ioctx), m_cct(reinterpret_cast(m_ioctx.cct())), m_work_queue(work_queue), m_oid(oid), m_locker(locker), - m_blacklist_locker(blacklist_locker), + m_exclusive(exclusive), m_blacklist_locker(blacklist_locker), m_blacklist_expire_seconds(blacklist_expire_seconds), m_force_break_lock(force_break_lock), m_on_finish(on_finish) { } @@ -112,6 +113,43 @@ void BreakRequest::handle_get_watchers(int r) { return; } + send_get_locker(); +} + +template +void BreakRequest::send_get_locker() { + ldout(m_cct, 10) << dendl; + + using klass = BreakRequest; + Context *ctx = create_context_callback( + this); + auto req = GetLockerRequest::create(m_ioctx, m_oid, m_exclusive, + &m_refreshed_locker, ctx); + req->send(); +} + +template +void BreakRequest::handle_get_locker(int r) { + ldout(m_cct, 10) << "r=" << r << dendl; + + if (r == -ENOENT) { + ldout(m_cct, 5) << "no lock owner" << dendl; + finish(0); + return; + } else if (r < 0 && r != -EBUSY) { + lderr(m_cct) << "failed to retrieve lockers: " << cpp_strerror(r) << dendl; + finish(r); + return; + } else if (r < 0) { + m_refreshed_locker = {}; + } + + if (m_refreshed_locker != m_locker || m_refreshed_locker == Locker{}) { + ldout(m_cct, 5) << "no longer lock owner" << dendl; + finish(-EAGAIN); + return; + } + send_blacklist(); } diff --git a/ceph/src/librbd/managed_lock/BreakRequest.h b/ceph/src/librbd/managed_lock/BreakRequest.h index 045f629de..6f4f4acab 100644 --- a/ceph/src/librbd/managed_lock/BreakRequest.h +++ b/ceph/src/librbd/managed_lock/BreakRequest.h @@ -30,12 +30,12 @@ class BreakRequest { public: static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue, const std::string& oid, const Locker &locker, - bool blacklist_locker, + bool exclusive, bool blacklist_locker, uint32_t blacklist_expire_seconds, bool force_break_lock, Context *on_finish) { - return new BreakRequest(ioctx, work_queue, oid, locker, blacklist_locker, - blacklist_expire_seconds, force_break_lock, - on_finish); + return new BreakRequest(ioctx, work_queue, oid, locker, exclusive, + blacklist_locker, blacklist_expire_seconds, + force_break_lock, on_finish); } void send(); @@ -50,6 +50,9 @@ private: * GET_WATCHERS * | * v + * GET_LOCKER + * | + * v * BLACKLIST (skip if disabled) * | * v @@ -66,6 +69,7 @@ private: ContextWQ *m_work_queue; std::string m_oid; Locker m_locker; + bool m_exclusive; bool m_blacklist_locker; uint32_t m_blacklist_expire_seconds; bool m_force_break_lock; @@ -76,14 +80,20 @@ private: std::list m_watchers; int m_watchers_ret_val; + Locker m_refreshed_locker; + BreakRequest(librados::IoCtx& ioctx, ContextWQ *work_queue, const std::string& oid, const Locker &locker, - bool blacklist_locker, uint32_t blacklist_expire_seconds, - bool force_break_lock, Context *on_finish); + bool exclusive, bool blacklist_locker, + uint32_t blacklist_expire_seconds, bool force_break_lock, + Context *on_finish); void send_get_watchers(); void handle_get_watchers(int r); + void send_get_locker(); + void handle_get_locker(int r); + void send_blacklist(); void handle_blacklist(int r); diff --git a/ceph/src/librbd/object_map/Request.cc b/ceph/src/librbd/object_map/Request.cc index e54aed0b2..82aaa7d19 100644 --- a/ceph/src/librbd/object_map/Request.cc +++ b/ceph/src/librbd/object_map/Request.cc @@ -48,7 +48,9 @@ bool Request::should_complete(int r) { } bool Request::invalidate() { - if (m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID)) { + bool flags_set; + int r = m_image_ctx.test_flags(RBD_FLAG_OBJECT_MAP_INVALID, &flags_set); + if (r == 0 && flags_set) { return true; } diff --git a/ceph/src/librbd/object_map/UpdateRequest.cc b/ceph/src/librbd/object_map/UpdateRequest.cc index e88085add..8c0ec69de 100644 --- a/ceph/src/librbd/object_map/UpdateRequest.cc +++ b/ceph/src/librbd/object_map/UpdateRequest.cc @@ -42,7 +42,10 @@ void UpdateRequest::send() { m_new_state, m_current_state); librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); + std::vector snaps; + int r = m_image_ctx.md_ctx.aio_operate( + oid, rados_completion, &op, 0, snaps, + (m_trace.valid() ? m_trace.get_info() : nullptr)); assert(r == 0); rados_completion->release(); } diff --git a/ceph/src/librbd/object_map/UpdateRequest.h b/ceph/src/librbd/object_map/UpdateRequest.h index 0bb9cd756..175160752 100644 --- a/ceph/src/librbd/object_map/UpdateRequest.h +++ b/ceph/src/librbd/object_map/UpdateRequest.h @@ -7,6 +7,8 @@ #include "include/int_types.h" #include "librbd/object_map/Request.h" #include "common/bit_vector.hpp" +#include "common/zipkin_trace.h" +#include "librbd/Utils.h" #include class Context; @@ -25,21 +27,27 @@ public: uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, + const ZTracer::Trace &parent_trace, Context *on_finish) { return new UpdateRequest(image_ctx, object_map, snap_id, start_object_no, end_object_no, new_state, current_state, - on_finish); + parent_trace, on_finish); } UpdateRequest(ImageCtx &image_ctx, ceph::BitVector<2> *object_map, uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, - Context *on_finish) + const ZTracer::Trace &parent_trace, Context *on_finish) : Request(image_ctx, snap_id, on_finish), m_object_map(*object_map), m_start_object_no(start_object_no), m_end_object_no(end_object_no), - m_new_state(new_state), m_current_state(current_state) + m_new_state(new_state), m_current_state(current_state), + m_trace(util::create_trace(image_ctx, "update object map", parent_trace)) { + m_trace.event("start"); + } + virtual ~UpdateRequest() { + m_trace.event("finish"); } void send() override; @@ -53,6 +61,7 @@ private: uint64_t m_end_object_no; uint8_t m_new_state; boost::optional m_current_state; + ZTracer::Trace m_trace; }; } // namespace object_map diff --git a/ceph/src/librbd/operation/FlattenRequest.cc b/ceph/src/librbd/operation/FlattenRequest.cc index 2cfa1ad1c..e01dc2bc6 100644 --- a/ceph/src/librbd/operation/FlattenRequest.cc +++ b/ceph/src/librbd/operation/FlattenRequest.cc @@ -42,7 +42,7 @@ public: bufferlist bl; string oid = image_ctx.get_object_name(m_object_no); auto req = new io::ObjectWriteRequest(&image_ctx, oid, m_object_no, 0, - bl, m_snapc, this, 0); + bl, m_snapc, 0, {}, this); if (!req->has_parent()) { // stop early if the parent went away - it just means // another flatten finished first or the image was resized diff --git a/ceph/src/librbd/operation/TrimRequest.cc b/ceph/src/librbd/operation/TrimRequest.cc index 5c59e3c16..46ec967b5 100644 --- a/ceph/src/librbd/operation/TrimRequest.cc +++ b/ceph/src/librbd/operation/TrimRequest.cc @@ -46,7 +46,7 @@ public: ldout(image_ctx.cct, 10) << "removing (with copyup) " << oid << dendl; auto req = new io::ObjectTrimRequest(&image_ctx, oid, m_object_no, - m_snapc, this, false); + m_snapc, false, this); req->send(); return 0; } @@ -277,7 +277,7 @@ void TrimRequest::send_pre_copyup() { RWLock::WLocker object_map_locker(image_ctx.object_map_lock); if (image_ctx.object_map->template aio_update >( CEPH_NOSNAP, m_copyup_start, m_copyup_end, OBJECT_PENDING, - OBJECT_EXISTS, this)) { + OBJECT_EXISTS, {}, this)) { return; } } @@ -309,7 +309,7 @@ void TrimRequest::send_pre_remove() { RWLock::WLocker object_map_locker(image_ctx.object_map_lock); if (image_ctx.object_map->template aio_update >( CEPH_NOSNAP, m_delete_start, m_num_objects, OBJECT_PENDING, - OBJECT_EXISTS, this)) { + OBJECT_EXISTS, {}, this)) { return; } } @@ -337,7 +337,7 @@ void TrimRequest::send_post_copyup() { RWLock::WLocker object_map_locker(image_ctx.object_map_lock); if (image_ctx.object_map->template aio_update >( CEPH_NOSNAP, m_copyup_start, m_copyup_end, OBJECT_NONEXISTENT, - OBJECT_PENDING, this)) { + OBJECT_PENDING, {}, this)) { return; } } @@ -365,7 +365,7 @@ void TrimRequest::send_post_remove() { RWLock::WLocker object_map_locker(image_ctx.object_map_lock); if (image_ctx.object_map->template aio_update >( CEPH_NOSNAP, m_delete_start, m_num_objects, OBJECT_NONEXISTENT, - OBJECT_PENDING, this)) { + OBJECT_PENDING, {}, this)) { return; } } @@ -416,10 +416,10 @@ void TrimRequest::send_clean_boundary() { io::ObjectRequest<> *req; if (p->offset == 0) { req = new io::ObjectTrimRequest(&image_ctx, p->oid.name, p->objectno, - snapc, req_comp, true); + snapc, true, req_comp); } else { req = new io::ObjectTruncateRequest(&image_ctx, p->oid.name, p->objectno, - p->offset, snapc, req_comp); + p->offset, snapc, {}, req_comp); } req->send(); } diff --git a/ceph/src/mds/CDentry.cc b/ceph/src/mds/CDentry.cc index 7eeba7e75..44dc6d52a 100644 --- a/ceph/src/mds/CDentry.cc +++ b/ceph/src/mds/CDentry.cc @@ -88,7 +88,9 @@ ostream& operator<<(ostream& out, const CDentry& dn) out << " inode=" << dn.get_linkage()->get_inode(); - if (dn.is_new()) out << " state=new"; + out << " state=" << dn.get_state(); + if (dn.is_new()) out << "|new"; + if (dn.state_test(CDentry::STATE_BOTTOMLRU)) out << "|bottomlru"; if (dn.get_num_ref()) { out << " |"; diff --git a/ceph/src/mds/CDentry.h b/ceph/src/mds/CDentry.h index 175ce4fc1..01e3d3c49 100644 --- a/ceph/src/mds/CDentry.h +++ b/ceph/src/mds/CDentry.h @@ -86,8 +86,10 @@ public: static const int STATE_BADREMOTEINO = (1<<3); static const int STATE_EVALUATINGSTRAY = (1<<4); static const int STATE_PURGINGPINNED = (1<<5); + static const int STATE_BOTTOMLRU = (1<<6); // stray dentry needs notification of releasing reference static const int STATE_STRAY = STATE_NOTIFYREF; + static const int MASK_STATE_IMPORT_KEPT = STATE_BOTTOMLRU; // -- pins -- static const int PIN_INODEPIN = 1; // linked inode is pinned @@ -289,7 +291,7 @@ public: ::decode(replica_map, blp); // twiddle - state = 0; + state &= MASK_STATE_IMPORT_KEPT; state_set(CDentry::STATE_AUTH); if (nstate & STATE_DIRTY) _mark_dirty(ls); diff --git a/ceph/src/mds/CDir.cc b/ceph/src/mds/CDir.cc index 03ba64463..6561d2fb2 100644 --- a/ceph/src/mds/CDir.cc +++ b/ceph/src/mds/CDir.cc @@ -328,7 +328,9 @@ CDentry* CDir::add_null_dentry(const string& dname, CDentry* dn = new CDentry(dname, inode->hash_dentry_name(dname), first, last); if (is_auth()) dn->state_set(CDentry::STATE_AUTH); - cache->lru.lru_insert_mid(dn); + + cache->bottom_lru.lru_insert_mid(dn); + dn->state_set(CDentry::STATE_BOTTOMLRU); dn->dir = this; dn->version = get_projected_version(); @@ -369,7 +371,12 @@ CDentry* CDir::add_primary_dentry(const string& dname, CInode *in, CDentry* dn = new CDentry(dname, inode->hash_dentry_name(dname), first, last); if (is_auth()) dn->state_set(CDentry::STATE_AUTH); - cache->lru.lru_insert_mid(dn); + if (is_auth() || !inode->is_stray()) { + cache->lru.lru_insert_mid(dn); + } else { + cache->bottom_lru.lru_insert_mid(dn); + dn->state_set(CDentry::STATE_BOTTOMLRU); + } dn->dir = this; dn->version = get_projected_version(); @@ -482,7 +489,10 @@ void CDir::remove_dentry(CDentry *dn) if (dn->is_dirty()) dn->mark_clean(); - cache->lru.lru_remove(dn); + if (dn->state_test(CDentry::STATE_BOTTOMLRU)) + cache->bottom_lru.lru_remove(dn); + else + cache->lru.lru_remove(dn); delete dn; // unpin? @@ -503,6 +513,12 @@ void CDir::link_remote_inode(CDentry *dn, inodeno_t ino, unsigned char d_type) dn->get_linkage()->set_remote(ino, d_type); + if (dn->state_test(CDentry::STATE_BOTTOMLRU)) { + cache->bottom_lru.lru_remove(dn); + cache->lru.lru_insert_mid(dn); + dn->state_clear(CDentry::STATE_BOTTOMLRU); + } + if (dn->last == CEPH_NOSNAP) { num_head_items++; num_head_null--; @@ -522,6 +538,13 @@ void CDir::link_primary_inode(CDentry *dn, CInode *in) in->set_primary_parent(dn); link_inode_work(dn, in); + + if (dn->state_test(CDentry::STATE_BOTTOMLRU) && + (is_auth() || !inode->is_stray())) { + cache->bottom_lru.lru_remove(dn); + cache->lru.lru_insert_mid(dn); + dn->state_clear(CDentry::STATE_BOTTOMLRU); + } if (dn->last == CEPH_NOSNAP) { num_head_items++; @@ -557,7 +580,7 @@ void CDir::link_inode_work( CDentry *dn, CInode *in) in->move_to_realm(inode->find_snaprealm()); } -void CDir::unlink_inode(CDentry *dn) +void CDir::unlink_inode(CDentry *dn, bool adjust_lru) { if (dn->get_linkage()->is_primary()) { dout(12) << "unlink_inode " << *dn << " " << *dn->get_linkage()->get_inode() << dendl; @@ -567,6 +590,12 @@ void CDir::unlink_inode(CDentry *dn) unlink_inode_work(dn); + if (adjust_lru && !dn->state_test(CDentry::STATE_BOTTOMLRU)) { + cache->lru.lru_remove(dn); + cache->bottom_lru.lru_insert_mid(dn); + dn->state_set(CDentry::STATE_BOTTOMLRU); + } + if (dn->last == CEPH_NOSNAP) { num_head_items--; num_head_null++; @@ -683,7 +712,7 @@ void CDir::remove_null_dentries() { void CDir::try_remove_dentries_for_stray() { dout(10) << __func__ << dendl; - assert(inode->inode.nlink == 0); + assert(get_parent_dir()->inode->is_stray()); // clear dirty only when the directory was not snapshotted bool clear_dirty = !inode->snaprealm; @@ -726,15 +755,6 @@ void CDir::try_remove_dentries_for_stray() mark_clean(); } -void CDir::touch_dentries_bottom() { - dout(12) << "touch_dentries_bottom " << *this << dendl; - - for (CDir::map_t::iterator p = items.begin(); - p != items.end(); - ++p) - inode->mdcache->touch_dentry_bottom(p->second); -} - bool CDir::try_trim_snap_dentry(CDentry *dn, const set& snaps) { assert(dn->last != CEPH_NOSNAP); @@ -849,12 +869,19 @@ void CDir::steal_dentry(CDentry *dn) dn->dir = this; } -void CDir::prepare_old_fragment(bool replay) +void CDir::prepare_old_fragment(map >& dentry_waiters, bool replay) { // auth_pin old fragment for duration so that any auth_pinning // during the dentry migration doesn't trigger side effects if (!replay && is_auth()) auth_pin(this); + + if (!waiting_on_dentry.empty()) { + for (auto p = waiting_on_dentry.begin(); p != waiting_on_dentry.end(); ++p) + dentry_waiters[p->first].swap(p->second); + waiting_on_dentry.clear(); + put(PIN_DNWAITER); + } } void CDir::prepare_new_fragment(bool replay) @@ -863,6 +890,7 @@ void CDir::prepare_new_fragment(bool replay) _freeze_dir(); mark_complete(); } + inode->add_dirfrag(this); } void CDir::finish_old_fragment(list& waiters, bool replay) @@ -940,7 +968,8 @@ void CDir::split(int bits, list& subs, list& wai fragstatdiff.add_delta(fnode.accounted_fragstat, fnode.fragstat); dout(10) << " rstatdiff " << rstatdiff << " fragstatdiff " << fragstatdiff << dendl; - prepare_old_fragment(replay); + map > dentry_waiters; + prepare_old_fragment(dentry_waiters, replay); // create subfrag dirs int n = 0; @@ -966,7 +995,6 @@ void CDir::split(int bits, list& subs, list& wai dout(10) << " subfrag " << *p << " " << *f << dendl; subfrags[n++] = f; subs.push_back(f); - inode->add_dirfrag(f); f->set_dir_auth(get_dir_auth()); f->prepare_new_fragment(replay); @@ -984,6 +1012,16 @@ void CDir::split(int bits, list& subs, list& wai f->steal_dentry(dn); } + for (auto& p : dentry_waiters) { + frag_t subfrag = inode->pick_dirfrag(p.first.name); + int n = (subfrag.value() & (subfrag.mask() ^ frag.mask())) >> subfrag.mask_shift(); + CDir *f = subfrags[n]; + + if (f->waiting_on_dentry.empty()) + f->get(PIN_DNWAITER); + f->waiting_on_dentry[p.first].swap(p.second); + } + // FIXME: handle dirty old rstat // fix up new frag fragstats @@ -1028,6 +1066,8 @@ void CDir::merge(list& subs, list& waiters, bool version_t rstat_version = inode->get_projected_inode()->rstat.version; version_t dirstat_version = inode->get_projected_inode()->dirstat.version; + map > dentry_waiters; + for (auto dir : subs) { dout(10) << " subfrag " << dir->get_frag() << " " << *dir << dendl; assert(!dir->is_auth() || dir->is_complete() || replay); @@ -1038,7 +1078,7 @@ void CDir::merge(list& subs, list& waiters, bool fragstatdiff.add_delta(dir->fnode.accounted_fragstat, dir->fnode.fragstat, &touched_mtime, &touched_chattr); - dir->prepare_old_fragment(replay); + dir->prepare_old_fragment(dentry_waiters, replay); // steal dentries while (!dir->items.empty()) @@ -1059,12 +1099,18 @@ void CDir::merge(list& subs, list& waiters, bool // merge state state_set(dir->get_state() & MASK_STATE_FRAGMENT_KEPT); - dir_auth = dir->dir_auth; dir->finish_old_fragment(waiters, replay); inode->close_dirfrag(dir->get_frag()); } + if (!dentry_waiters.empty()) { + get(PIN_DNWAITER); + for (auto& p : dentry_waiters) { + waiting_on_dentry[p.first].swap(p.second); + } + } + if (is_auth() && !replay) mark_complete(); @@ -1425,9 +1471,11 @@ void CDir::fetch(MDSInternalContextBase *c, const string& want_dn, bool ignore_a } // unlinked directory inode shouldn't have any entry - if (inode->inode.nlink == 0 && !inode->snaprealm) { + if (!inode->is_base() && get_parent_dir()->inode->is_stray() && + !inode->snaprealm) { dout(7) << "fetch dirfrag for unlinked directory, mark complete" << dendl; if (get_version() == 0) { + assert(inode->is_auth()); set_version(1); if (state_test(STATE_REJOINUNDEF)) { @@ -2003,14 +2051,6 @@ void CDir::commit(version_t want, MDSInternalContextBase *c, bool ignore_authpin assert(is_auth()); assert(ignore_authpinnability || can_auth_pin()); - if (inode->inode.nlink == 0 && !inode->snaprealm) { - dout(7) << "commit dirfrag for unlinked directory, mark clean" << dendl; - try_remove_dentries_for_stray(); - if (c) - cache->mds->queue_waiter(c); - return; - } - // note: queue up a noop if necessary, so that we always // get an auth_pin. if (!c) @@ -2268,9 +2308,10 @@ void CDir::_committed(int r, version_t v) if (r < 0) { // the directory could be partly purged during MDS failover if (r == -ENOENT && committed_version == 0 && - inode->inode.nlink == 0 && inode->snaprealm) { - inode->state_set(CInode::STATE_MISSINGOBJS); + !inode->is_base() && get_parent_dir()->inode->is_stray()) { r = 0; + if (inode->snaprealm) + inode->state_set(CInode::STATE_MISSINGOBJS); } if (r < 0) { dout(1) << "commit error " << r << " v " << v << dendl; @@ -2361,7 +2402,8 @@ void CDir::_committed(int r, version_t v) } // try drop dentries in this dirfrag if it's about to be purged - if (inode->inode.nlink == 0 && inode->snaprealm) + if (!inode->is_base() && get_parent_dir()->inode->is_stray() && + inode->snaprealm) cache->maybe_eval_stray(inode, true); // unpin if we kicked the last waiter. diff --git a/ceph/src/mds/CDir.h b/ceph/src/mds/CDir.h index 3a65a82b3..5b0079a74 100644 --- a/ceph/src/mds/CDir.h +++ b/ceph/src/mds/CDir.h @@ -450,7 +450,7 @@ protected: void link_remote_inode( CDentry *dn, inodeno_t ino, unsigned char d_type); void link_remote_inode( CDentry *dn, CInode *in ); void link_primary_inode( CDentry *dn, CInode *in ); - void unlink_inode( CDentry *dn ); + void unlink_inode(CDentry *dn, bool adjust_lru=true); void try_remove_unlinked_dn(CDentry *dn); void add_to_bloom(CDentry *dn); @@ -465,7 +465,6 @@ private: void remove_null_dentries(); void purge_stale_snap_data(const std::set& snaps); public: - void touch_dentries_bottom(); void try_remove_dentries_for_stray(); bool try_trim_snap_dentry(CDentry *dn, const std::set& snaps); @@ -484,7 +483,7 @@ public: private: void prepare_new_fragment(bool replay); - void prepare_old_fragment(bool replay); + void prepare_old_fragment(map >& dentry_waiters, bool replay); void steal_dentry(CDentry *dn); // from another dir. used by merge/split. void finish_old_fragment(list& waiters, bool replay); void init_fragment_pins(); diff --git a/ceph/src/mds/CInode.cc b/ceph/src/mds/CInode.cc index 7af16b564..567668a12 100644 --- a/ceph/src/mds/CInode.cc +++ b/ceph/src/mds/CInode.cc @@ -1809,8 +1809,9 @@ void CInode::decode_lock_state(int type, bufferlist& bl) if (inode.ctime < tm) inode.ctime = tm; ::decode(inode.layout, p); ::decode(inode.quota, p); + mds_rank_t old_pin = inode.export_pin; ::decode(inode.export_pin, p); - maybe_export_pin(); + maybe_export_pin(old_pin != inode.export_pin); } break; @@ -3079,7 +3080,7 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session, unsigned max_bytes, int getattr_caps) { - int client = session->info.inst.name.num(); + client_t client = session->info.inst.name.num(); assert(snapid); assert(session->connection); @@ -4407,70 +4408,43 @@ int64_t CInode::get_backtrace_pool() const } } -class C_CInode_ExportPin : public MDSInternalContext { -public: - explicit C_CInode_ExportPin(CInode *in) : MDSInternalContext(in->mdcache->mds), in(in) { - in->get(MDSCacheObject::PIN_PTRWAITER); - } - ~C_CInode_ExportPin() { - in->put(MDSCacheObject::PIN_PTRWAITER); - } +void CInode::maybe_export_pin(bool update) +{ + if (!g_conf->mds_bal_export_pin) + return; + if (!is_dir() || !is_normal()) + return; - void finish(int r) override { - in->maybe_export_pin(); - } -private: - CInode *in; -}; + mds_rank_t export_pin = get_export_pin(false); + if (export_pin == MDS_RANK_NONE && !update) + return; -void CInode::maybe_export_pin() -{ - if (g_conf->mds_bal_export_pin && is_dir() && is_normal()) { - mds_rank_t pin = get_export_pin(false); - dout(20) << "maybe_export_pin export_pin=" << pin << " on " << *this << dendl; - if (pin == mdcache->mds->get_nodeid()) { - for (auto it = dirfrags.begin(); it != dirfrags.end(); it++) { - CDir *cd = it->second; - dout(20) << "dirfrag: " << *cd << dendl; - if (cd->state_test(CDir::STATE_CREATING)) { - /* inode is not journaled yet */ - cd->add_waiter(CDir::WAIT_CREATED, new C_CInode_ExportPin(this)); - dout(15) << "aux subtree pin of " << *cd << " delayed for finished creation" << dendl; - continue; - } - if (cd->state_test(CDir::STATE_AUXSUBTREE)) continue; - CDir *subtree = mdcache->get_subtree_root(cd); - assert(subtree); - if (subtree->is_ambiguous_auth()) { - subtree->add_waiter(MDSCacheObject::WAIT_SINGLEAUTH, new C_CInode_ExportPin(this)); - dout(15) << "aux subtree pin of " << *cd << " delayed for single auth on subtree " << *subtree << dendl; - } else if (subtree->is_auth()) { - assert(cd->is_auth()); - if (subtree->is_frozen() || subtree->is_freezing()) { - subtree->add_waiter(MDSCacheObject::WAIT_UNFREEZE, new C_CInode_ExportPin(this)); - dout(15) << "aux subtree pin of " << *cd << " delayed for unfreeze on subtree " << *subtree << dendl; - } else { - cd->state_set(CDir::STATE_AUXSUBTREE); - mdcache->adjust_subtree_auth(cd, mdcache->mds->get_nodeid()); - dout(15) << "aux subtree pinned " << *cd << dendl; - } - } else { - assert(!cd->is_auth()); - dout(15) << "not setting aux subtree pin for " << *cd << " because not auth" << dendl; - } - } - } else if (pin != MDS_RANK_NONE) { - for (auto it = dirfrags.begin(); it != dirfrags.end(); it++) { - CDir *cd = it->second; - if (cd->is_auth() && cd->state_test(CDir::STATE_AUXSUBTREE)) { - assert(!(cd->is_frozen() || cd->is_freezing())); - assert(!cd->state_test(CDir::STATE_EXPORTBOUND)); - cd->state_clear(CDir::STATE_AUXSUBTREE); /* merge will happen eventually */ - dout(15) << "cleared aux subtree pin " << *cd << dendl; - } + if (state_test(CInode::STATE_QUEUEDEXPORTPIN)) + return; + + bool queue = false; + for (auto p = dirfrags.begin(); p != dirfrags.end(); p++) { + CDir *dir = p->second; + if (!dir->is_auth()) + continue; + if (export_pin != MDS_RANK_NONE) { + if (dir->is_subtree_root()) { + // set auxsubtree bit or export it + if (!dir->state_test(CDir::STATE_AUXSUBTREE) || + export_pin != dir->get_dir_auth().first) + queue = true; + } else { + // create aux subtree or export it + queue = true; } - dout(20) << "adding to export_pin_queue " << *this << dendl; + } else { + // clear aux subtrees ? + queue = dir->state_test(CDir::STATE_AUXSUBTREE); + } + if (queue) { + state_set(CInode::STATE_QUEUEDEXPORTPIN); mdcache->export_pin_queue.insert(this); + break; } } } @@ -4480,7 +4454,7 @@ void CInode::set_export_pin(mds_rank_t rank) assert(is_dir()); assert(is_projected()); get_projected_inode()->export_pin = rank; - maybe_export_pin(); + maybe_export_pin(true); } mds_rank_t CInode::get_export_pin(bool inherit) const diff --git a/ceph/src/mds/CInode.h b/ceph/src/mds/CInode.h index eae86ef4c..030c86e62 100644 --- a/ceph/src/mds/CInode.h +++ b/ceph/src/mds/CInode.h @@ -200,6 +200,7 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter - $) + $) target_link_libraries(mds ${ALLOC_LIBS} osdc liblua) diff --git a/ceph/src/mds/FSMap.cc b/ceph/src/mds/FSMap.cc index 35c8093a3..eb08d02b7 100644 --- a/ceph/src/mds/FSMap.cc +++ b/ceph/src/mds/FSMap.cc @@ -124,16 +124,15 @@ void FSMap::print_summary(Formatter *f, ostream *out) const f->dump_unsigned("max", fs->mds_map.max_mds); } } else { - *out << "e" << get_epoch() << ":"; if (filesystems.size() == 1) { auto fs = filesystems.begin()->second; - *out << " " << fs->mds_map.up.size() << "/" << fs->mds_map.in.size() << "/" + *out << fs->mds_map.up.size() << "/" << fs->mds_map.in.size() << "/" << fs->mds_map.max_mds << " up"; } else { for (auto i : filesystems) { auto fs = i.second; - *out << " " << fs->mds_map.fs_name << "-" << fs->mds_map.up.size() << "/" - << fs->mds_map.in.size() << "/" << fs->mds_map.max_mds << " up"; + *out << fs->mds_map.fs_name << "-" << fs->mds_map.up.size() << "/" + << fs->mds_map.in.size() << "/" << fs->mds_map.max_mds << " up "; } } } @@ -237,7 +236,7 @@ void FSMap::create_filesystem(const std::string &name, auto fs = std::make_shared(); fs->mds_map.fs_name = name; fs->mds_map.max_mds = 1; - fs->mds_map.data_pools.insert(data_pool); + fs->mds_map.data_pools.push_back(data_pool); fs->mds_map.metadata_pool = metadata_pool; fs->mds_map.cas_pool = -1; fs->mds_map.max_file_size = g_conf->mds_max_file_size; @@ -408,7 +407,7 @@ void FSMap::decode(bufferlist::iterator& p) while (n--) { __u32 m; ::decode(m, p); - legacy_mds_map.data_pools.insert(m); + legacy_mds_map.data_pools.push_back(m); } __s32 s; ::decode(s, p); @@ -669,8 +668,8 @@ mds_gid_t FSMap::find_standby_for(mds_role_t role, const std::string& name) cons return result; } -mds_gid_t FSMap::find_unused(fs_cluster_id_t fscid, - bool force_standby_active) const { +mds_gid_t FSMap::find_unused_for(mds_role_t role, + bool force_standby_active) const { for (const auto &i : standby_daemons) { const auto &gid = i.first; const auto &info = i.second; @@ -680,7 +679,10 @@ mds_gid_t FSMap::find_unused(fs_cluster_id_t fscid, continue; if (info.standby_for_fscid != FS_CLUSTER_ID_NONE && - info.standby_for_fscid != fscid) + info.standby_for_fscid != role.fscid) + continue; + if (info.standby_for_rank != MDS_RANK_NONE && + info.standby_for_rank != role.rank) continue; // To be considered 'unused' a daemon must either not @@ -699,7 +701,7 @@ mds_gid_t FSMap::find_replacement_for(mds_role_t role, const std::string& name, if (standby) return standby; else - return find_unused(role.fscid, force_standby_active); + return find_unused_for(role, force_standby_active); } void FSMap::sanity() const diff --git a/ceph/src/mds/FSMap.h b/ceph/src/mds/FSMap.h index 881281edc..3d389c488 100644 --- a/ceph/src/mds/FSMap.h +++ b/ceph/src/mds/FSMap.h @@ -468,7 +468,7 @@ public: mds_gid_t find_standby_for(mds_role_t mds, const std::string& name) const; - mds_gid_t find_unused(fs_cluster_id_t fscid, bool force_standby_active) const; + mds_gid_t find_unused_for(mds_role_t mds, bool force_standby_active) const; mds_gid_t find_replacement_for(mds_role_t mds, const std::string& name, bool force_standby_active) const; diff --git a/ceph/src/mds/Locker.cc b/ceph/src/mds/Locker.cc index 18125e3ef..6cb9a7351 100644 --- a/ceph/src/mds/Locker.cc +++ b/ceph/src/mds/Locker.cc @@ -1853,7 +1853,7 @@ Capability* Locker::issue_new_caps(CInode *in, // my needs assert(session->info.inst.name.is_client()); - int my_client = session->info.inst.name.num(); + client_t my_client = session->info.inst.name.num(); int my_want = ceph_caps_for_mode(mode); // register a capability @@ -2231,6 +2231,16 @@ public: } }; +uint64_t Locker::calc_new_max_size(inode_t *pi, uint64_t size) +{ + uint64_t new_max = (size + 1) << 1; + uint64_t max_inc = g_conf->mds_client_writeable_range_max_inc_objs; + if (max_inc > 0) { + max_inc *= pi->get_layout_size_increment(); + new_max = MIN(new_max, size + max_inc); + } + return ROUND_UP_TO(new_max, pi->get_layout_size_increment()); +} void Locker::calc_new_client_ranges(CInode *in, uint64_t size, map *new_ranges, @@ -2239,7 +2249,7 @@ void Locker::calc_new_client_ranges(CInode *in, uint64_t size, inode_t *latest = in->get_projected_inode(); uint64_t ms; if(latest->has_layout()) { - ms = ROUND_UP_TO((size+1)<<1, latest->get_layout_size_increment()); + ms = calc_new_max_size(latest, size); } else { // Layout-less directories like ~mds0/, have zero size ms = 0; @@ -2260,6 +2270,7 @@ void Locker::calc_new_client_ranges(CInode *in, uint64_t size, nr.range.last = MAX(ms, oldr.range.last); nr.follows = oldr.follows; } else { + *max_increased = true; nr.range.last = ms; nr.follows = in->first - 1; } @@ -2977,17 +2988,6 @@ void Locker::kick_cap_releases(MDRequestRef& mdr) } } -static uint64_t calc_bounding(uint64_t t) -{ - t |= t >> 1; - t |= t >> 2; - t |= t >> 4; - t |= t >> 8; - t |= t >> 16; - t |= t >> 32; - return t + 1; -} - /** * m and ack might be NULL, so don't dereference them unless dirty != 0 */ @@ -3204,11 +3204,9 @@ bool Locker::_do_cap_update(CInode *in, Capability *cap, << " > max " << old_max << dendl; change_max = true; forced_change_max = true; - new_max = ROUND_UP_TO((m->get_max_size()+1) << 1, latest->get_layout_size_increment()); + new_max = calc_new_max_size(latest, m->get_max_size()); } else { - new_max = calc_bounding(size * 2); - if (new_max < latest->get_layout_size_increment()) - new_max = latest->get_layout_size_increment(); + new_max = calc_new_max_size(latest, size); if (new_max > old_max) change_max = true; @@ -3853,6 +3851,8 @@ void Locker::handle_simple_lock(SimpleLock *lock, MLock *m) if (lock->is_leased()) revoke_client_leases(lock); eval_gather(lock, true); + if (lock->is_unstable_and_locked()) + mds->mdlog->flush(); break; @@ -5089,6 +5089,8 @@ void Locker::handle_file_lock(ScatterLock *lock, MLock *m) if (lock->get_state() == LOCK_MIX) { lock->set_state(LOCK_MIX_SYNC); eval_gather(lock, true); + if (lock->is_unstable_and_locked()) + mds->mdlog->flush(); break; } @@ -5114,6 +5116,9 @@ void Locker::handle_file_lock(ScatterLock *lock, MLock *m) } eval_gather(lock, true); + if (lock->is_unstable_and_locked()) + mds->mdlog->flush(); + break; case LOCK_AC_LOCKFLUSHED: @@ -5133,6 +5138,8 @@ void Locker::handle_file_lock(ScatterLock *lock, MLock *m) // MIXED lock->set_state(LOCK_SYNC_MIX); eval_gather(lock, true); + if (lock->is_unstable_and_locked()) + mds->mdlog->flush(); break; } diff --git a/ceph/src/mds/Locker.h b/ceph/src/mds/Locker.h index eb3d45ce5..32b7d6301 100644 --- a/ceph/src/mds/Locker.h +++ b/ceph/src/mds/Locker.h @@ -250,6 +250,8 @@ protected: void file_update_finish(CInode *in, MutationRef& mut, bool share_max, bool issue_client_cap, client_t client, MClientCaps *ack); +private: + uint64_t calc_new_max_size(inode_t *pi, uint64_t size); public: void calc_new_client_ranges(CInode *in, uint64_t size, map* new_ranges, diff --git a/ceph/src/mds/MDBalancer.cc b/ceph/src/mds/MDBalancer.cc index 192dc9d02..26f14e519 100644 --- a/ceph/src/mds/MDBalancer.cc +++ b/ceph/src/mds/MDBalancer.cc @@ -83,31 +83,53 @@ void MDBalancer::handle_export_pins(void) auto it = q.begin(); dout(20) << "export_pin_queue size=" << q.size() << dendl; while (it != q.end()) { - auto current = it++; - CInode *in = *current; + auto cur = it++; + CInode *in = *cur; assert(in->is_dir()); - mds_rank_t export_pin = in->get_export_pin(); - if (!in->is_exportable(export_pin)) { - dout(10) << "can no longer export " << *in << " because export pins have since changed" << dendl; - q.erase(current); - continue; - } - dout(10) << "exporting dirfrags of " << *in << " to " << export_pin << dendl; - bool has_auth = false; - list ls; - in->dirfragtree.get_leaves(ls); - for (const auto &fg : ls) { - CDir *cd = in->get_dirfrag(fg); - if (cd && cd->is_auth()) { - /* N.B. when we are no longer auth after exporting, this function will remove the inode from the queue */ - mds->mdcache->migrator->export_dir(cd, export_pin); - has_auth = true; + mds_rank_t export_pin = in->get_export_pin(false); + + bool remove = true; + list dfls; + in->get_dirfrags(dfls); + for (auto dir : dfls) { + if (!dir->is_auth()) + continue; + + if (export_pin == MDS_RANK_NONE) { + if (dir->state_test(CDir::STATE_AUXSUBTREE)) { + if (dir->is_frozen() || dir->is_freezing()) { + // try again later + remove = false; + continue; + } + dout(10) << " clear auxsubtree on " << *dir << dendl; + dir->state_clear(CDir::STATE_AUXSUBTREE); + mds->mdcache->try_subtree_merge(dir); + } + } else if (export_pin == mds->get_nodeid()) { + if (dir->state_test(CDir::STATE_CREATING) || + dir->is_frozen() || dir->is_freezing()) { + // try again later + remove = false; + continue; + } + if (!dir->is_subtree_root()) { + dir->state_set(CDir::STATE_AUXSUBTREE); + mds->mdcache->adjust_subtree_auth(dir, mds->get_nodeid()); + dout(10) << " create aux subtree on " << *dir << dendl; + } else if (!dir->state_test(CDir::STATE_AUXSUBTREE)) { + dout(10) << " set auxsubtree bit on " << *dir << dendl; + dir->state_set(CDir::STATE_AUXSUBTREE); + } + } else { + mds->mdcache->migrator->export_dir(dir, export_pin); + remove = false; } } - if (!has_auth) { - dout(10) << "can no longer export " << *in << " because I am not auth for any dirfrags" << dendl; - q.erase(current); - continue; + + if (remove) { + in->state_clear(CInode::STATE_QUEUEDEXPORTPIN); + q.erase(cur); } } @@ -374,7 +396,7 @@ void MDBalancer::handle_heartbeat(MHeartbeat *m) /* avoid spamming ceph -w if user does not turn mantle on */ if (mds->mdsmap->get_balancer() != "") { int r = mantle_prep_rebalance(); - if (!r) return; + if (!r) goto out; mds->clog->warn() << "using old balancer; mantle failed for " << "balancer=" << mds->mdsmap->get_balancer() << " : " << cpp_strerror(r); @@ -711,15 +733,6 @@ void MDBalancer::prep_rebalance(int beat) try_rebalance(state); } -void MDBalancer::hit_targets(const balance_state_t& state) -{ - utime_t now = ceph_clock_now(); - for (auto &it : state.targets) { - mds_rank_t target = it.first; - mds->hit_export_target(now, target, g_conf->mds_bal_target_decay); - } -} - int MDBalancer::mantle_prep_rebalance() { balance_state_t state; @@ -775,9 +788,6 @@ int MDBalancer::mantle_prep_rebalance() void MDBalancer::try_rebalance(balance_state_t& state) { - if (!check_targets(state)) - return; - if (g_conf->mds_thrash_exports) { dout(5) << "mds_thrash is on; not performing standard rebalance operation!" << dendl; @@ -928,18 +938,6 @@ void MDBalancer::try_rebalance(balance_state_t& state) mds->mdcache->show_subtrees(); } - -/* Check that all targets are in the MDSMap export_targets for my rank. */ -bool MDBalancer::check_targets(const balance_state_t& state) -{ - for (const auto &it : state.targets) { - if (!mds->is_export_target(it.first)) { - return false; - } - } - return true; -} - void MDBalancer::find_exports(CDir *dir, double amount, list& exports, diff --git a/ceph/src/mds/MDBalancer.h b/ceph/src/mds/MDBalancer.h index cbfc1c479..1f8d0dd1e 100644 --- a/ceph/src/mds/MDBalancer.h +++ b/ceph/src/mds/MDBalancer.h @@ -89,8 +89,6 @@ private: void export_empties(); int localize_balancer(); - bool check_targets(const balance_state_t& state); - void hit_targets(const balance_state_t& state); void send_heartbeat(); void handle_heartbeat(MHeartbeat *m); void find_exports(CDir *dir, diff --git a/ceph/src/mds/MDCache.cc b/ceph/src/mds/MDCache.cc index 8f0ca76ac..6c9f47a72 100644 --- a/ceph/src/mds/MDCache.cc +++ b/ceph/src/mds/MDCache.cc @@ -205,6 +205,9 @@ MDCache::MDCache(MDSRank *m, PurgeQueue &purge_queue_) : lru.lru_set_max(g_conf->mds_cache_size); lru.lru_set_midpoint(g_conf->mds_cache_mid); + bottom_lru.lru_set_max(0); + bottom_lru.lru_set_midpoint(0); + decayrate.set_halflife(g_conf->mds_decay_halflife); did_shutdown_log_cap = false; @@ -295,7 +298,8 @@ void MDCache::remove_inode(CInode *o) o->item_open_file.remove_myself(); - export_pin_queue.erase(o); + if (o->state_test(CInode::STATE_QUEUEDEXPORTPIN)) + export_pin_queue.erase(o); // remove from inode map inode_map.erase(o->vino()); @@ -2875,6 +2879,7 @@ void MDCache::handle_mds_failure(mds_rank_t who) rejoin_gather.insert(who); rejoin_sent.erase(who); // i need to send another + rejoin_ack_sent.erase(who); // i need to send another rejoin_ack_gather.erase(who); // i'll need/get another. dout(10) << " resolve_gather " << resolve_gather << dendl; @@ -2934,6 +2939,13 @@ void MDCache::handle_mds_failure(mds_rank_t who) dout(10) << " slave request " << *mdr << " uncommitted, will resolve shortly" << dendl; add_ambiguous_slave_update(p->first, mdr->slave_to_mds); } + } else if (mdr->slave_request) { + MMDSSlaveRequest *slave_req = mdr->slave_request; + // FIXME: Slave rename request can arrive after we notice mds failure. + // This can cause mds to crash (does not affect integrity of FS). + if (slave_req->get_op() == MMDSSlaveRequest::OP_RENAMEPREP && + slave_req->srcdn_auth == who) + slave_req->mark_interrupted(); } // failed node is slave? @@ -3656,7 +3668,7 @@ void MDCache::remove_inode_recursive(CInode *in) CDentry::linkage_t *dnl = dn->get_linkage(); if (dnl->is_primary()) { CInode *tin = dnl->get_inode(); - subdir->unlink_inode(dn); + subdir->unlink_inode(dn, false); remove_inode_recursive(tin); } subdir->remove_dentry(dn); @@ -5925,11 +5937,16 @@ void MDCache::rejoin_send_acks() rejoin_unlinked_inodes.clear(); // send acks to everyone in the recovery set - map ack; + map acks; for (set::iterator p = recovery_set.begin(); p != recovery_set.end(); - ++p) - ack[*p] = new MMDSCacheRejoin(MMDSCacheRejoin::OP_ACK); + ++p) { + if (rejoin_ack_sent.count(*p)) + continue; + acks[*p] = new MMDSCacheRejoin(MMDSCacheRejoin::OP_ACK); + } + + rejoin_ack_sent = recovery_set; // walk subtrees for (map >::iterator p = subtrees.begin(); @@ -5952,8 +5969,11 @@ void MDCache::rejoin_send_acks() for (compact_map::iterator r = dir->replicas_begin(); r != dir->replicas_end(); ++r) { - ack[r->first]->add_strong_dirfrag(dir->dirfrag(), ++r->second, dir->dir_rep); - ack[r->first]->add_dirfrag_base(dir); + auto it = acks.find(r->first); + if (it == acks.end()) + continue; + it->second->add_strong_dirfrag(dir->dirfrag(), ++r->second, dir->dir_rep); + it->second->add_dirfrag_base(dir); } for (CDir::map_t::iterator q = dir->items.begin(); @@ -5971,7 +5991,10 @@ void MDCache::rejoin_send_acks() for (compact_map::iterator r = dn->replicas_begin(); r != dn->replicas_end(); ++r) { - ack[r->first]->add_strong_dentry(dir->dirfrag(), dn->name, dn->first, dn->last, + auto it = acks.find(r->first); + if (it == acks.end()) + continue; + it->second->add_strong_dentry(dir->dirfrag(), dn->name, dn->first, dn->last, dnl->is_primary() ? dnl->get_inode()->ino():inodeno_t(0), dnl->is_remote() ? dnl->get_remote_ino():inodeno_t(0), dnl->is_remote() ? dnl->get_remote_d_type():0, @@ -5988,10 +6011,13 @@ void MDCache::rejoin_send_acks() for (compact_map::iterator r = in->replicas_begin(); r != in->replicas_end(); ++r) { - ack[r->first]->add_inode_base(in, mds->mdsmap->get_up_features()); + auto it = acks.find(r->first); + if (it == acks.end()) + continue; + it->second->add_inode_base(in, mds->mdsmap->get_up_features()); bufferlist bl; in->_encode_locks_state_for_rejoin(bl, r->first); - ack[r->first]->add_inode_locks(in, ++r->second, bl); + it->second->add_inode_locks(in, ++r->second, bl); } // subdirs in this subtree? @@ -6005,19 +6031,25 @@ void MDCache::rejoin_send_acks() for (compact_map::iterator r = root->replicas_begin(); r != root->replicas_end(); ++r) { - ack[r->first]->add_inode_base(root, mds->mdsmap->get_up_features()); + auto it = acks.find(r->first); + if (it == acks.end()) + continue; + it->second->add_inode_base(root, mds->mdsmap->get_up_features()); bufferlist bl; root->_encode_locks_state_for_rejoin(bl, r->first); - ack[r->first]->add_inode_locks(root, ++r->second, bl); + it->second->add_inode_locks(root, ++r->second, bl); } if (myin) for (compact_map::iterator r = myin->replicas_begin(); r != myin->replicas_end(); ++r) { - ack[r->first]->add_inode_base(myin, mds->mdsmap->get_up_features()); + auto it = acks.find(r->first); + if (it == acks.end()) + continue; + it->second->add_inode_base(myin, mds->mdsmap->get_up_features()); bufferlist bl; myin->_encode_locks_state_for_rejoin(bl, r->first); - ack[r->first]->add_inode_locks(myin, ++r->second, bl); + it->second->add_inode_locks(myin, ++r->second, bl); } // include inode base for any inodes whose scatterlocks may have updated @@ -6027,14 +6059,16 @@ void MDCache::rejoin_send_acks() CInode *in = *p; for (compact_map::iterator r = in->replicas_begin(); r != in->replicas_end(); - ++r) - ack[r->first]->add_inode_base(in, mds->mdsmap->get_up_features()); + ++r) { + auto it = acks.find(r->first); + if (it == acks.end()) + continue; + it->second->add_inode_base(in, mds->mdsmap->get_up_features()); + } } // send acks - for (map::iterator p = ack.begin(); - p != ack.end(); - ++p) { + for (auto p = acks.begin(); p != acks.end(); ++p) { ::encode(rejoin_imported_caps[p->first], p->second->imported_caps); mds->send_message_mds(p->second, p->first); } @@ -6410,7 +6444,8 @@ bool MDCache::trim(int max, int count) if (max <= 0) return false; } - dout(7) << "trim max=" << max << " cur=" << lru.lru_get_size() << dendl; + dout(7) << "trim max=" << max << " cur=" << lru.lru_get_size() + << "/" << bottom_lru.lru_get_size() << dendl; // process delayed eval_stray() stray_manager.advance_delayed(); @@ -6420,22 +6455,26 @@ bool MDCache::trim(int max, int count) int unexpirable = 0; list unexpirables; + for (;;) { + CDentry *dn = static_cast(bottom_lru.lru_expire()); + if (!dn) + break; + if (trim_dentry(dn, expiremap)) { + unexpirables.push_back(dn); + ++unexpirable; + } + } + + for(auto dn : unexpirables) + bottom_lru.lru_insert_mid(dn); + unexpirables.clear(); + // trim dentries from the LRU: only enough to satisfy `max`, - // unless we see null dentries at the bottom of the LRU, - // in which case trim all those. - bool trimming_nulls = true; - while (trimming_nulls || lru.lru_get_size() + unexpirable > (unsigned)max) { + while (lru.lru_get_size() + unexpirable > (unsigned)max) { CDentry *dn = static_cast(lru.lru_expire()); if (!dn) { break; } - if (!dn->get_linkage()->is_null()) { - trimming_nulls = false; - if (lru.lru_get_size() + unexpirable < (unsigned)max) { - unexpirables.push_back(dn); - break; - } - } if ((is_standby_replay && dn->get_linkage()->inode && dn->get_linkage()->inode->item_open_file.is_on_list()) || trim_dentry(dn, expiremap)) { @@ -6443,24 +6482,41 @@ bool MDCache::trim(int max, int count) ++unexpirable; } } - for(list::iterator i = unexpirables.begin(); - i != unexpirables.end(); - ++i) - lru.lru_insert_mid(*i); + for(auto dn : unexpirables) + lru.lru_insert_mid(dn); + unexpirables.clear(); // trim non-auth, non-bound subtrees for (map >::iterator p = subtrees.begin(); p != subtrees.end();) { CDir *dir = p->first; ++p; - if (!dir->is_auth() && !dir->get_inode()->is_auth()) { - // don't trim subtree root if its auth MDS is recovering. - // This simplify the cache rejoin code. - if (dir->is_subtree_root() && - rejoin_ack_gather.count(dir->get_dir_auth().first)) - continue; - if (dir->get_num_ref() == 1) // subtree pin + CInode *diri = dir->get_inode(); + if (dir->is_auth()) { + if (!diri->is_auth() && !diri->is_base() && + dir->get_num_head_items() == 0) { + if (dir->state_test(CDir::STATE_EXPORTING) || + dir->is_freezing() || dir->is_frozen()) + continue; + + migrator->export_empty_import(dir); + } + } else { + if (!diri->is_auth()) { + if (dir->get_num_ref() > 1) // only subtree pin + continue; + list ls; + diri->get_subtree_dirfrags(ls); + if (diri->get_num_ref() > (int)ls.size()) // only pinned by subtrees + continue; + + // don't trim subtree root if its auth MDS is recovering. + // This simplify the cache rejoin code. + if (dir->is_subtree_root() && + rejoin_ack_gather.count(dir->get_dir_auth().first)) + continue; trim_dirfrag(dir, 0, expiremap); + } } } @@ -6583,7 +6639,7 @@ bool MDCache::trim_dentry(CDentry *dn, map& expiremap // unlink the dentry if (dnl->is_remote()) { // just unlink. - dir->unlink_inode(dn); + dir->unlink_inode(dn, false); } else if (dnl->is_primary()) { // expire the inode, too. CInode *in = dnl->get_inode(); @@ -6622,10 +6678,6 @@ bool MDCache::trim_dentry(CDentry *dn, map& expiremap if (clear_complete) dir->state_clear(CDir::STATE_COMPLETE); - // reexport? - if (dir->get_num_head_items() == 0 && dir->is_subtree_root()) - migrator->export_empty_import(dir); - if (mds->logger) mds->logger->inc(l_mds_inodes_expired); return false; } @@ -6753,7 +6805,7 @@ bool MDCache::trim_inode(CDentry *dn, CInode *in, CDir *con, mapget_dir()->unlink_inode(dn); + dn->get_dir()->unlink_inode(dn, false); remove_inode(in); return false; } @@ -6785,29 +6837,26 @@ void MDCache::trim_non_auth() ++p) p->first->get(CDir::PIN_SUBTREETEMP); - // note first auth item we see. - // when we see it the second time, stop. - CDentry *first_auth = 0; + list auth_list; // trim non-auth items from the lru - while (lru.lru_get_size() > 0) { - CDentry *dn = static_cast(lru.lru_expire()); - if (!dn) break; + for (;;) { + CDentry *dn = NULL; + if (bottom_lru.lru_get_size() > 0) + dn = static_cast(bottom_lru.lru_expire()); + if (!dn && lru.lru_get_size() > 0) + dn = static_cast(lru.lru_expire()); + if (!dn) + break; + CDentry::linkage_t *dnl = dn->get_linkage(); if (dn->is_auth()) { // add back into lru (at the top) - lru.lru_insert_top(dn); + auth_list.push_back(dn); if (dnl->is_remote() && dnl->get_inode() && !dnl->get_inode()->is_auth()) dn->unlink_remote(dnl); - - if (!first_auth) { - first_auth = dn; - } else { - if (first_auth == dn) - break; - } } else { // non-auth. expire. CDir *dir = dn->get_dir(); @@ -6816,7 +6865,7 @@ void MDCache::trim_non_auth() // unlink the dentry dout(10) << " removing " << *dn << dendl; if (dnl->is_remote()) { - dir->unlink_inode(dn); + dir->unlink_inode(dn, false); } else if (dnl->is_primary()) { CInode *in = dnl->get_inode(); @@ -6828,7 +6877,7 @@ void MDCache::trim_non_auth() assert(!subdir->is_subtree_root()); in->close_dirfrag(subdir->dirfrag().frag); } - dir->unlink_inode(dn); + dir->unlink_inode(dn, false); remove_inode(in); } else { @@ -6845,6 +6894,13 @@ void MDCache::trim_non_auth() } } + for (auto dn : auth_list) { + if (dn->state_test(CDentry::STATE_BOTTOMLRU)) + bottom_lru.lru_insert_mid(dn); + else + lru.lru_insert_top(dn); + } + // move everything in the pintail to the top bit of the lru. lru.lru_touch_entire_pintail(); @@ -6854,7 +6910,8 @@ void MDCache::trim_non_auth() ++p) p->first->put(CDir::PIN_SUBTREETEMP); - if (lru.lru_get_size() == 0) { + if (lru.lru_get_size() == 0 && + bottom_lru.lru_get_size() == 0) { // root, stray, etc.? ceph::unordered_map::iterator p = inode_map.begin(); while (p != inode_map.end()) { @@ -6929,7 +6986,7 @@ bool MDCache::trim_non_auth_subtree(CDir *dir) } if (!keep_inode) { // remove it! dout(20) << "trim_non_auth_subtree(" << dir << ") removing inode " << in << " with dentry" << dn << dendl; - dir->unlink_inode(dn); + dir->unlink_inode(dn, false); remove_inode(in); assert(!dir->has_bloom()); dir->remove_dentry(dn); @@ -6943,7 +7000,7 @@ bool MDCache::trim_non_auth_subtree(CDir *dir) } else { // just remove it dout(20) << "trim_non_auth_subtree(" << dir << ") removing dentry " << dn << dendl; if (dnl->is_remote()) - dir->unlink_inode(dn); + dir->unlink_inode(dn, false); dir->remove_dentry(dn); } } @@ -7430,7 +7487,7 @@ void MDCache::shutdown_check() mds->timer.add_event_after(g_conf->mds_shutdown_check, new C_MDC_ShutdownCheck(this)); // this - dout(0) << "lru size now " << lru.lru_get_size() << dendl; + dout(0) << "lru size now " << lru.lru_get_size() << "/" << bottom_lru.lru_get_size() << dendl; dout(0) << "log len " << mds->mdlog->get_num_events() << dendl; @@ -7482,7 +7539,7 @@ bool MDCache::shutdown_pass() // trim cache trim(0); - dout(5) << "lru size now " << lru.lru_get_size() << dendl; + dout(5) << "lru size now " << lru.lru_get_size() << "/" << bottom_lru.lru_get_size() << dendl; // SUBTREES int num_auth_subtree = 0; @@ -7547,20 +7604,6 @@ bool MDCache::shutdown_pass() assert(!migrator->is_exporting()); assert(!migrator->is_importing()); - // make mydir subtree go away - if (mydir) { - adjust_subtree_auth(mydir, CDIR_AUTH_UNKNOWN); - remove_subtree(mydir); - } - assert(subtrees.empty()); - - // Still replicas of mydir? - if ((mydir != NULL) && mydir->inode->is_replicated()) { - // We do this because otherwise acks to locks could come in after - // we cap the log. - dout(7) << "waiting for mydir replicas to release: " << *mydir << dendl; - return false; - } // flush what we can from the log mds->mdlog->trim(0); @@ -7600,12 +7643,28 @@ bool MDCache::shutdown_pass() } // trim what we can from the cache - if (lru.lru_get_size() > 0) { - dout(7) << "there's still stuff in the cache: " << lru.lru_get_size() << dendl; + if (lru.lru_get_size() > 0 || bottom_lru.lru_get_size() > 0) { + dout(7) << "there's still stuff in the cache: " << lru.lru_get_size() << "/" << bottom_lru.lru_get_size() << dendl; show_cache(); //dump(); return false; } + + // make mydir subtree go away + if (mydir) { + if (mydir->get_num_ref() > 1) { // subtree pin + dout(7) << "there's still reference to mydir " << *mydir << dendl; + show_cache(); + return false; + } + + remove_subtree(mydir); + myin->close_dirfrag(mydir->get_frag()); + } + assert(subtrees.empty()); + + if (myin) + remove_inode(myin); // done! dout(2) << "shutdown done." << dendl; @@ -8174,9 +8233,12 @@ struct C_MDC_OpenRemoteDentry : public MDCacheContext { MDSInternalContextBase *onfinish; bool want_xlocked; C_MDC_OpenRemoteDentry(MDCache *m, CDentry *d, inodeno_t i, MDSInternalContextBase *f, bool wx) : - MDCacheContext(m), dn(d), ino(i), onfinish(f), want_xlocked(wx) {} + MDCacheContext(m), dn(d), ino(i), onfinish(f), want_xlocked(wx) { + dn->get(MDSCacheObject::PIN_PTRWAITER); + } void finish(int r) override { mdcache->_open_remote_dentry_finish(dn, ino, onfinish, want_xlocked, r); + dn->put(MDSCacheObject::PIN_PTRWAITER); } }; @@ -8194,22 +8256,26 @@ void MDCache::_open_remote_dentry_finish(CDentry *dn, inodeno_t ino, MDSInternal bool want_xlocked, int r) { if (r < 0) { + CDentry::linkage_t *dnl = dn->get_projected_linkage(); + if (dnl->is_remote() && dnl->get_remote_ino() == ino) { dout(0) << "open_remote_dentry_finish bad remote dentry " << *dn << dendl; dn->state_set(CDentry::STATE_BADREMOTEINO); std::string path; CDir *dir = dn->get_dir(); if (dir) { - dir->get_inode()->make_path_string(path); - path = path + "/" + dn->get_name(); + dir->get_inode()->make_path_string(path); + path = path + "/" + dn->get_name(); } - bool fatal = mds->damage_table.notify_remote_damaged( - dn->get_projected_linkage()->get_remote_ino(), path); + bool fatal = mds->damage_table.notify_remote_damaged(ino, path); if (fatal) { - mds->damaged(); - ceph_abort(); // unreachable, damaged() respawns us + mds->damaged(); + ceph_abort(); // unreachable, damaged() respawns us } + } else { + r = 0; + } } fin->complete(r < 0 ? r : 0); } @@ -9426,59 +9492,6 @@ void MDCache::scan_stray_dir(dirfrag_t next) } } -/** - * If a remote dentry refers to an inode whose primary - * dentry is a stray, then evaluate the inode for purging if - * we have the auth copy, or migrate the stray to use if we - * do not. - */ -void MDCache::eval_remote(CDentry *remote_dn) -{ - assert(remote_dn); - dout(10) << __func__ << " " << *remote_dn << dendl; - - CDentry::linkage_t *dnl = remote_dn->get_projected_linkage(); - assert(dnl->is_remote()); - CInode *in = dnl->get_inode(); - - if (!in) { - dout(20) << __func__ << ": no inode, cannot evaluate" << dendl; - return; - } - - if (remote_dn->last != CEPH_NOSNAP) { - dout(20) << __func__ << ": snap dentry, cannot evaluate" << dendl; - return; - } - - // refers to stray? - CDentry *primary_dn = in->get_projected_parent_dn(); - assert(primary_dn != NULL); - if (primary_dn->get_dir()->get_inode()->is_stray()) { - if (in->is_auth()) { - dout(20) << __func__ << ": have auth for inode, evaluating" << dendl; - - stray_manager.eval_remote_stray(primary_dn, remote_dn); - } else { - dout(20) << __func__ << ": do not have auth for inode, migrating " << dendl; - /* - * Inodes get filed into a stray dentry when a client unlinks - * the primary DN for them. However, that doesn't mean there - * isn't a remote DN still in the world. The remote DN just - * ends up pointing at a stray. Strays can pretty much live - * forever in this scenario. - * - * Therefore, we have a special behaviour here: migrate a stray - * to when handle a client request with a trace referring - * to a stray inode on another MDS. - */ - stray_manager.migrate_stray(primary_dn, mds->get_nodeid()); - } - } else { - dout(20) << __func__ << ": inode's primary dn not stray" << dendl; - } -} - void MDCache::fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Context *fin) { object_t oid = CInode::get_object_name(ino, frag_t(), ""); @@ -9645,7 +9658,7 @@ void MDCache::discover_path(CDir *base, !base->is_waiting_for_dentry(want_path[0].c_str(), snap) || !onfinish) { discover_info_t& d = _create_discover(from); d.ino = base->ino(); - d.pin_base(base); + d.pin_base(base->inode); d.frag = base->get_frag(); d.snap = snap; d.want_path = want_path; @@ -9826,15 +9839,15 @@ void MDCache::handle_discover(MDiscover *dis) curdir = cur->get_or_open_dirfrag(this, fg); } else if (curdir->is_frozen_tree() || (curdir->is_frozen_dir() && fragment_are_all_frozen(curdir))) { + if (!reply->is_empty()) { + dout(7) << *curdir << " is frozen, non-empty reply, stopping" << dendl; + break; + } if (dis->wants_base_dir() && dis->get_base_dir_frag() != curdir->get_frag()) { dout(7) << *curdir << " is frozen, dirfrag mismatch, stopping" << dendl; reply->set_flag_error_dir(); break; } - if (!reply->is_empty()) { - dout(7) << *curdir << " is frozen, non-empty reply, stopping" << dendl; - break; - } dout(7) << *curdir << " is frozen, empty reply, waiting" << dendl; curdir->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryMessage(mds, dis)); reply->put(); @@ -9861,6 +9874,7 @@ void MDCache::handle_discover(MDiscover *dis) CDentry *dn = 0; if (curdir->get_version() == 0) { // fetch newly opened dir + assert(!curdir->has_bloom()); } else if (dis->get_want().depth() > 0) { // lookup dentry dn = curdir->lookup(dis->get_dentry(i), snapid); @@ -9869,7 +9883,8 @@ void MDCache::handle_discover(MDiscover *dis) // incomplete dir? if (!dn) { - if (!curdir->is_complete()) { + if (!curdir->is_complete() && + (!curdir->has_bloom() || curdir->is_in_bloom(dis->get_dentry(i)))) { // readdir dout(7) << "incomplete dir contents for " << *curdir << ", fetching" << dendl; if (reply->is_empty()) { @@ -9892,6 +9907,13 @@ void MDCache::handle_discover(MDiscover *dis) } assert(dn); + // don't add replica to purging dentry/inode + if (dn->state_test(CDentry::STATE_PURGING)) { + if (reply->is_empty()) + reply->set_flag_error_dn(dis->get_dentry(i)); + break; + } + CDentry::linkage_t *dnl = dn->get_linkage(); // xlocked dentry? @@ -10057,10 +10079,11 @@ void MDCache::handle_discover_reply(MDiscoverReply *m) if (who >= 0) dout(7) << " dir_auth_hint is " << m->get_dir_auth_hint() << dendl; - frag_t fg = m->get_base_dir_frag(); - CDir *dir = cur->get_dirfrag(fg); if (m->get_wanted_base_dir()) { + frag_t fg = m->get_base_dir_frag(); + CDir *dir = cur->get_dirfrag(fg); + if (cur->is_waiting_for_dir(fg)) { if (cur->is_auth()) cur->take_waiting(CInode::WAIT_DIR, finished); @@ -10074,6 +10097,8 @@ void MDCache::handle_discover_reply(MDiscoverReply *m) // try again? if (m->get_error_dentry().length()) { + frag_t fg = cur->pick_dirfrag(m->get_error_dentry()); + CDir *dir = cur->get_dirfrag(fg); // wanted a dentry if (dir && dir->is_waiting_for_dentry(m->get_error_dentry(), m->get_wanted_snapid())) { if (dir->is_auth() || dir->lookup(m->get_error_dentry())) { @@ -10087,6 +10112,17 @@ void MDCache::handle_discover_reply(MDiscoverReply *m) dout(7) << " doing nothing, have dir but nobody is waiting on dentry " << m->get_error_dentry() << dendl; } + } else if (m->is_flag_error_dn()) { + frag_t fg = cur->pick_dirfrag(m->get_error_dentry()); + CDir *dir = cur->get_dirfrag(fg); + if (dir) { + if (dir->is_auth()) { + dir->take_sub_waiting(finished); + } else { + dir->take_dentry_waiting(m->get_error_dentry(), m->get_wanted_snapid(), + m->get_wanted_snapid(), error); + } + } } // waiters @@ -10480,7 +10516,6 @@ void MDCache::handle_dentry_unlink(MDentryUnlink *m) !in->state_test(CInode::STATE_EXPORTINGCAPS)) migrator->export_caps(in); - touch_dentry_bottom(straydn); // move stray to end of lru straydn = NULL; } else { assert(!straydn); @@ -10488,9 +10523,6 @@ void MDCache::handle_dentry_unlink(MDentryUnlink *m) dn->dir->unlink_inode(dn); } assert(dnl->is_null()); - - // move to bottom of lru - touch_dentry_bottom(dn); } } @@ -10671,13 +10703,26 @@ void MDCache::adjust_dir_fragments(CInode *diri, // are my constituent bits subtrees? if so, i will be too. // (it's all or none, actually.) - bool was_subtree = false; - set new_bounds; - for (list::iterator p = srcfrags.begin(); p != srcfrags.end(); ++p) { - CDir *dir = *p; + bool any_subtree = false; + for (CDir *dir : srcfrags) { if (dir->is_subtree_root()) { + any_subtree = true; + break; + } + } + set new_bounds; + if (any_subtree) { + for (CDir *dir : srcfrags) { + // this simplifies the code that find subtrees underneath the dirfrag + if (!dir->is_subtree_root()) { + dir->state_set(CDir::STATE_AUXSUBTREE); + adjust_subtree_auth(dir, mds->get_nodeid()); + } + } + + for (CDir *dir : srcfrags) { + assert(dir->is_subtree_root()); dout(10) << " taking srcfrag subtree bounds from " << *dir << dendl; - was_subtree = true; map >::iterator q = subtrees.find(dir); set::iterator r = q->second.begin(); while (r != subtrees[dir].end()) { @@ -10685,7 +10730,7 @@ void MDCache::adjust_dir_fragments(CInode *diri, subtrees[dir].erase(r++); } subtrees.erase(q); - + // remove myself as my parent's bound if (parent_subtree) subtrees[parent_subtree].erase(dir); @@ -10695,9 +10740,8 @@ void MDCache::adjust_dir_fragments(CInode *diri, // merge CDir *f = new CDir(diri, basefrag, this, srcfrags.front()->is_auth()); f->merge(srcfrags, waiters, replay); - diri->add_dirfrag(f); - if (was_subtree) { + if (any_subtree) { assert(f->is_subtree_root()); subtrees[f].swap(new_bounds); if (parent_subtree) @@ -10785,6 +10829,11 @@ void MDCache::split_dir(CDir *dir, int bits) return; } + if (dir->frag.bits() + bits > 24) { + dout(7) << __func__ << " frag bits > 24, dropping" << dendl; + return; + } + MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_FRAGMENTDIR); mdr->more()->fragment_base = dir->dirfrag(); @@ -11780,26 +11829,26 @@ void MDCache::show_cache() } } -void MDCache::dump_cache(std::string const &file_name) +int MDCache::dump_cache(std::string const &file_name) { - dump_cache(file_name.c_str(), NULL); + return dump_cache(file_name.c_str(), NULL); } -void MDCache::dump_cache(Formatter *f) +int MDCache::dump_cache(Formatter *f) { - dump_cache(NULL, f); + return dump_cache(NULL, f); } -void MDCache::dump_cache(const string& dump_root, int depth, Formatter *f) +int MDCache::dump_cache(const string& dump_root, int depth, Formatter *f) { - dump_cache(NULL, f, dump_root, depth); + return dump_cache(NULL, f, dump_root, depth); } /** * Dump the metadata cache, either to a Formatter, if * provided, else to a plain text file. */ -void MDCache::dump_cache(const char *fn, Formatter *f, +int MDCache::dump_cache(const char *fn, Formatter *f, const string& dump_root, int depth) { int r = 0; @@ -11819,7 +11868,7 @@ void MDCache::dump_cache(const char *fn, Formatter *f, fd = ::open(fn, O_WRONLY|O_CREAT|O_EXCL, 0600); if (fd < 0) { derr << "failed to open " << fn << ": " << cpp_strerror(errno) << dendl; - return; + return errno; } } @@ -11921,6 +11970,7 @@ void MDCache::dump_cache(const char *fn, Formatter *f, } else { ::close(fd); } + return r; } @@ -12349,3 +12399,19 @@ void MDCache::maybe_eval_stray(CInode *in, bool delay) { } } +void MDCache::clear_dirty_bits_for_stray(CInode* diri) { + dout(10) << __func__ << " " << *diri << dendl; + assert(diri->get_projected_parent_dir()->inode->is_stray()); + list ls; + diri->get_dirfrags(ls); + for (auto p : ls) { + if (p->is_auth() && !(p->is_frozen() || p->is_freezing())) + p->try_remove_dentries_for_stray(); + } + if (!diri->snaprealm) { + if (diri->is_auth()) + diri->clear_dirty_rstat(); + diri->clear_scatter_dirty(); + } +} + diff --git a/ceph/src/mds/MDCache.h b/ceph/src/mds/MDCache.h index 28ebc48ec..768f4cc92 100644 --- a/ceph/src/mds/MDCache.h +++ b/ceph/src/mds/MDCache.h @@ -114,6 +114,7 @@ class MDCache { // -- my cache -- LRU lru; // dentry lru for expiring items from cache + LRU bottom_lru; // dentries that should be trimmed ASAP protected: ceph::unordered_map inode_map; // map of inodes by ino CInode *root; // root inode @@ -154,6 +155,8 @@ public: } void maybe_eval_stray(CInode *in, bool delay=false); + void clear_dirty_bits_for_stray(CInode* diri); + bool is_readonly() { return readonly; } void force_readonly(); @@ -193,6 +196,11 @@ public: stray_manager.notify_stray_created(); } + void eval_remote(CDentry *dn) + { + stray_manager.eval_remote(dn); + } + // -- client caps -- uint64_t last_cap_id; @@ -206,20 +214,20 @@ public: frag_t frag; snapid_t snap; filepath want_path; - MDSCacheObject *base; + CInode *basei; bool want_base_dir; bool want_xlocked; discover_info_t() : - tid(0), mds(-1), snap(CEPH_NOSNAP), base(NULL), + tid(0), mds(-1), snap(CEPH_NOSNAP), basei(NULL), want_base_dir(false), want_xlocked(false) {} ~discover_info_t() { - if (base) - base->put(MDSCacheObject::PIN_DISCOVERBASE); + if (basei) + basei->put(MDSCacheObject::PIN_DISCOVERBASE); } - void pin_base(MDSCacheObject *b) { - base = b; - base->get(MDSCacheObject::PIN_DISCOVERBASE); + void pin_base(CInode *b) { + basei = b; + basei->get(MDSCacheObject::PIN_DISCOVERBASE); } }; @@ -491,6 +499,7 @@ protected: bool rejoins_pending; set rejoin_gather; // nodes from whom i need a rejoin set rejoin_sent; // nodes i sent a rejoin to + set rejoin_ack_sent; // nodes i sent a rejoin to set rejoin_ack_gather; // nodes from whom i need a rejoin ack map > > rejoin_imported_caps; map > > rejoin_slave_exports; @@ -766,28 +775,19 @@ public: } public: void touch_dentry(CDentry *dn) { - // touch ancestors - if (dn->get_dir()->get_inode()->get_projected_parent_dn()) - touch_dentry(dn->get_dir()->get_inode()->get_projected_parent_dn()); - - // touch me - if (dn->is_auth()) - lru.lru_touch(dn); - else - lru.lru_midtouch(dn); + if (dn->state_test(CDentry::STATE_BOTTOMLRU)) { + bottom_lru.lru_midtouch(dn); + } else { + if (dn->is_auth()) + lru.lru_touch(dn); + else + lru.lru_midtouch(dn); + } } void touch_dentry_bottom(CDentry *dn) { + if (dn->state_test(CDentry::STATE_BOTTOMLRU)) + return; lru.lru_bottouch(dn); - if (dn->get_projected_linkage()->is_primary() && - dn->get_dir()->inode->is_stray()) { - CInode *in = dn->get_projected_linkage()->get_inode(); - if (in->has_dirfrags()) { - list ls; - in->get_dirfrags(ls); - for (list::iterator p = ls.begin(); p != ls.end(); ++p) - (*p)->touch_dentries_bottom(); - } - } } protected: @@ -976,7 +976,6 @@ public: // -- stray -- public: - void eval_remote(CDentry *dn); void fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Context *fin); uint64_t get_num_strays() const { return stray_manager.get_num_strays(); } @@ -1122,14 +1121,14 @@ public: void discard_delayed_expire(CDir *dir); protected: - void dump_cache(const char *fn, Formatter *f, + int dump_cache(const char *fn, Formatter *f, const std::string& dump_root = "", int depth = -1); public: - void dump_cache() {dump_cache(NULL, NULL);} - void dump_cache(const std::string &filename); - void dump_cache(Formatter *f); - void dump_cache(const std::string& dump_root, int depth, Formatter *f); + int dump_cache() { return dump_cache(NULL, NULL); } + int dump_cache(const std::string &filename); + int dump_cache(Formatter *f); + int dump_cache(const std::string& dump_root, int depth, Formatter *f); void dump_resolve_status(Formatter *f) const; void dump_rejoin_status(Formatter *f) const; diff --git a/ceph/src/mds/MDLog.cc b/ceph/src/mds/MDLog.cc index f02489fd1..e8e5d3abe 100644 --- a/ceph/src/mds/MDLog.cc +++ b/ceph/src/mds/MDLog.cc @@ -782,9 +782,11 @@ void MDLog::_trim_expired_segments() // this was the oldest segment, adjust expire pos if (journaler->get_expire_pos() < ls->end) { journaler->set_expire_pos(ls->end); + logger->set(l_mdl_expos, ls->end); + } else { + logger->set(l_mdl_expos, ls->offset); } - logger->set(l_mdl_expos, ls->offset); logger->inc(l_mdl_segtrm); logger->inc(l_mdl_evtrm, ls->num_events); @@ -847,7 +849,7 @@ void MDLog::replay(MDSInternalContextBase *c) // empty? if (journaler->get_read_pos() == journaler->get_write_pos()) { dout(10) << "replay - journal empty, done." << dendl; - mds->mdcache->trim(-1); + mds->mdcache->trim(); if (c) { c->complete(0); } diff --git a/ceph/src/mds/MDSCacheObject.h b/ceph/src/mds/MDSCacheObject.h index ec40359dd..1bc80cfed 100644 --- a/ceph/src/mds/MDSCacheObject.h +++ b/ceph/src/mds/MDSCacheObject.h @@ -48,10 +48,10 @@ struct mdsco_db_line_prefix { MDSCacheObject *object; explicit mdsco_db_line_prefix(MDSCacheObject *o) : object(o) {} }; -std::ostream& operator<<(std::ostream& out, mdsco_db_line_prefix o); +std::ostream& operator<<(std::ostream& out, const mdsco_db_line_prefix& o); // printer -std::ostream& operator<<(std::ostream& out, MDSCacheObject &o); +std::ostream& operator<<(std::ostream& out, const MDSCacheObject &o); class MDSCacheObject { public: @@ -406,7 +406,7 @@ inline std::ostream& operator<<(std::ostream& out, MDSCacheObject &o) { return out; } -inline std::ostream& operator<<(std::ostream& out, mdsco_db_line_prefix o) { +inline std::ostream& operator<<(std::ostream& out, const mdsco_db_line_prefix& o) { o.object->print_db_line_prefix(out); return out; } diff --git a/ceph/src/mds/MDSDaemon.cc b/ceph/src/mds/MDSDaemon.cc index 4c3d558ed..29aa5c2ce 100644 --- a/ceph/src/mds/MDSDaemon.cc +++ b/ceph/src/mds/MDSDaemon.cc @@ -661,9 +661,15 @@ COMMAND("cpu_profiler " \ COMMAND("session ls " \ "name=filters,type=CephString,n=N,req=false", "List client sessions", "mds", "r", "cli,rest") +COMMAND("client ls " \ + "name=filters,type=CephString,n=N,req=false", + "List client sessions", "mds", "r", "cli,rest") COMMAND("session evict " \ "name=filters,type=CephString,n=N,req=false", "Evict client session(s)", "mds", "rw", "cli,rest") +COMMAND("client evict " \ + "name=filters,type=CephString,n=N,req=false", + "Evict client session(s)", "mds", "rw", "cli,rest") COMMAND("damage ls", "List detected metadata damage", "mds", "r", "cli,rest") COMMAND("damage rm name=damage_id,type=CephInt", @@ -774,7 +780,9 @@ int MDSDaemon::_handle_command( int64_t session_id = 0; bool got = cmd_getval(cct, cmdmap, "session_id", session_id); assert(got); - bool killed = mds_rank->kill_session(session_id, false, ss); + bool killed = mds_rank->evict_client(session_id, false, + g_conf->mds_session_blacklist_on_evict, + ss); if (!killed) r = -ENOENT; } else if (prefix == "heap") { diff --git a/ceph/src/mds/MDSDaemon.h b/ceph/src/mds/MDSDaemon.h index 2abcd87fe..1c6a7d791 100644 --- a/ceph/src/mds/MDSDaemon.h +++ b/ceph/src/mds/MDSDaemon.h @@ -40,7 +40,7 @@ #include "Beacon.h" -#define CEPH_MDS_PROTOCOL 29 /* cluster internal */ +#define CEPH_MDS_PROTOCOL 30 /* cluster internal */ class MonClient; diff --git a/ceph/src/mds/MDSMap.cc b/ceph/src/mds/MDSMap.cc index da223e866..b397eb089 100644 --- a/ceph/src/mds/MDSMap.cc +++ b/ceph/src/mds/MDSMap.cc @@ -178,8 +178,8 @@ void MDSMap::dump(Formatter *f) const } f->close_section(); f->open_array_section("data_pools"); - for (set::const_iterator p = data_pools.begin(); p != data_pools.end(); ++p) - f->dump_int("pool", *p); + for (const auto p: data_pools) + f->dump_int("pool", p); f->close_section(); f->dump_int("metadata_pool", metadata_pool); f->dump_bool("enabled", enabled); @@ -192,7 +192,7 @@ void MDSMap::generate_test_instances(list& ls) { MDSMap *m = new MDSMap(); m->max_mds = 1; - m->data_pools.insert(0); + m->data_pools.push_back(0); m->metadata_pool = 1; m->cas_pool = 2; m->compat = get_mdsmap_compat_set_all(); @@ -498,8 +498,8 @@ void MDSMap::encode(bufferlist& bl, uint64_t features) const } n = data_pools.size(); ::encode(n, bl); - for (set::const_iterator p = data_pools.begin(); p != data_pools.end(); ++p) { - n = *p; + for (const auto p: data_pools) { + n = p; ::encode(n, bl); } @@ -603,7 +603,7 @@ void MDSMap::decode(bufferlist::iterator& p) while (n--) { __u32 m; ::decode(m, p); - data_pools.insert(m); + data_pools.push_back(m); } __s32 s; ::decode(s, p); diff --git a/ceph/src/mds/MDSMap.h b/ceph/src/mds/MDSMap.h index 1d8e29b2a..e99be2be6 100644 --- a/ceph/src/mds/MDSMap.h +++ b/ceph/src/mds/MDSMap.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "common/config.h" @@ -178,7 +179,7 @@ protected: __u32 session_autoclose; uint64_t max_file_size; - std::set data_pools; // file data pools available to clients (via an ioctl). first is the default. + std::vector data_pools; // file data pools available to clients (via an ioctl). first is the default. int64_t cas_pool; // where CAS objects go int64_t metadata_pool; // where fs metadata objects go @@ -309,11 +310,11 @@ public: mds_rank_t get_tableserver() const { return tableserver; } mds_rank_t get_root() const { return root; } - const std::set &get_data_pools() const { return data_pools; } + const std::vector &get_data_pools() const { return data_pools; } int64_t get_first_data_pool() const { return *data_pools.begin(); } int64_t get_metadata_pool() const { return metadata_pool; } bool is_data_pool(int64_t poolid) const { - return data_pools.count(poolid); + return std::binary_search(data_pools.begin(), data_pools.end(), poolid); } bool pool_in_use(int64_t poolid) const { @@ -346,6 +347,10 @@ public: unsigned get_num_up_mds() const { return up.size(); } + mds_rank_t get_last_in_mds() const { + auto p = in.rbegin(); + return p == in.rend() ? MDS_RANK_NONE : *p; + } int get_num_failed_mds() const { return failed.size(); } @@ -360,10 +365,10 @@ public: // data pools void add_data_pool(int64_t poolid) { - data_pools.insert(poolid); + data_pools.push_back(poolid); } int remove_data_pool(int64_t poolid) { - std::set::iterator p = data_pools.find(poolid); + std::vector::iterator p = std::find(data_pools.begin(), data_pools.end(), poolid); if (p == data_pools.end()) return -ENOENT; data_pools.erase(p); diff --git a/ceph/src/mds/MDSRank.cc b/ceph/src/mds/MDSRank.cc index 7aa53dcc0..6d75054ad 100644 --- a/ceph/src/mds/MDSRank.cc +++ b/ceph/src/mds/MDSRank.cc @@ -351,7 +351,7 @@ void MDSRankDispatcher::shutdown() finisher->stop(); // no flushing mds_lock.Lock(); - if (objecter->initialized.read()) + if (objecter->initialized) objecter->shutdown(); monc->shutdown(); @@ -975,9 +975,6 @@ void MDSRank::set_osd_epoch_barrier(epoch_t e) osd_epoch_barrier = e; } -/** - * FIXME ugly call up to MDS daemon until the dispatching is separated out - */ void MDSRank::retry_dispatch(Message *m) { inc_dispatch_depth(); @@ -1338,6 +1335,23 @@ void MDSRank::reconnect_start() reopen_log(); } + // Drop any blacklisted clients from the SessionMap before going + // into reconnect, so that we don't wait for them. + objecter->enable_blacklist_events(); + std::set blacklist; + epoch_t epoch = 0; + objecter->with_osdmap([this, &blacklist, &epoch](const OSDMap& o) { + o.get_blacklist(&blacklist); + epoch = o.get_epoch(); + }); + auto killed = server->apply_blacklist(blacklist); + dout(4) << "reconnect_start: killed " << killed << " blacklisted sessions (" + << blacklist.size() << " blacklist entries, " + << sessionmap.get_sessions().size() << ")" << dendl; + if (killed) { + set_osd_epoch_barrier(epoch); + } + server->reconnect_clients(new C_MDS_VoidFn(this, &MDSRank::reconnect_done)); finish_contexts(g_ceph_context, waiting_for_reconnect); } @@ -1508,6 +1522,9 @@ void MDSRank::boot_create() mdlog->journal_segment_subtree_map(fin.new_sub()); mdlog->flush(); + // Usually we do this during reconnect, but creation skips that. + objecter->enable_blacklist_events(); + fin.activate(); } @@ -1859,9 +1876,10 @@ bool MDSRankDispatcher::handle_asok_command( } mds_lock.Lock(); - stringstream dss; - bool killed = kill_session(strtol(client_id.c_str(), 0, 10), true, dss); - if (!killed) { + std::stringstream dss; + bool evicted = evict_client(strtol(client_id.c_str(), 0, 10), true, + g_conf->mds_session_blacklist_on_evict, dss); + if (!evicted) { dout(15) << dss.str() << dendl; ss << dss.str(); } @@ -1901,10 +1919,15 @@ bool MDSRankDispatcher::handle_asok_command( } else if (command == "dump cache") { Mutex::Locker l(mds_lock); string path; + int r; if(!cmd_getval(g_ceph_context, cmdmap, "path", path)) { - mdcache->dump_cache(f); + r = mdcache->dump_cache(f); } else { - mdcache->dump_cache(path); + r = mdcache->dump_cache(path); + } + + if (r != 0) { + ss << "Failed to dump cache: " << cpp_strerror(r); } } else if (command == "dump tree") { string root; @@ -1914,7 +1937,10 @@ bool MDSRankDispatcher::handle_asok_command( depth = -1; { Mutex::Locker l(mds_lock); - mdcache->dump_cache(root, depth, f); + int r = mdcache->dump_cache(root, depth, f); + if (r != 0) { + ss << "Failed to dump tree: " << cpp_strerror(r); + } } } else if (command == "force_readonly") { Mutex::Locker l(mds_lock); @@ -1954,7 +1980,7 @@ public: * MDSRank after calling it (we could have gone into shutdown): just * send your result back to the calling client and finish. */ -void MDSRankDispatcher::evict_sessions(const SessionFilter &filter, MCommand *m) +void MDSRankDispatcher::evict_clients(const SessionFilter &filter, MCommand *m) { C_MDS_Send_Command_Reply *reply = new C_MDS_Send_Command_Reply(this, m); @@ -1988,7 +2014,9 @@ void MDSRankDispatcher::evict_sessions(const SessionFilter &filter, MCommand *m) C_GatherBuilder gather(g_ceph_context, reply); for (const auto s : victims) { - server->kill_session(s, gather.new_sub()); + std::stringstream ss; + evict_client(s->info.inst.name.num(), false, + g_conf->mds_session_blacklist_on_evict, ss, gather.new_sub()); } gather.activate(); } @@ -2599,34 +2627,133 @@ void MDSRankDispatcher::handle_osd_map() purge_queue.update_op_limit(*mdsmap); + std::set newly_blacklisted; + objecter->consume_blacklist_events(&newly_blacklisted); + auto epoch = objecter->with_osdmap([](const OSDMap &o){return o.get_epoch();}); + dout(4) << "handle_osd_map epoch " << epoch << ", " + << newly_blacklisted.size() << " new blacklist entries" << dendl; + auto victims = server->apply_blacklist(newly_blacklisted); + if (victims) { + set_osd_epoch_barrier(epoch); + } + + // By default the objecter only requests OSDMap updates on use, // we would like to always receive the latest maps in order to // apply policy based on the FULL flag. objecter->maybe_request_map(); } -bool MDSRankDispatcher::kill_session(int64_t session_id, bool wait, std::stringstream& err_ss) +bool MDSRank::evict_client(int64_t session_id, + bool wait, bool blacklist, std::stringstream& err_ss, + Context *on_killed) { + assert(mds_lock.is_locked_by_me()); + + // Mutually exclusive args + assert(!(wait && on_killed != nullptr)); + if (is_any_replay()) { err_ss << "MDS is replaying log"; return false; } - Session *session = sessionmap.get_session(entity_name_t(CEPH_ENTITY_TYPE_CLIENT, session_id)); + Session *session = sessionmap.get_session( + entity_name_t(CEPH_ENTITY_TYPE_CLIENT, session_id)); if (!session) { err_ss << "session " << session_id << " not in sessionmap!"; return false; } - if (wait) { - C_SaferCond on_safe; - server->kill_session(session, &on_safe); + dout(4) << "Preparing blacklist command... (wait=" << wait << ")" << dendl; + stringstream ss; + ss << "{\"prefix\":\"osd blacklist\", \"blacklistop\":\"add\","; + ss << "\"addr\":\""; + ss << session->info.inst.addr; + ss << "\"}"; + std::string tmp = ss.str(); + std::vector cmd = {tmp}; + + auto kill_mds_session = [this, session_id, on_killed](){ + assert(mds_lock.is_locked_by_me()); + Session *session = sessionmap.get_session( + entity_name_t(CEPH_ENTITY_TYPE_CLIENT, session_id)); + if (session) { + if (on_killed) { + server->kill_session(session, on_killed); + } else { + C_SaferCond on_safe; + server->kill_session(session, &on_safe); + + mds_lock.Unlock(); + on_safe.wait(); + mds_lock.Lock(); + } + } else { + dout(1) << "session " << session_id << " was removed while we waited " + "for blacklist" << dendl; + + // Even though it wasn't us that removed it, kick our completion + // as the session has been removed. + if (on_killed) { + on_killed->complete(0); + } + } + }; + + auto background_blacklist = [this, session_id, cmd](std::function fn){ + assert(mds_lock.is_locked_by_me()); + + Context *on_blacklist_done = new FunctionContext([this, session_id, fn](int r) { + objecter->wait_for_latest_osdmap( + new C_OnFinisher( + new FunctionContext([this, session_id, fn](int r) { + Mutex::Locker l(mds_lock); + auto epoch = objecter->with_osdmap([](const OSDMap &o){ + return o.get_epoch(); + }); + + set_osd_epoch_barrier(epoch); + + fn(); + }), finisher) + ); + }); + + dout(4) << "Sending mon blacklist command: " << cmd[0] << dendl; + monc->start_mon_command(cmd, {}, nullptr, nullptr, on_blacklist_done); + }; + + auto blocking_blacklist = [this, cmd, &err_ss, background_blacklist](){ + C_SaferCond inline_ctx; + background_blacklist([&inline_ctx](){inline_ctx.complete(0);}); mds_lock.Unlock(); - on_safe.wait(); + inline_ctx.wait(); mds_lock.Lock(); + }; + + if (wait) { + if (blacklist) { + blocking_blacklist(); + } + + // We dropped mds_lock, so check that session still exists + session = sessionmap.get_session(entity_name_t(CEPH_ENTITY_TYPE_CLIENT, + session_id)); + if (!session) { + dout(1) << "session " << session_id << " was removed while we waited " + "for blacklist" << dendl; + return true; + } + kill_mds_session(); } else { - server->kill_session(session, NULL); + if (blacklist) { + background_blacklist(kill_mds_session); + } else { + kill_mds_session(); + } } + return true; } @@ -2676,7 +2803,7 @@ bool MDSRankDispatcher::handle_command( std::string prefix; cmd_getval(g_ceph_context, cmdmap, "prefix", prefix); - if (prefix == "session ls") { + if (prefix == "session ls" || prefix == "client ls") { std::vector filter_args; cmd_getval(g_ceph_context, cmdmap, "filters", filter_args); @@ -2691,7 +2818,7 @@ bool MDSRankDispatcher::handle_command( f->flush(*ds); delete f; return true; - } else if (prefix == "session evict") { + } else if (prefix == "session evict" || prefix == "client evict") { std::vector filter_args; cmd_getval(g_ceph_context, cmdmap, "filters", filter_args); @@ -2701,7 +2828,7 @@ bool MDSRankDispatcher::handle_command( return true; } - evict_sessions(filter, m); + evict_clients(filter, m); *need_reply = false; return true; diff --git a/ceph/src/mds/MDSRank.h b/ceph/src/mds/MDSRank.h index af46f4c2f..e8ec9dc07 100644 --- a/ceph/src/mds/MDSRank.h +++ b/ceph/src/mds/MDSRank.h @@ -406,6 +406,9 @@ class MDSRank { return map_targets.count(rank); } + bool evict_client(int64_t session_id, bool wait, bool blacklist, + std::stringstream& ss, Context *on_killed=nullptr); + protected: void dump_clientreplay_status(Formatter *f) const; void command_scrub_path(Formatter *f, const string& path, vector& scrubop_vec); @@ -535,7 +538,6 @@ public: Formatter *f, std::ostream& ss); void handle_mds_map(MMDSMap *m, MDSMap *oldmap); void handle_osd_map(); - bool kill_session(int64_t session_id, bool wait, std::stringstream& ss); void update_log_config(); bool handle_command( @@ -547,7 +549,7 @@ public: bool *need_reply); void dump_sessions(const SessionFilter &filter, Formatter *f) const; - void evict_sessions(const SessionFilter &filter, MCommand *m); + void evict_clients(const SessionFilter &filter, MCommand *m); // Call into me from MDS::ms_dispatch bool ms_dispatch(Message *m); diff --git a/ceph/src/mds/Migrator.cc b/ceph/src/mds/Migrator.cc index 67796cf5a..aafd89c28 100644 --- a/ceph/src/mds/Migrator.cc +++ b/ceph/src/mds/Migrator.cc @@ -755,11 +755,11 @@ void Migrator::get_export_lock_set(CDir *dir, set& locks) } -class C_M_ExportTargetWait : public MigratorContext { +class C_M_ExportDirWait : public MigratorContext { MDRequestRef mdr; int count; public: - C_M_ExportTargetWait(Migrator *m, MDRequestRef mdr, int count) + C_M_ExportDirWait(Migrator *m, MDRequestRef mdr, int count) : MigratorContext(m), mdr(mdr), count(count) {} void finish(int r) override { mig->dispatch_export_dir(mdr, count); @@ -781,6 +781,10 @@ void Migrator::export_dir(CDir *dir, mds_rank_t dest) dout(7) << "read-only FS, no exports for now" << dendl; return; } + if (!mds->mdsmap->is_active(dest)) { + dout(7) << "dest not active, no exports for now" << dendl; + return; + } if (mds->is_cluster_degraded()) { dout(7) << "cluster degraded, no exports for now" << dendl; return; @@ -884,13 +888,13 @@ void Migrator::dispatch_export_dir(MDRequestRef& mdr, int count) export_try_cancel(dir); return; } - mds->wait_for_mdsmap(mds->mdsmap->get_epoch(), new C_M_ExportTargetWait(this, mdr, count+1)); + mds->wait_for_mdsmap(mds->mdsmap->get_epoch(), new C_M_ExportDirWait(this, mdr, count+1)); return; } if (!dir->inode->get_parent_dn()) { dout(7) << "waiting for dir to become stable before export: " << *dir << dendl; - dir->add_waiter(CDir::WAIT_CREATED, new C_M_ExportTargetWait(this, mdr, 1)); + dir->add_waiter(CDir::WAIT_CREATED, new C_M_ExportDirWait(this, mdr, 1)); return; } @@ -1498,13 +1502,6 @@ void Migrator::finish_export_inode(CInode *in, utime_t now, mds_rank_t peer, in->finish_export(now); finish_export_inode_caps(in, peer, peer_imported); - - // *** other state too? - - // move to end of LRU so we drop out of cache quickly! - if (in->get_parent_dn()) - cache->lru.lru_bottouch(in->get_parent_dn()); - } uint64_t Migrator::encode_export_dir(bufferlist& exportbl, @@ -1690,17 +1687,13 @@ void Migrator::handle_export_ack(MExportDirAck *m) set bounds; cache->get_subtree_bounds(dir, bounds); - // list us second, them first. - // this keeps authority().first in sync with subtree auth state in the journal. - cache->adjust_subtree_auth(dir, it->second.peer, mds->get_nodeid()); - // log completion. // include export bounds, to ensure they're in the journal. - EExport *le = new EExport(mds->mdlog, dir); + EExport *le = new EExport(mds->mdlog, dir, it->second.peer);; mds->mdlog->start_entry(le); le->metablob.add_dir_context(dir, EMetaBlob::TO_ROOT); - le->metablob.add_dir( dir, false ); + le->metablob.add_dir(dir, false); for (set::iterator p = bounds.begin(); p != bounds.end(); ++p) { @@ -1710,6 +1703,10 @@ void Migrator::handle_export_ack(MExportDirAck *m) le->metablob.add_dir(bound, false); } + // list us second, them first. + // this keeps authority().first in sync with subtree auth state in the journal. + cache->adjust_subtree_auth(dir, it->second.peer, mds->get_nodeid()); + // log export completion, then finish (unfreeze, trigger finish context, etc.) mds->mdlog->submit_entry(le, new C_MDS_ExportFinishLogged(this, dir)); mds->mdlog->flush(); @@ -2165,6 +2162,7 @@ void Migrator::handle_export_prep(MExportDirPrep *m) if (!m->did_assim()) { assert(it != import_state.end()); assert(it->second.state == IMPORT_DISCOVERED); + assert(it->second.peer == oldauth); diri = cache->get_inode(m->get_dirfrag().ino); assert(diri); bufferlist::iterator p = m->basedir.begin(); @@ -2179,6 +2177,7 @@ void Migrator::handle_export_prep(MExportDirPrep *m) return; } assert(it->second.state == IMPORT_PREPPING); + assert(it->second.peer == oldauth); dir = cache->get_dirfrag(m->get_dirfrag()); assert(dir); @@ -2371,27 +2370,29 @@ void Migrator::handle_export_dir(MExportDir *m) assert (g_conf->mds_kill_import_at != 5); CDir *dir = cache->get_dirfrag(m->dirfrag); assert(dir); + + mds_rank_t oldauth = mds_rank_t(m->get_source().num()); + dout(7) << "handle_export_dir importing " << *dir << " from " << oldauth << dendl; + + assert(!dir->is_auth()); map::iterator it = import_state.find(m->dirfrag); assert(it != import_state.end()); assert(it->second.state == IMPORT_PREPPED); assert(it->second.tid == m->get_tid()); + assert(it->second.peer == oldauth); utime_t now = ceph_clock_now(); - mds_rank_t oldauth = mds_rank_t(m->get_source().num()); - dout(7) << "handle_export_dir importing " << *dir << " from " << oldauth << dendl; - assert(dir->is_auth() == false); if (!dir->get_inode()->dirfragtree.is_leaf(dir->get_frag())) dir->get_inode()->dirfragtree.force_to_leaf(g_ceph_context, dir->get_frag()); cache->show_subtrees(); - C_MDS_ImportDirLoggedStart *onlogged = new C_MDS_ImportDirLoggedStart( - this, dir, mds_rank_t(m->get_source().num())); + C_MDS_ImportDirLoggedStart *onlogged = new C_MDS_ImportDirLoggedStart(this, dir, oldauth); // start the journal entry - EImportStart *le = new EImportStart(mds->mdlog, dir->dirfrag(), m->bounds); + EImportStart *le = new EImportStart(mds->mdlog, dir->dirfrag(), m->bounds, oldauth); mds->mdlog->start_entry(le); le->metablob.add_dir_context(dir); diff --git a/ceph/src/mds/PurgeQueue.cc b/ceph/src/mds/PurgeQueue.cc index 2cf61938a..430d3eee8 100644 --- a/ceph/src/mds/PurgeQueue.cc +++ b/ceph/src/mds/PurgeQueue.cc @@ -445,21 +445,12 @@ void PurgeQueue::_execute_item( } assert(gather.has_subs()); - gather.set_finisher(new FunctionContext([this, expire_to](int r){ - if (lock.is_locked_by_me()) { - // Fast completion, Objecter ops completed before we hit gather.activate() - // and we're being called inline. We are still inside _consume so - // no need to call back into it. - _execute_item_complete(expire_to); - } else { - // Normal completion, we're being called back from outside PurgeQueue::lock - // by the Objecter. Take the lock, and call back into _consume to - // find more work. - Mutex::Locker l(lock); - _execute_item_complete(expire_to); + gather.set_finisher(new C_OnFinisher( + new FunctionContext([this, expire_to](int r){ + Mutex::Locker l(lock); + _execute_item_complete(expire_to); - _consume(); - } + _consume(); // Have we gone idle? If so, do an extra write_head now instead of // waiting for next flush after journaler_write_head_interval. @@ -471,7 +462,8 @@ void PurgeQueue::_execute_item( journaler.trim(); })); } - })); + }), &finisher)); + gather.activate(); } @@ -515,7 +507,7 @@ void PurgeQueue::update_op_limit(const MDSMap &mds_map) uint64_t pg_count = 0; objecter->with_osdmap([&](const OSDMap& o) { // Number of PGs across all data pools - const std::set &data_pools = mds_map.get_data_pools(); + const std::vector &data_pools = mds_map.get_data_pools(); for (const auto dp : data_pools) { if (o.get_pg_pool(dp) == NULL) { // It is possible that we have an older OSDMap than MDSMap, diff --git a/ceph/src/mds/RecoveryQueue.cc b/ceph/src/mds/RecoveryQueue.cc index aca08bbff..ed7d1096b 100644 --- a/ceph/src/mds/RecoveryQueue.cc +++ b/ceph/src/mds/RecoveryQueue.cc @@ -20,7 +20,6 @@ #include "RecoveryQueue.h" - #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mds #undef dout_prefix diff --git a/ceph/src/mds/Server.cc b/ceph/src/mds/Server.cc index 500fd3ec6..2b4034006 100644 --- a/ceph/src/mds/Server.cc +++ b/ceph/src/mds/Server.cc @@ -185,6 +185,7 @@ Server::Server(MDSRank *m) : is_full(false), reconnect_done(NULL), failed_reconnects(0), + reconnect_evicting(false), terminating_sessions(false) { } @@ -318,6 +319,7 @@ Session *Server::get_session(Message *m) void Server::handle_client_session(MClientSession *m) { version_t pv; + bool blacklisted = false; Session *session = get_session(m); dout(3) << "handle_client_session " << *m << " from " << m->get_source() << dendl; @@ -346,6 +348,17 @@ void Server::handle_client_session(MClientSession *m) assert(session->is_closed() || session->is_closing()); + blacklisted = mds->objecter->with_osdmap( + [session](const OSDMap &osd_map) -> bool { + return osd_map.is_blacklisted(session->info.inst.addr); + }); + + if (blacklisted) { + dout(10) << "ignoring blacklisted client " << session->info.inst.addr << dendl; + m->put(); + return; + } + session->set_client_metadata(m->client_meta); dout(20) << __func__ << " CEPH_SESSION_REQUEST_OPEN " << session->info.client_metadata.size() << " metadata entries:" << dendl; @@ -442,6 +455,10 @@ void Server::handle_client_session(MClientSession *m) finish_flush_session(session, m->get_seq()); break; + case CEPH_SESSION_REQUEST_FLUSH_MDLOG: + mdlog->flush(); + break; + default: ceph_abort(); } @@ -713,10 +730,16 @@ void Server::find_idle_sessions() return; } - while (1) { - Session *session = mds->sessionmap.get_oldest_session(Session::STATE_STALE); - if (!session) - break; + // Collect a list of sessions exceeding the autoclose threshold + std::vector to_evict; + const auto sessions_p = mds->sessionmap.by_state.find(Session::STATE_STALE); + if (sessions_p == mds->sessionmap.by_state.end() || sessions_p->second->empty()) { + return; + } + const auto &stale_sessions = sessions_p->second; + assert(stale_sessions != nullptr); + + for (const auto &session: *stale_sessions) { if (session->is_importing()) { dout(10) << "stopping at importing session " << session->info.inst << dendl; break; @@ -727,13 +750,25 @@ void Server::find_idle_sessions() << session->last_cap_renew << ")" << dendl; break; } - + + to_evict.push_back(session); + } + + for (const auto &session: to_evict) { utime_t age = now; age -= session->last_cap_renew; - mds->clog->info() << "closing stale session " << session->info.inst - << " after " << age; - dout(10) << "autoclosing stale session " << session->info.inst << " last " << session->last_cap_renew << dendl; - kill_session(session, NULL); + mds->clog->warn() << "evicting unresponsive client " << *session + << ", after " << age << " seconds"; + dout(10) << "autoclosing stale session " << session->info.inst << " last " + << session->last_cap_renew << dendl; + + if (g_conf->mds_session_blacklist_on_timeout) { + std::stringstream ss; + mds->evict_client(session->info.inst.name.num(), false, true, + ss, nullptr); + } else { + kill_session(session, NULL); + } } } @@ -743,6 +778,8 @@ void Server::find_idle_sessions() */ void Server::kill_session(Session *session, Context *on_safe) { + assert(mds->mds_lock.is_locked_by_me()); + if ((session->is_opening() || session->is_open() || session->is_stale()) && @@ -761,6 +798,32 @@ void Server::kill_session(Session *session, Context *on_safe) } } +size_t Server::apply_blacklist(const std::set &blacklist) +{ + std::list victims; + const auto sessions = mds->sessionmap.get_sessions(); + for (const auto p : sessions) { + if (!p.first.is_client()) { + // Do not apply OSDMap blacklist to MDS daemons, we find out + // about their death via MDSMap. + continue; + } + + Session *s = p.second; + if (blacklist.count(s->info.inst.addr)) { + victims.push_back(s); + } + } + + for (const auto s : victims) { + kill_session(s, nullptr); + } + + dout(10) << "apply_blacklist: killed " << victims.size() << dendl; + + return victims.size(); +} + void Server::journal_close_session(Session *session, int state, Context *on_safe) { uint64_t sseq = mds->sessionmap.set_state(session, state); @@ -942,22 +1005,53 @@ void Server::reconnect_gather_finish() void Server::reconnect_tick() { + if (reconnect_evicting) { + dout(4) << "reconnect_tick: waiting for evictions" << dendl; + return; + } + utime_t reconnect_end = reconnect_start; reconnect_end += g_conf->mds_reconnect_timeout; if (ceph_clock_now() >= reconnect_end && !client_reconnect_gather.empty()) { dout(10) << "reconnect timed out" << dendl; + + // If we're doing blacklist evictions, use this to wait for them before + // proceeding to reconnect_gather_finish + MDSGatherBuilder gather(g_ceph_context); + for (set::iterator p = client_reconnect_gather.begin(); p != client_reconnect_gather.end(); ++p) { Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p->v)); assert(session); dout(1) << "reconnect gave up on " << session->info.inst << dendl; - kill_session(session, NULL); + + mds->clog->warn() << "evicting unresponsive client " << *session + << ", after waiting " << g_conf->mds_reconnect_timeout + << " seconds during MDS startup"; + + if (g_conf->mds_session_blacklist_on_timeout) { + std::stringstream ss; + mds->evict_client(session->info.inst.name.num(), false, true, ss, + gather.new_sub()); + } else { + kill_session(session, NULL); + } + failed_reconnects++; } client_reconnect_gather.clear(); - reconnect_gather_finish(); + + if (gather.has_subs()) { + dout(1) << "reconnect will complete once clients are evicted" << dendl; + gather.set_finisher(new MDSInternalContextWrapper(mds, new FunctionContext( + [this](int r){reconnect_gather_finish();}))); + gather.activate(); + reconnect_evicting = true; + } else { + reconnect_gather_finish(); + } } } @@ -5230,7 +5324,9 @@ void Server::_link_local_finish(MDRequestRef& mdr, CDentry *dn, CInode *targeti, dout(10) << "_link_local_finish " << *dn << " to " << *targeti << dendl; // link and unlock the NEW dentry - dn->pop_projected_linkage(); + CDentry::linkage_t *dnl = dn->pop_projected_linkage(); + if (!dnl->get_inode()) + dn->link_remote(dnl, targeti); dn->mark_dirty(dnpv, mdr->ls); // target inode @@ -5327,6 +5423,7 @@ void Server::_link_remote(MDRequestRef& mdr, bool inc, CDentry *dn, CInode *targ mdcache->predirty_journal_parents(mdr, &le->metablob, targeti, dn->get_dir(), PREDIRTY_DIR, -1); mdcache->journal_cow_dentry(mdr.get(), &le->metablob, dn); le->metablob.add_null_dentry(dn, true); + dn->push_projected_linkage(); } journal_and_reply(mdr, targeti, dn, le, new C_MDS_link_remote_finish(this, mdr, inc, dn, targeti)); @@ -5347,11 +5444,14 @@ void Server::_link_remote_finish(MDRequestRef& mdr, bool inc, if (inc) { // link the new dentry - dn->pop_projected_linkage(); + CDentry::linkage_t *dnl = dn->pop_projected_linkage(); + if (!dnl->get_inode()) + dn->link_remote(dnl, targeti); dn->mark_dirty(dpv, mdr->ls); } else { // unlink main dentry dn->get_dir()->unlink_inode(dn); + dn->pop_projected_linkage(); dn->mark_dirty(dn->get_projected_version(), mdr->ls); // dirty old dentry } @@ -5856,7 +5956,7 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn) dn->pre_dirty(); inode_t *pi = in->project_inode(); - dn->make_path_string(pi->stray_prior_path); + dn->make_path_string(pi->stray_prior_path, true); mdr->add_projected_inode(in); // do this _after_ my dn->pre_dirty().. we apply that one manually. pi->version = in->pre_dirty(); pi->ctime = mdr->get_op_stamp(); @@ -5994,10 +6094,11 @@ struct C_MDS_SlaveRmdirPrep : public ServerLogContext { struct C_MDS_SlaveRmdirCommit : public ServerContext { MDRequestRef mdr; - C_MDS_SlaveRmdirCommit(Server *s, MDRequestRef& r) - : ServerContext(s), mdr(r) { } + CDentry *straydn; + C_MDS_SlaveRmdirCommit(Server *s, MDRequestRef& r, CDentry *sd) + : ServerContext(s), mdr(r), straydn(sd) { } void finish(int r) override { - server->_commit_slave_rmdir(mdr, r); + server->_commit_slave_rmdir(mdr, r, straydn); } }; @@ -6040,7 +6141,7 @@ void Server::handle_slave_rmdir_prep(MDRequestRef& mdr) dout(20) << " rollback is " << mdr->more()->rollback_bl.length() << " bytes" << dendl; // set up commit waiter - mdr->more()->slave_commit = new C_MDS_SlaveRmdirCommit(this, mdr); + mdr->more()->slave_commit = new C_MDS_SlaveRmdirCommit(this, mdr, straydn); if (!in->has_subtree_root_dirfrag(mds->get_nodeid())) { dout(10) << " no auth subtree in " << *in << ", skipping journal" << dendl; @@ -6141,11 +6242,17 @@ void Server::handle_slave_rmdir_prep_ack(MDRequestRef& mdr, MMDSSlaveRequest *ac dout(10) << "still waiting on slaves " << mdr->more()->waiting_on_slave << dendl; } -void Server::_commit_slave_rmdir(MDRequestRef& mdr, int r) +void Server::_commit_slave_rmdir(MDRequestRef& mdr, int r, CDentry *straydn) { dout(10) << "_commit_slave_rmdir " << *mdr << " r=" << r << dendl; if (r == 0) { + if (mdr->more()->slave_update_journaled) { + CInode *strayin = straydn->get_projected_linkage()->get_inode(); + if (strayin && !strayin->snaprealm) + mdcache->clear_dirty_bits_for_stray(strayin); + } + mdr->cleanup(); if (mdr->more()->slave_update_journaled) { @@ -6821,6 +6928,8 @@ bool Server::_rename_prepare_witness(MDRequestRef& mdr, mds_rank_t who, setdestdnpath.push_dentry(dn->name); if (straydn) mdcache->replicate_stray(straydn, who, req->stray); + + req->srcdn_auth = mdr->more()->srcdn_auth_mds; // srcdn auth will verify our current witness list is sufficient req->witnesses = witnesse; @@ -7037,7 +7146,7 @@ void Server::_rename_prepare(MDRequestRef& mdr, if (tpi) { tpi->ctime = mdr->get_op_stamp(); tpi->change_attr++; - destdn->make_path_string(tpi->stray_prior_path); + destdn->make_path_string(tpi->stray_prior_path, true); tpi->nlink--; if (tpi->nlink == 0) oldin->state_set(CInode::STATE_ORPHAN); @@ -7204,7 +7313,7 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C if (destdnl->is_primary()) { assert(straydn); dout(10) << "straydn is " << *straydn << dendl; - destdn->get_dir()->unlink_inode(destdn); + destdn->get_dir()->unlink_inode(destdn, false); straydn->pop_projected_linkage(); if (mdr->is_slave() && !mdr->more()->slave_update_journaled) @@ -7223,7 +7332,7 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C //oldin->open_snaprealm(); might be sufficient.. } } else if (destdnl->is_remote()) { - destdn->get_dir()->unlink_inode(destdn); + destdn->get_dir()->unlink_inode(destdn, false); if (oldin->is_auth()) oldin->pop_and_dirty_projected_inode(mdr->ls); } @@ -7257,7 +7366,7 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C } else { // primary if (linkmerge) { dout(10) << "merging primary onto remote link" << dendl; - destdn->get_dir()->unlink_inode(destdn); + destdn->get_dir()->unlink_inode(destdn, false); } destdnl = destdn->pop_projected_linkage(); if (mdr->is_slave() && !mdr->more()->slave_update_journaled) @@ -7371,7 +7480,17 @@ void Server::handle_slave_rename_prep(MDRequestRef& mdr) << " " << mdr->slave_request->srcdnpath << " to " << mdr->slave_request->destdnpath << dendl; - + + if (mdr->slave_request->is_interrupted()) { + dout(10) << " slave request interrupted, sending noop reply" << dendl; + MMDSSlaveRequest *reply= new MMDSSlaveRequest(mdr->reqid, mdr->attempt, MMDSSlaveRequest::OP_RENAMEPREPACK); + reply->mark_interrupted(); + mds->send_message_mds(reply, mdr->slave_to_mds); + mdr->slave_request->put(); + mdr->slave_request = 0; + return; + } + // discover destdn filepath destpath(mdr->slave_request->destdnpath); dout(10) << " dest " << destpath << dendl; @@ -7701,6 +7820,11 @@ void Server::_commit_slave_rename(MDRequestRef& mdr, int r, mdr->more()->is_ambiguous_auth = false; } + if (straydn && mdr->more()->slave_update_journaled) { + CInode *strayin = straydn->get_projected_linkage()->get_inode(); + if (strayin && !strayin->snaprealm) + mdcache->clear_dirty_bits_for_stray(strayin); + } mds->queue_waiters(finished); mdr->cleanup(); @@ -8129,7 +8253,9 @@ void Server::handle_slave_rename_prep_ack(MDRequestRef& mdr, MMDSSlaveRequest *a // witnessed? or add extra witnesses? assert(mdr->more()->witnessed.count(from) == 0); - if (ack->witnesses.empty()) { + if (ack->is_interrupted()) { + dout(10) << " slave request interrupted, noop" << dendl; + } else if (ack->witnesses.empty()) { mdr->more()->witnessed.insert(from); if (!ack->is_not_journaled()) mdr->more()->has_journaled_slaves = true; diff --git a/ceph/src/mds/Server.h b/ceph/src/mds/Server.h index 7d1aaeab7..2f554f26a 100644 --- a/ceph/src/mds/Server.h +++ b/ceph/src/mds/Server.h @@ -80,6 +80,8 @@ private: // State for while in reconnect MDSInternalContext *reconnect_done; int failed_reconnects; + bool reconnect_evicting; // true if I am waiting for evictions to complete + // before proceeding to reconnect_gather_finish friend class MDSContinuation; friend class ServerContext; @@ -122,6 +124,7 @@ public: void terminate_sessions(); void find_idle_sessions(); void kill_session(Session *session, Context *on_safe); + size_t apply_blacklist(const std::set &blacklist); void journal_close_session(Session *session, int state, Context *on_safe); void reconnect_clients(MDSInternalContext *reconnect_done_); void handle_client_reconnect(class MClientReconnect *m); @@ -260,7 +263,7 @@ public: bool _rmdir_prepare_witness(MDRequestRef& mdr, mds_rank_t who, vector& trace, CDentry *straydn); void handle_slave_rmdir_prep(MDRequestRef& mdr); void _logged_slave_rmdir(MDRequestRef& mdr, CDentry *srcdn, CDentry *straydn); - void _commit_slave_rmdir(MDRequestRef& mdr, int r); + void _commit_slave_rmdir(MDRequestRef& mdr, int r, CDentry *straydn); void handle_slave_rmdir_prep_ack(MDRequestRef& mdr, MMDSSlaveRequest *ack); void do_rmdir_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef& mdr); void _rmdir_rollback_finish(MDRequestRef& mdr, metareqid_t reqid, CDentry *dn, CDentry *straydn); diff --git a/ceph/src/mds/SessionMap.cc b/ceph/src/mds/SessionMap.cc index a1ba0db4d..561f2db9e 100644 --- a/ceph/src/mds/SessionMap.cc +++ b/ceph/src/mds/SessionMap.cc @@ -628,6 +628,9 @@ void SessionMap::touch_session(Session *session) void SessionMap::_mark_dirty(Session *s) { + if (dirty_sessions.count(s->info.inst.name)) + return; + if (dirty_sessions.size() >= g_conf->mds_sessionmap_keys_per_op) { // Pre-empt the usual save() call from journal segment trim, in // order to avoid building up an oversized OMAP update operation @@ -635,6 +638,7 @@ void SessionMap::_mark_dirty(Session *s) save(new C_MDSInternalNoop, version); } + null_sessions.erase(s->info.inst.name); dirty_sessions.insert(s->info.inst.name); } diff --git a/ceph/src/mds/SnapServer.cc b/ceph/src/mds/SnapServer.cc index 4518abef6..ea78bff1d 100644 --- a/ceph/src/mds/SnapServer.cc +++ b/ceph/src/mds/SnapServer.cc @@ -166,11 +166,9 @@ bool SnapServer::_commit(version_t tid, MMDSTableRequest *req) dout(7) << "commit " << tid << " destroy " << sn << " seq " << seq << dendl; snaps.erase(sn); - for (set::const_iterator p = mds->mdsmap->get_data_pools().begin(); - p != mds->mdsmap->get_data_pools().end(); - ++p) { - need_to_purge[*p].insert(sn); - need_to_purge[*p].insert(seq); + for (const auto p : mds->mdsmap->get_data_pools()) { + need_to_purge[p].insert(sn); + need_to_purge[p].insert(seq); } pending_destroy.erase(tid); diff --git a/ceph/src/mds/StrayManager.cc b/ceph/src/mds/StrayManager.cc index f4d3ac4ef..25c247744 100644 --- a/ceph/src/mds/StrayManager.cc +++ b/ceph/src/mds/StrayManager.cc @@ -237,9 +237,11 @@ void StrayManager::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *l assert(!in->state_test(CInode::STATE_RECOVERING)); + bool new_dn = dn->is_new(); + // unlink assert(dn->get_projected_linkage()->is_null()); - dn->dir->unlink_inode(dn); + dn->dir->unlink_inode(dn, !new_dn); dn->pop_projected_linkage(); dn->mark_dirty(pdv, ls); @@ -250,12 +252,10 @@ void StrayManager::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *l dn->put(CDentry::PIN_PURGING); // drop dentry? - if (dn->is_new()) { + if (new_dn) { dout(20) << " dn is new, removing" << dendl; dn->mark_clean(); dn->dir->remove_dentry(dn); - } else { - in->mdcache->touch_dentry_bottom(dn); // drop dn as quickly as possible. } // drop inode @@ -431,10 +431,6 @@ bool StrayManager::_eval_stray(CDentry *dn, bool delay) assert(!dn->state_test(CDentry::STATE_PURGING)); if (!dn->is_auth()) { - // has to be mine - // move to bottom of lru so that we trim quickly! - - in->mdcache->touch_dentry_bottom(dn); return false; } @@ -472,13 +468,7 @@ bool StrayManager::_eval_stray(CDentry *dn, bool delay) return false; // not until some snaps are deleted. } - if (in->has_dirfrags()) { - list ls; - in->get_nested_dirfrags(ls); - for (list::iterator p = ls.begin(); p != ls.end(); ++p) { - (*p)->try_remove_dentries_for_stray(); - } - } + in->mdcache->clear_dirty_bits_for_stray(in); if (!in->remote_parents.empty()) { // unlink any stale remote snap dentry. @@ -545,7 +535,7 @@ bool StrayManager::_eval_stray(CDentry *dn, bool delay) * if we can do anything with them if we happen to have them in * cache. */ - eval_remote_stray(dn, NULL); + _eval_stray_remote(dn, NULL); return false; } } @@ -568,8 +558,51 @@ bool StrayManager::eval_stray(CDentry *dn, bool delay) return ret; } -void StrayManager::eval_remote_stray(CDentry *stray_dn, CDentry *remote_dn) +void StrayManager::eval_remote(CDentry *remote_dn) { + dout(10) << __func__ << " " << *remote_dn << dendl; + + CDentry::linkage_t *dnl = remote_dn->get_projected_linkage(); + assert(dnl->is_remote()); + CInode *in = dnl->get_inode(); + + if (!in) { + dout(20) << __func__ << ": no inode, cannot evaluate" << dendl; + return; + } + + if (remote_dn->last != CEPH_NOSNAP) { + dout(20) << __func__ << ": snap dentry, cannot evaluate" << dendl; + return; + } + + // refers to stray? + CDentry *primary_dn = in->get_projected_parent_dn(); + assert(primary_dn != NULL); + if (primary_dn->get_dir()->get_inode()->is_stray()) { + _eval_stray_remote(primary_dn, remote_dn); + } else { + dout(20) << __func__ << ": inode's primary dn not stray" << dendl; + } +} + +class C_RetryEvalRemote : public StrayManagerContext { + CDentry *dn; + public: + C_RetryEvalRemote(StrayManager *sm_, CDentry *dn_) : + StrayManagerContext(sm_), dn(dn_) { + dn->get(CDentry::PIN_PTRWAITER); + } + void finish(int r) override { + if (dn->get_projected_linkage()->is_remote()) + sm->eval_remote(dn); + dn->put(CDentry::PIN_PTRWAITER); + } +}; + +void StrayManager::_eval_stray_remote(CDentry *stray_dn, CDentry *remote_dn) +{ + dout(20) << __func__ << " " << *stray_dn << dendl; assert(stray_dn != NULL); assert(stray_dn->get_dir()->get_inode()->is_stray()); CDentry::linkage_t *stray_dnl = stray_dn->get_projected_linkage(); @@ -584,9 +617,14 @@ void StrayManager::eval_remote_stray(CDentry *stray_dn, CDentry *remote_dn) for (compact_set::iterator p = stray_in->remote_parents.begin(); p != stray_in->remote_parents.end(); ++p) - if ((*p)->last == CEPH_NOSNAP) { - remote_dn = *p; - break; + if ((*p)->last == CEPH_NOSNAP && !(*p)->is_projected()) { + if ((*p)->is_auth()) { + remote_dn = *p; + if (remote_dn->dir->can_auth_pin()) + break; + } else if (!remote_dn) { + remote_dn = *p; + } } } if (!remote_dn) { @@ -597,8 +635,14 @@ void StrayManager::eval_remote_stray(CDentry *stray_dn, CDentry *remote_dn) assert(remote_dn->last == CEPH_NOSNAP); // NOTE: we repeat this check in _rename(), since our submission path is racey. if (!remote_dn->is_projected()) { - if (remote_dn->is_auth() && remote_dn->dir->can_auth_pin()) { - reintegrate_stray(stray_dn, remote_dn); + if (remote_dn->is_auth()) { + if (remote_dn->dir->can_auth_pin()) { + reintegrate_stray(stray_dn, remote_dn); + } else { + remote_dn->dir->add_waiter(CDir::WAIT_UNFREEZE, new C_RetryEvalRemote(this, remote_dn)); + dout(20) << __func__ << ": not reintegrating (can't authpin remote parent)" << dendl; + } + } else if (!remote_dn->is_auth() && stray_dn->is_auth()) { migrate_stray(stray_dn, remote_dn->authority().first); } else { diff --git a/ceph/src/mds/StrayManager.h b/ceph/src/mds/StrayManager.h index a9bf3aa78..54629ee04 100644 --- a/ceph/src/mds/StrayManager.h +++ b/ceph/src/mds/StrayManager.h @@ -119,6 +119,8 @@ class StrayManager */ bool _eval_stray(CDentry *dn, bool delay=false); + void _eval_stray_remote(CDentry *stray_dn, CDentry *remote_dn); + // My public interface is for consumption by MDCache public: explicit StrayManager(MDSRank *mds, PurgeQueue &purge_queue_); @@ -144,11 +146,10 @@ class StrayManager void advance_delayed(); /** - * When a metadata op touches a remote dentry that points to - * a stray, call in here to evaluate it for migration (move - * a stray residing on another MDS to this MDS) or reintegration - * (move a stray dentry's inode into a non-stray hardlink dentry and - * clean up the stray). + * Remote dentry potentially points to a stray. When it is touched, + * call in here to evaluate it for migration (move a stray residing + * on another MDS to this MDS) or reintegration (move a stray dentry's + * inode into a non-stray hardlink dentry and clean up the stray). * * @param stray_dn a stray dentry whose inode has been referenced * by a remote dentry @@ -157,7 +158,7 @@ class StrayManager * as a hint for which remote to reintegrate into * if there are multiple remotes. */ - void eval_remote_stray(CDentry *stray_dn, CDentry *remote_dn=NULL); + void eval_remote(CDentry *remote_dn); /** * Given a dentry within one of my stray directories, diff --git a/ceph/src/mds/events/EExport.h b/ceph/src/mds/events/EExport.h index 602124012..9c53c447a 100644 --- a/ceph/src/mds/events/EExport.h +++ b/ceph/src/mds/events/EExport.h @@ -29,17 +29,19 @@ public: protected: dirfrag_t base; set bounds; + mds_rank_t target; public: - EExport() : LogEvent(EVENT_EXPORT) { } - EExport(MDLog *mdlog, CDir *dir) : + EExport() : + LogEvent(EVENT_EXPORT), target(MDS_RANK_NONE) { } + EExport(MDLog *mdlog, CDir *dir, mds_rank_t t) : LogEvent(EVENT_EXPORT), metablob(mdlog), - base(dir->dirfrag()) { } + base(dir->dirfrag()), target(t) { } set &get_bounds() { return bounds; } void print(ostream& out) const override { - out << "EExport " << base << " " << metablob; + out << "EExport " << base << " to mds." << target << " " << metablob; } EMetaBlob *get_metablob() override { return &metablob; } diff --git a/ceph/src/mds/events/EImportStart.h b/ceph/src/mds/events/EImportStart.h index 36f07b451..9d446b629 100644 --- a/ceph/src/mds/events/EImportStart.h +++ b/ceph/src/mds/events/EImportStart.h @@ -28,21 +28,21 @@ class EImportStart : public LogEvent { protected: dirfrag_t base; vector bounds; + mds_rank_t from; - public: +public: EMetaBlob metablob; bufferlist client_map; // encoded map<__u32,entity_inst_t> version_t cmapv; - EImportStart(MDLog *log, - dirfrag_t di, - vector& b) : LogEvent(EVENT_IMPORTSTART), - base(di), bounds(b), - metablob(log) { } - EImportStart() : LogEvent(EVENT_IMPORTSTART) { } + EImportStart(MDLog *log, dirfrag_t di, vector& b, mds_rank_t f) : + LogEvent(EVENT_IMPORTSTART), + base(di), bounds(b), from(f), metablob(log) { } + EImportStart() : + LogEvent(EVENT_IMPORTSTART), from(MDS_RANK_NONE) { } void print(ostream& out) const override { - out << "EImportStart " << base << " " << metablob; + out << "EImportStart " << base << " from mds." << from << " " << metablob; } EMetaBlob *get_metablob() override { return &metablob; } diff --git a/ceph/src/mds/flock.cc b/ceph/src/mds/flock.cc index 73c918013..2382322bc 100644 --- a/ceph/src/mds/flock.cc +++ b/ceph/src/mds/flock.cc @@ -10,20 +10,25 @@ static multimap global_waiting_locks; +static void remove_global_waiting(ceph_filelock &fl, ceph_lock_state_t *lock_state) +{ + for (auto p = global_waiting_locks.find(fl); + p != global_waiting_locks.end(); ) { + if (p->first != fl) + break; + if (p->second == lock_state) { + global_waiting_locks.erase(p); + break; + } + ++p; + } +} + ceph_lock_state_t::~ceph_lock_state_t() { if (type == CEPH_LOCK_FCNTL) { for (auto p = waiting_locks.begin(); p != waiting_locks.end(); ++p) { - for (auto q = global_waiting_locks.find(p->second); - q != global_waiting_locks.end(); ) { - if (q->first != p->second) - break; - if (q->second == this) { - global_waiting_locks.erase(q); - break; - } - ++q; - } + remove_global_waiting(p->second, this); } } } @@ -50,6 +55,9 @@ void ceph_lock_state_t::remove_waiting(const ceph_filelock& fl) break; if (p->second.length == fl.length && ceph_filelock_owner_equal(p->second, fl)) { + if (type == CEPH_LOCK_FCNTL) { + remove_global_waiting(p->second, this); + } waiting_locks.erase(p); --client_waiting_lock_counts[(client_t)fl.client]; if (!client_waiting_lock_counts[(client_t)fl.client]) { @@ -59,19 +67,6 @@ void ceph_lock_state_t::remove_waiting(const ceph_filelock& fl) } ++p; } - - if (type == CEPH_LOCK_FCNTL) { - for (auto q = global_waiting_locks.find(fl); - q != global_waiting_locks.end(); ) { - if (q->first != fl) - break; - if (q->second == this) { - global_waiting_locks.erase(q); - break; - } - ++q; - } - } } bool ceph_lock_state_t::is_deadlock(const ceph_filelock& fl, @@ -141,6 +136,7 @@ bool ceph_lock_state_t::is_deadlock(const ceph_filelock& fl, void ceph_lock_state_t::add_waiting(const ceph_filelock& fl) { waiting_locks.insert(pair(fl.start, fl)); + ++client_waiting_lock_counts[(client_t)fl.client]; if (type == CEPH_LOCK_FCNTL) { global_waiting_locks.insert(pair(fl, this)); } @@ -200,8 +196,6 @@ bool ceph_lock_state_t::add_lock(ceph_filelock& new_lock, if (ret) { ++client_held_lock_counts[(client_t)new_lock.client]; } - else if (wait_on_fail && !replay) - ++client_waiting_lock_counts[(client_t)new_lock.client]; return ret; } @@ -320,16 +314,8 @@ bool ceph_lock_state_t::remove_all_from (client_t client) ++iter; continue; } - - for (auto p = global_waiting_locks.find(iter->second); - p != global_waiting_locks.end(); ) { - if (p->first != iter->second) - break; - if (p->second == this) { - global_waiting_locks.erase(p); - break; - } - ++p; + if (type == CEPH_LOCK_FCNTL) { + remove_global_waiting(iter->second, this); } waiting_locks.erase(iter++); } diff --git a/ceph/src/mds/flock.h b/ceph/src/mds/flock.h index cceb78e7a..142e4d127 100644 --- a/ceph/src/mds/flock.h +++ b/ceph/src/mds/flock.h @@ -252,21 +252,11 @@ private: public: void encode(bufferlist& bl) const { ::encode(held_locks, bl); - ::encode(waiting_locks, bl); ::encode(client_held_lock_counts, bl); - ::encode(client_waiting_lock_counts, bl); } void decode(bufferlist::iterator& bl) { ::decode(held_locks, bl); - ::decode(waiting_locks, bl); ::decode(client_held_lock_counts, bl); - ::decode(client_waiting_lock_counts, bl); - } - void clear() { - held_locks.clear(); - waiting_locks.clear(); - client_held_lock_counts.clear(); - client_waiting_lock_counts.clear(); } bool empty() const { return held_locks.empty() && waiting_locks.empty() && diff --git a/ceph/src/mds/journal.cc b/ceph/src/mds/journal.cc index a28491547..5d8088234 100644 --- a/ceph/src/mds/journal.cc +++ b/ceph/src/mds/journal.cc @@ -329,13 +329,20 @@ void EMetaBlob::add_dir_context(CDir *dir, int mode) if (mode == TO_AUTH_SUBTREE_ROOT) { // subtree root? - if (dir->is_subtree_root() && - !dir->state_test(CDir::STATE_EXPORTBOUND)) { - if (dir->is_auth() && !dir->is_ambiguous_auth() ) { - if (dir->state_test(CDir::STATE_AUXSUBTREE) && - dir->get_dir_auth().first == diri->authority().first) { - // auxiliary subtree. treat it as normal dirfrag - dout(20) << "EMetaBlob::add_dir_context(" << dir << ") auxiliary subtree " << dendl; + if (dir->is_subtree_root()) { + // match logic in MDCache::create_subtree_map() + if (dir->get_dir_auth().first == mds->get_nodeid()) { + mds_authority_t parent_auth = parent ? parent->authority() : CDIR_AUTH_UNDEF; + if (parent_auth.first == dir->get_dir_auth().first) { + if (parent_auth.second == CDIR_AUTH_UNKNOWN && + !dir->is_ambiguous_dir_auth() && + !dir->state_test(CDir::STATE_EXPORTBOUND) && + !dir->state_test(CDir::STATE_AUXSUBTREE) && + !diri->state_test(CInode::STATE_AMBIGUOUSAUTH)) { + dout(0) << "EMetaBlob::add_dir_context unexpected subtree " << *dir << dendl; + assert(0); + } + dout(20) << "EMetaBlob::add_dir_context(" << dir << ") ambiguous or transient subtree " << dendl; } else { // it's an auth subtree, we don't need maybe (if any), and we're done. dout(20) << "EMetaBlob::add_dir_context(" << dir << ") reached unambig auth subtree, don't need " << maybe @@ -351,7 +358,7 @@ void EMetaBlob::add_dir_context(CDir *dir, int mode) maybenot = false; } } - + // was the inode journaled in this blob? if (event_seq && diri->last_journaled == event_seq) { dout(20) << "EMetaBlob::add_dir_context(" << dir << ") already have diri this blob " << *diri << dendl; @@ -549,6 +556,7 @@ void EMetaBlob::fullbit::update_inode(MDSRank *mds, CInode *in) { in->inode = inode; in->xattrs = xattrs; + in->maybe_export_pin(); if (in->inode.is_dir()) { if (!(in->dirfragtree == dirfragtree)) { dout(10) << "EMetaBlob::fullbit::update_inode dft " << in->dirfragtree << " -> " @@ -1305,8 +1313,7 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) dout(0) << ss.str() << dendl; mds->clog->warn(ss); } - dir->unlink_inode(dn); - mds->mdcache->touch_dentry_bottom(dn); + dir->unlink_inode(dn, false); } if (unlinked.count(in)) linked.insert(in); @@ -1318,9 +1325,7 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) if (dn->get_linkage()->get_inode() != in && in->get_parent_dn()) { dout(10) << "EMetaBlob.replay unlinking " << *in << dendl; unlinked[in] = in->get_parent_dir(); - CDentry *unlinked_dn = in->get_parent_dn(); in->get_parent_dir()->unlink_inode(in->get_parent_dn()); - mds->mdcache->touch_dentry_bottom(unlinked_dn); } if (dn->get_linkage()->get_inode() != in) { if (!dn->get_linkage()->is_null()) { // note: might be remote. as with stray reintegration. @@ -1332,8 +1337,7 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) dout(0) << ss.str() << dendl; mds->clog->warn(ss); } - dir->unlink_inode(dn); - mds->mdcache->touch_dentry_bottom(dn); + dir->unlink_inode(dn, false); } if (unlinked.count(in)) linked.insert(in); @@ -1378,8 +1382,7 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) << " " << *dn->get_linkage()->get_inode() << " should be remote " << p->ino; dout(0) << ss.str() << dendl; } - dir->unlink_inode(dn); - mds->mdcache->touch_dentry_bottom(dn); + dir->unlink_inode(dn, false); } dir->link_remote_inode(dn, p->ino, p->d_type); dn->set_version(p->dnv); @@ -1414,7 +1417,6 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) if (dn->get_linkage()->is_primary()) unlinked[in] = dir; dir->unlink_inode(dn); - mds->mdcache->touch_dentry_bottom(dn); } } dn->set_version(p->dnv); @@ -1428,7 +1430,6 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) // Make null dentries the first things we trim dout(10) << "EMetaBlob.replay pushing to bottom of lru " << *dn << dendl; - mds->mdcache->touch_dentry_bottom(dn); } } @@ -1637,7 +1638,6 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup) if (parent) { dout(10) << "EMetaBlob.replay unlinked from dentry " << *parent << dendl; assert(parent->get_linkage()->is_null()); - mds->mdcache->touch_dentry_bottom(parent); } } else { dout(10) << "EMetaBlob.replay destroyed " << *p << ", not in cache" << dendl; @@ -2874,11 +2874,12 @@ void EExport::replay(MDSRank *mds) void EExport::encode(bufferlist& bl, uint64_t features) const { - ENCODE_START(3, 3, bl); + ENCODE_START(4, 3, bl); ::encode(stamp, bl); ::encode(metablob, bl, features); ::encode(base, bl); ::encode(bounds, bl); + ::encode(target, bl); ENCODE_FINISH(bl); } @@ -2890,6 +2891,8 @@ void EExport::decode(bufferlist::iterator &bl) ::decode(metablob, bl); ::decode(base, bl); ::decode(bounds, bl); + if (struct_v >= 4) + ::decode(target, bl); DECODE_FINISH(bl); } @@ -2968,13 +2971,14 @@ void EImportStart::replay(MDSRank *mds) } void EImportStart::encode(bufferlist &bl, uint64_t features) const { - ENCODE_START(3, 3, bl); + ENCODE_START(4, 3, bl); ::encode(stamp, bl); ::encode(base, bl); ::encode(metablob, bl, features); ::encode(bounds, bl); ::encode(cmapv, bl); ::encode(client_map, bl); + ::encode(from, bl); ENCODE_FINISH(bl); } @@ -2987,6 +2991,8 @@ void EImportStart::decode(bufferlist::iterator &bl) { ::decode(bounds, bl); ::decode(cmapv, bl); ::decode(client_map, bl); + if (struct_v >= 4) + ::decode(from, bl); DECODE_FINISH(bl); } diff --git a/ceph/src/messages/MClientCaps.h b/ceph/src/messages/MClientCaps.h index 1db9bd16b..e973b6341 100644 --- a/ceph/src/messages/MClientCaps.h +++ b/ceph/src/messages/MClientCaps.h @@ -288,6 +288,7 @@ public: ::encode(head, payload); ceph_mds_caps_body_legacy body; if (head.op == CEPH_CAP_OP_EXPORT) { + memset(&body, 0, sizeof(body)); body.peer = peer; } else { body.size = size; diff --git a/ceph/src/messages/MClientReply.h b/ceph/src/messages/MClientReply.h index dc7e7e342..228db2f9d 100644 --- a/ceph/src/messages/MClientReply.h +++ b/ceph/src/messages/MClientReply.h @@ -214,7 +214,7 @@ public: epoch_t get_mdsmap_epoch() const { return head.mdsmap_epoch; } int get_result() const { - return ceph_to_host_errno((__s32)(__u32)head.result); + return ceph_to_hostos_errno((__s32)(__u32)head.result); } void set_result(int r) { head.result = r; } diff --git a/ceph/src/messages/MMDSResolve.h b/ceph/src/messages/MMDSResolve.h index 6e9f02852..baf581b4b 100644 --- a/ceph/src/messages/MMDSResolve.h +++ b/ceph/src/messages/MMDSResolve.h @@ -86,7 +86,7 @@ public: } }; -inline ostream& operator<<(ostream& out, const MMDSResolve::slave_request) { +inline ostream& operator<<(ostream& out, const MMDSResolve::slave_request&) { return out; } diff --git a/ceph/src/messages/MMDSSlaveRequest.h b/ceph/src/messages/MMDSSlaveRequest.h index 5512c5a07..9e7510c9a 100644 --- a/ceph/src/messages/MMDSSlaveRequest.h +++ b/ceph/src/messages/MMDSSlaveRequest.h @@ -101,6 +101,7 @@ class MMDSSlaveRequest : public Message { static const unsigned FLAG_NOTJOURNALED = 1<<2; static const unsigned FLAG_EROFS = 1<<3; static const unsigned FLAG_ABORT = 1<<4; + static const unsigned FLAG_INTERRUPTED = 1<<5; // for locking __u16 lock_type; // lock object type @@ -117,6 +118,7 @@ class MMDSSlaveRequest : public Message { bufferlist inode_export; version_t inode_export_v; bufferlist srci_replica; + mds_rank_t srcdn_auth; utime_t op_stamp; bufferlist stray; // stray dir + dentry @@ -142,6 +144,8 @@ public: bool is_error_rofs() { return (flags & FLAG_EROFS); } bool is_abort() { return (flags & FLAG_ABORT); } void mark_abort() { flags |= FLAG_ABORT; } + bool is_interrupted() { return (flags & FLAG_INTERRUPTED); } + void mark_interrupted() { flags |= FLAG_INTERRUPTED; } void set_lock_type(int t) { lock_type = t; } @@ -151,7 +155,7 @@ public: MMDSSlaveRequest(metareqid_t ri, __u32 att, int o) : Message(MSG_MDS_SLAVE_REQUEST), reqid(ri), attempt(att), op(o), flags(0), lock_type(0), - inode_export_v(0) { } + inode_export_v(0), srcdn_auth(MDS_RANK_NONE) { } private: ~MMDSSlaveRequest() override {} @@ -170,6 +174,7 @@ public: ::encode(op_stamp, payload); ::encode(inode_export, payload); ::encode(inode_export_v, payload); + ::encode(srcdn_auth, payload); ::encode(srci_replica, payload); ::encode(stray, payload); } @@ -188,6 +193,7 @@ public: ::decode(op_stamp, p); ::decode(inode_export, p); ::decode(inode_export_v, p); + ::decode(srcdn_auth, p); ::decode(srci_replica, p); ::decode(stray, p); } diff --git a/ceph/src/messages/MMonMgrReport.h b/ceph/src/messages/MMonMgrReport.h new file mode 100644 index 000000000..bf91519eb --- /dev/null +++ b/ceph/src/messages/MMonMgrReport.h @@ -0,0 +1,67 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 Greg Farnum/Red Hat + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_MMONMGRREPORT_H +#define CEPH_MMONMGRREPORT_H + +#include "messages/PaxosServiceMessage.h" +#include "include/types.h" + +// health_status_t +static inline void encode(health_status_t hs, bufferlist& bl) { + uint8_t v = hs; + ::encode(v, bl); +} +static inline void decode(health_status_t& hs, bufferlist::iterator& p) { + uint8_t v; + ::decode(v, p); + hs = health_status_t(v); +} + +class MMonMgrReport : public PaxosServiceMessage { + + static const int HEAD_VERSION = 1; + static const int COMPAT_VERSION = 1; + +public: + // PGMapDigest is in data payload + list> health_summary, health_detail; + + MMonMgrReport() + : PaxosServiceMessage(MSG_MON_MGR_REPORT, 0, HEAD_VERSION, COMPAT_VERSION) + {} +private: + ~MMonMgrReport() override {} + +public: + const char *get_type_name() const override { return "monmgrreport"; } + + void print(ostream& out) const override { + out << get_type_name(); + } + + void encode_payload(uint64_t features) override { + paxos_encode(); + ::encode(health_summary, payload); + ::encode(health_detail, payload); + } + void decode_payload() override { + bufferlist::iterator p = payload.begin(); + paxos_decode(p); + ::decode(health_summary, p); + ::decode(health_detail, p); + } +}; + +#endif diff --git a/ceph/src/messages/MMonPaxos.h b/ceph/src/messages/MMonPaxos.h index 8c709ddb8..4b21ee38a 100644 --- a/ceph/src/messages/MMonPaxos.h +++ b/ceph/src/messages/MMonPaxos.h @@ -22,7 +22,7 @@ class MMonPaxos : public Message { - static const int HEAD_VERSION = 3; + static const int HEAD_VERSION = 4; static const int COMPAT_VERSION = 3; public: @@ -63,6 +63,8 @@ class MMonPaxos : public Message { map values; + bufferlist feature_map; + MMonPaxos() : Message(MSG_MON_PAXOS, HEAD_VERSION, COMPAT_VERSION) { } MMonPaxos(epoch_t e, int o, utime_t now) : Message(MSG_MON_PAXOS, HEAD_VERSION, COMPAT_VERSION), @@ -103,6 +105,7 @@ public: ::encode(latest_version, payload); ::encode(latest_value, payload); ::encode(values, payload); + ::encode(feature_map, payload); } void decode_payload() override { bufferlist::iterator p = payload.begin(); @@ -118,6 +121,9 @@ public: ::decode(latest_version, p); ::decode(latest_value, p); ::decode(values, p); + if (header.version >= 4) { + ::decode(feature_map, p); + } } }; diff --git a/ceph/src/messages/MOSDPGUpdateLogMissing.h b/ceph/src/messages/MOSDPGUpdateLogMissing.h index facb65bc8..7823fd08f 100644 --- a/ceph/src/messages/MOSDPGUpdateLogMissing.h +++ b/ceph/src/messages/MOSDPGUpdateLogMissing.h @@ -29,7 +29,7 @@ public: spg_t pgid; shard_id_t from; ceph_tid_t rep_tid; - mempool::osd::list entries; + mempool::osd_pglog::list entries; epoch_t get_epoch() const { return map_epoch; } spg_t get_pgid() const { return pgid; } @@ -50,7 +50,7 @@ public: : MOSDFastDispatchOp(MSG_OSD_PG_UPDATE_LOG_MISSING, HEAD_VERSION, COMPAT_VERSION) { } MOSDPGUpdateLogMissing( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, spg_t pgid, shard_id_t from, epoch_t epoch, diff --git a/ceph/src/messages/MOSDPing.h b/ceph/src/messages/MOSDPing.h index 3bb54c5ae..f9b775a0d 100644 --- a/ceph/src/messages/MOSDPing.h +++ b/ceph/src/messages/MOSDPing.h @@ -12,6 +12,17 @@ * */ + +/** + * This is used to send pings between daemons (so far, the OSDs) for + * heartbeat purposes. We include a timestamp and distinguish between + * outgoing pings and responses to those. If you set the + * min_message in the constructor, the message will inflate itself + * to the specified size -- this is good for dealing with network + * issues with jumbo frames. See http://tracker.ceph.com/issues/20087 + * + */ + #ifndef CEPH_MOSDPING_H #define CEPH_MOSDPING_H @@ -23,7 +34,7 @@ class MOSDPing : public Message { - static const int HEAD_VERSION = 2; + static const int HEAD_VERSION = 3; static const int COMPAT_VERSION = 2; public: @@ -52,13 +63,15 @@ class MOSDPing : public Message { __u8 op; osd_peer_stat_t peer_stat; utime_t stamp; + uint32_t min_message_size; - MOSDPing(const uuid_d& f, epoch_t e, __u8 o, utime_t s) + MOSDPing(const uuid_d& f, epoch_t e, __u8 o, utime_t s, uint32_t min_message) : Message(MSG_OSD_PING, HEAD_VERSION, COMPAT_VERSION), - fsid(f), map_epoch(e), peer_as_of_epoch(0), op(o), stamp(s) + fsid(f), map_epoch(e), peer_as_of_epoch(0), op(o), stamp(s), + min_message_size(min_message) { } MOSDPing() - : Message(MSG_OSD_PING, HEAD_VERSION, COMPAT_VERSION) + : Message(MSG_OSD_PING, HEAD_VERSION, COMPAT_VERSION), min_message_size(0) {} private: ~MOSDPing() override {} @@ -72,6 +85,13 @@ public: ::decode(op, p); ::decode(peer_stat, p); ::decode(stamp, p); + if (header.version >= 3) { + int payload_mid_length = p.get_off(); + uint32_t size; + ::decode(size, p); + p.advance(size); + min_message_size = size + payload_mid_length; + } } void encode_payload(uint64_t features) override { ::encode(fsid, payload); @@ -80,6 +100,25 @@ public: ::encode(op, payload); ::encode(peer_stat, payload); ::encode(stamp, payload); + + size_t s = 0; + if (min_message_size > payload.length()) + s = min_message_size - payload.length(); + ::encode((uint32_t)s, payload); + if (s) { + // this should be big enough for normal min_message padding sizes. since + // we are targetting jumbo ethernet frames around 9000 bytes, 16k should + // be more than sufficient! the compiler will statically zero this so + // that at runtime we are only adding a bufferptr reference to it. + static char zeros[16384] = {}; + while (s > sizeof(zeros)) { + payload.append(buffer::create_static(sizeof(zeros), zeros)); + s -= sizeof(zeros); + } + if (s) { + payload.append(buffer::create_static(s, zeros)); + } + } } const char *get_type_name() const override { return "osd_ping"; } diff --git a/ceph/src/mgr/ClusterState.cc b/ceph/src/mgr/ClusterState.cc index 81bcdb728..8bc88c530 100644 --- a/ceph/src/mgr/ClusterState.cc +++ b/ceph/src/mgr/ClusterState.cc @@ -12,6 +12,7 @@ */ #include "messages/MMgrDigest.h" +#include "messages/MMonMgrReport.h" #include "messages/MPGStats.h" #include "mgr/ClusterState.h" @@ -22,7 +23,7 @@ #define dout_prefix *_dout << "mgr " << __func__ << " " ClusterState::ClusterState(MonClient *monc_, Objecter *objecter_) - : monc(monc_), objecter(objecter_), lock("ClusterState") + : monc(monc_), objecter(objecter_), lock("ClusterState"), pgservice(pg_map) {} void ClusterState::set_objecter(Objecter *objecter_) @@ -48,8 +49,6 @@ void ClusterState::load_digest(MMgrDigest *m) void ClusterState::ingest_pgstats(MPGStats *stats) { Mutex::Locker l(lock); - PGMap::Incremental pending_inc; - pending_inc.version = pg_map.version + 1; // to make apply_incremental happy const int from = stats->get_orig_source().num(); bool is_in = false; @@ -58,7 +57,7 @@ void ClusterState::ingest_pgstats(MPGStats *stats) }); if (is_in) { - pending_inc.update_stat(from, stats->epoch, stats->osd_stat); + pending_inc.update_stat(from, stats->epoch, std::move(stats->osd_stat)); } else { pending_inc.update_stat(from, stats->epoch, osd_stat_t()); } @@ -69,36 +68,65 @@ void ClusterState::ingest_pgstats(MPGStats *stats) // In case we're hearing about a PG that according to last // OSDMap update should not exist - if (pg_map.pg_stat.count(pgid) == 0) { - dout(15) << " got " << pgid << " reported at " << pg_stats.reported_epoch << ":" + if (existing_pools.count(pgid.pool()) == 0) { + dout(15) << " got " << pgid + << " reported at " << pg_stats.reported_epoch << ":" << pg_stats.reported_seq << " state " << pg_state_string(pg_stats.state) - << " but DNE in pg_map; pool was probably deleted." + << " but pool not in " << existing_pools << dendl; continue; - // In case we already heard about more recent stats from this PG - // from another OSD - } else if (pg_map.pg_stat[pgid].get_version_pair() > pg_stats.get_version_pair()) { - dout(15) << " had " << pgid << " from " << pg_map.pg_stat[pgid].reported_epoch << ":" + } + // In case we already heard about more recent stats from this PG + // from another OSD + if (pg_map.pg_stat[pgid].get_version_pair() > pg_stats.get_version_pair()) { + dout(15) << " had " << pgid << " from " + << pg_map.pg_stat[pgid].reported_epoch << ":" << pg_map.pg_stat[pgid].reported_seq << dendl; continue; } pending_inc.pg_stat_updates[pgid] = pg_stats; } +} + +void ClusterState::update_delta_stats() +{ + pending_inc.stamp = ceph_clock_now(); + pending_inc.version = pg_map.version + 1; // to make apply_incremental happy + dout(10) << " v" << pending_inc.version << dendl; + + dout(30) << " pg_map before:\n"; + JSONFormatter jf(true); + jf.dump_object("pg_map", pg_map); + jf.flush(*_dout); + *_dout << dendl; + dout(30) << " incremental:\n"; + JSONFormatter jf(true); + jf.dump_object("pending_inc", pending_inc); + jf.flush(*_dout); + *_dout << dendl; pg_map.apply_incremental(g_ceph_context, pending_inc); + pending_inc = PGMap::Incremental(); } void ClusterState::notify_osdmap(const OSDMap &osd_map) { Mutex::Locker l(lock); - PGMap::Incremental pending_inc; + pending_inc.stamp = ceph_clock_now(); pending_inc.version = pg_map.version + 1; // to make apply_incremental happy + dout(10) << " v" << pending_inc.version << dendl; - PGMapUpdater::update_creating_pgs(osd_map, pg_map, &pending_inc); - PGMapUpdater::register_new_pgs(osd_map, pg_map, &pending_inc); + PGMapUpdater::check_osd_map(g_ceph_context, osd_map, pg_map, &pending_inc); + + // update our list of pools that exist, so that we can filter pg_map updates + // in synchrony with this OSDMap. + existing_pools.clear(); + for (auto& p : osd_map.get_pools()) { + existing_pools.insert(p.first); + } // brute force this for now (don't bother being clever by only // checking osds that went up/down) @@ -106,10 +134,20 @@ void ClusterState::notify_osdmap(const OSDMap &osd_map) PGMapUpdater::check_down_pgs(osd_map, pg_map, true, need_check_down_pg_osds, &pending_inc); - pg_map.apply_incremental(g_ceph_context, pending_inc); + dout(30) << " pg_map before:\n"; + JSONFormatter jf(true); + jf.dump_object("pg_map", pg_map); + jf.flush(*_dout); + *_dout << dendl; + dout(30) << " incremental:\n"; + JSONFormatter jf(true); + jf.dump_object("pending_inc", pending_inc); + jf.flush(*_dout); + *_dout << dendl; + pg_map.apply_incremental(g_ceph_context, pending_inc); + pending_inc = PGMap::Incremental(); // TODO: Complete the separation of PG state handling so // that a cut-down set of functionality remains in PGMonitor // while the full-blown PGMap lives only here. } - diff --git a/ceph/src/mgr/ClusterState.h b/ceph/src/mgr/ClusterState.h index fb967e17f..ae08c75da 100644 --- a/ceph/src/mgr/ClusterState.h +++ b/ceph/src/mgr/ClusterState.h @@ -22,6 +22,7 @@ #include "mon/PGMap.h" class MMgrDigest; +class MMonMgrReport; class MPGStats; @@ -37,7 +38,11 @@ protected: FSMap fsmap; mutable Mutex lock; + set existing_pools; ///< pools that exist, as of PGMap epoch PGMap pg_map; + PGMap::Incremental pending_inc; + + PGMapStatService pgservice; bufferlist health_json; bufferlist mon_status_json; @@ -47,6 +52,8 @@ public: void load_digest(MMgrDigest *m); void ingest_pgstats(MPGStats *stats); + void update_delta_stats(); + const bufferlist &get_health() const {return health_json;} const bufferlist &get_mon_status() const {return mon_status_json;} @@ -77,6 +84,14 @@ public: return std::forward(cb)(pg_map, std::forward(args)...); } + template + auto with_pgservice(Callback&& cb, Args&&...args) const -> + decltype(cb(pgservice, std::forward(args)...)) + { + Mutex::Locker l(lock); + return std::forward(cb)(pg_map, std::forward(args)...); + } + template void with_monmap(Args &&... args) const { diff --git a/ceph/src/mgr/DaemonServer.cc b/ceph/src/mgr/DaemonServer.cc index bb1927e25..e8d8c8a21 100644 --- a/ceph/src/mgr/DaemonServer.cc +++ b/ceph/src/mgr/DaemonServer.cc @@ -13,12 +13,13 @@ #include "DaemonServer.h" +#include "include/str_list.h" #include "auth/RotatingKeyRing.h" - #include "json_spirit/json_spirit_writer.h" #include "messages/MMgrOpen.h" #include "messages/MMgrConfigure.h" +#include "messages/MMonMgrReport.h" #include "messages/MCommand.h" #include "messages/MCommandReply.h" #include "messages/MPGStats.h" @@ -171,6 +172,14 @@ bool DaemonServer::ms_verify_authorizer(Connection *con, } } con->set_priv(s->get()); + + if (peer_type == CEPH_ENTITY_TYPE_OSD) { + Mutex::Locker l(lock); + s->osd_id = atoi(s->entity_name.get_id().c_str()); + dout(10) << __func__ << " registering osd." << s->osd_id << " session " + << s << " con " << con << dendl; + osd_cons[s->osd_id].insert(con); + } } return true; @@ -196,6 +205,22 @@ bool DaemonServer::ms_get_authorizer(int dest_type, return *authorizer != NULL; } +bool DaemonServer::ms_handle_reset(Connection *con) +{ + if (con->get_peer_type() == CEPH_ENTITY_TYPE_OSD) { + MgrSessionRef session(static_cast(con->get_priv())); + if (!session) { + return false; + } + session->put(); // SessionRef takes a ref + Mutex::Locker l(lock); + dout(10) << __func__ << " unregistering osd." << session->osd_id + << " session " << session << " con " << con << dendl; + osd_cons[session->osd_id].erase(con); + } + return false; +} + bool DaemonServer::ms_handle_refused(Connection *con) { // do nothing for now @@ -235,15 +260,19 @@ void DaemonServer::shutdown() bool DaemonServer::handle_open(MMgrOpen *m) { - DaemonKey key( - m->get_connection()->get_peer_type(), - m->daemon_name); + uint32_t type = m->get_connection()->get_peer_type(); + DaemonKey key(type, m->daemon_name); dout(4) << "from " << m->get_connection() << " name " - << m->daemon_name << dendl; + << ceph_entity_type_name(type) << "." << m->daemon_name << dendl; auto configure = new MMgrConfigure(); - configure->stats_period = g_conf->mgr_stats_period; + if (m->get_connection()->get_peer_type() == entity_name_t::TYPE_CLIENT) { + // We don't want clients to send us stats + configure->stats_period = 0; + } else { + configure->stats_period = g_conf->mgr_stats_period; + } m->get_connection()->send_message(configure); if (daemon_state.exists(key)) { @@ -257,12 +286,18 @@ bool DaemonServer::handle_open(MMgrOpen *m) bool DaemonServer::handle_report(MMgrReport *m) { - DaemonKey key( - m->get_connection()->get_peer_type(), - m->daemon_name); + uint32_t type = m->get_connection()->get_peer_type(); + DaemonKey key(type, m->daemon_name); dout(4) << "from " << m->get_connection() << " name " - << m->daemon_name << dendl; + << ceph_entity_type_name(type) << "." << m->daemon_name << dendl; + + if (m->get_connection()->get_peer_type() == entity_name_t::TYPE_CLIENT) { + // Clients should not be sending us stats + dout(4) << "rejecting report from client " << m->daemon_name << dendl; + m->put(); + return true; + } DaemonStatePtr daemon; if (daemon_state.exists(key)) { @@ -492,17 +527,14 @@ bool DaemonServer::handle_command(MCommand *m) "mgr", pyc.perm, "cli", 0); cmdnum++; } -#if 0 - for (MgrCommand *cp = mgr_commands; - cp < &mgr_commands[ARRAY_SIZE(mgr_commands)]; cp++) { + for (const auto &cp : mgr_commands) { ostringstream secname; secname << "cmd" << setfill('0') << std::setw(3) << cmdnum; - dump_cmddesc_to_json(f, secname.str(), cp->cmdstring, cp->helpstring, - cp->module, cp->perm, cp->availability, 0); + dump_cmddesc_to_json(&f, secname.str(), cp.cmdstring, cp.helpstring, + cp.module, cp.perm, cp.availability, 0); cmdnum++; } -#endif f.close_section(); // command_descriptions f.flush(cmdctx->odata); cmdctx->reply(0, ss); @@ -518,7 +550,8 @@ bool DaemonServer::handle_command(MCommand *m) if (!_allowed_command(session.get(), py_command.module, prefix, cmdctx->cmdmap, param_str_map, &py_command)) { dout(1) << " access denied" << dendl; - ss << "access denied"; + ss << "access denied; does your client key have mgr caps?" + " See http://docs.ceph.com/docs/master/mgr/administrator/#client-authentication"; cmdctx->reply(-EACCES, ss); return true; } @@ -530,7 +563,8 @@ bool DaemonServer::handle_command(MCommand *m) audit_clog->info() << "from='" << session->inst << "' " << "entity='" << session->entity_name << "' " << "cmd=" << m->cmd << ": access denied"; - ss << "access denied"; + ss << "access denied' does your client key have mgr caps?" + " See http://docs.ceph.com/docs/master/mgr/administrator/#client-authentication"; cmdctx->reply(-EACCES, ss); return true; } @@ -566,26 +600,90 @@ bool DaemonServer::handle_command(MCommand *m) return true; } int acting_primary = -1; - entity_inst_t inst; cluster_state.with_osdmap([&](const OSDMap& osdmap) { acting_primary = osdmap.get_pg_acting_primary(pgid); - if (acting_primary >= 0) { - inst = osdmap.get_inst(acting_primary); - } }); if (acting_primary == -1) { ss << "pg " << pgid << " has no primary osd"; cmdctx->reply(-EAGAIN, ss); return true; } + auto p = osd_cons.find(acting_primary); + if (p == osd_cons.end()) { + ss << "pg " << pgid << " primary osd." << acting_primary + << " is not currently connected"; + cmdctx->reply(-EAGAIN, ss); + } vector pgs = { pgid }; - msgr->send_message(new MOSDScrub(monc->get_fsid(), - pgs, - scrubop == "repair", - scrubop == "deep-scrub"), - inst); + for (auto& con : p->second) { + con->send_message(new MOSDScrub(monc->get_fsid(), + pgs, + scrubop == "repair", + scrubop == "deep-scrub")); + } ss << "instructing pg " << pgid << " on osd." << acting_primary - << " (" << inst << ") to " << scrubop; + << " to " << scrubop; + cmdctx->reply(0, ss); + return true; + } else if (prefix == "osd scrub" || + prefix == "osd deep-scrub" || + prefix == "osd repair") { + string whostr; + cmd_getval(g_ceph_context, cmdctx->cmdmap, "who", whostr); + vector pvec; + get_str_vec(prefix, pvec); + + set osds; + if (whostr == "*") { + cluster_state.with_osdmap([&](const OSDMap& osdmap) { + for (int i = 0; i < osdmap.get_max_osd(); i++) + if (osdmap.is_up(i)) { + osds.insert(i); + } + }); + } else { + long osd = parse_osd_id(whostr.c_str(), &ss); + if (osd < 0) { + ss << "invalid osd '" << whostr << "'"; + cmdctx->reply(-EINVAL, ss); + return true; + } + cluster_state.with_osdmap([&](const OSDMap& osdmap) { + if (osdmap.is_up(osd)) { + osds.insert(osd); + } + }); + if (osds.empty()) { + ss << "osd." << osd << " is not up"; + cmdctx->reply(-EAGAIN, ss); + return true; + } + } + set sent_osds, failed_osds; + for (auto osd : osds) { + auto p = osd_cons.find(osd); + if (p == osd_cons.end()) { + failed_osds.insert(osd); + } else { + sent_osds.insert(osd); + for (auto& con : p->second) { + con->send_message(new MOSDScrub(monc->get_fsid(), + pvec.back() == "repair", + pvec.back() == "deep-scrub")); + } + } + } + if (failed_osds.size() == osds.size()) { + ss << "failed to instruct osd(s) " << osds << " to " << pvec.back() + << " (not connected)"; + r = -EAGAIN; + } else { + ss << "instructed osd(s) " << sent_osds << " to " << pvec.back(); + if (!failed_osds.empty()) { + ss << "; osd(s) " << failed_osds << " were not connected"; + } + r = 0; + } cmdctx->reply(0, ss); return true; } else if (prefix == "osd reweight-by-pg" || @@ -682,6 +780,20 @@ bool DaemonServer::handle_command(MCommand *m) &on_finish->from_mon, &on_finish->outs, on_finish); return true; } + } else if (prefix == "osd df") { + string method; + cmd_getval(g_ceph_context, cmdctx->cmdmap, "output_method", method); + r = cluster_state.with_pgservice([&](const PGMapStatService& pgservice) { + return cluster_state.with_osdmap([&](const OSDMap& osdmap) { + print_osd_utilization(osdmap, &pgservice, ss, + f.get(), method == "tree"); + + cmdctx->odata.append(ss); + return 0; + }); + }); + cmdctx->reply(r, ""); + return true; } else { r = cluster_state.with_pgmap([&](const PGMap& pg_map) { return cluster_state.with_osdmap([&](const OSDMap& osdmap) { @@ -728,3 +840,26 @@ bool DaemonServer::handle_command(MCommand *m) return true; } } + +void DaemonServer::send_report() +{ + auto m = new MMonMgrReport(); + cluster_state.with_pgmap([&](const PGMap& pg_map) { + cluster_state.update_delta_stats(); + + // FIXME: reporting health detail here might be a bad idea? + cluster_state.with_osdmap([&](const OSDMap& osdmap) { + // FIXME: no easy way to get mon features here. this will do for + // now, though, as long as we don't make a backward-incompat change. + pg_map.encode_digest(osdmap, m->get_data(), CEPH_FEATURES_ALL); + dout(10) << pg_map << dendl; + pg_map.get_health(g_ceph_context, osdmap, + m->health_summary, + &m->health_detail); + }); + }); + // TODO? We currently do not notify the PyModules + // TODO: respect needs_send, so we send the report only if we are asked to do + // so, or the state is updated. + monc->send_mon_message(m); +} diff --git a/ceph/src/mgr/DaemonServer.h b/ceph/src/mgr/DaemonServer.h index 0ef4a5655..a1ed292e1 100644 --- a/ceph/src/mgr/DaemonServer.h +++ b/ceph/src/mgr/DaemonServer.h @@ -32,6 +32,7 @@ class MMgrReport; class MMgrOpen; +class MMonMgrReport; class MCommand; struct MgrCommand; @@ -62,6 +63,9 @@ protected: AuthAuthorizeHandlerRegistry auth_registry; + /// connections for osds + ceph::unordered_map> osd_cons; + Mutex lock; static void _generate_command_map(map& cmdmap, @@ -95,7 +99,7 @@ public: ~DaemonServer() override; bool ms_dispatch(Message *m) override; - bool ms_handle_reset(Connection *con) override { return false; } + bool ms_handle_reset(Connection *con) override; void ms_handle_remote_reset(Connection *con) override {} bool ms_handle_refused(Connection *con) override; bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, @@ -111,6 +115,7 @@ public: bool handle_open(MMgrOpen *m); bool handle_report(MMgrReport *m); bool handle_command(MCommand *m); + void send_report(); }; #endif diff --git a/ceph/src/mgr/DaemonState.cc b/ceph/src/mgr/DaemonState.cc index f83f9749d..290fde651 100644 --- a/ceph/src/mgr/DaemonState.cc +++ b/ceph/src/mgr/DaemonState.cc @@ -30,18 +30,20 @@ void DaemonStateIndex::insert(DaemonStatePtr dm) all[dm->key] = dm; } -void DaemonStateIndex::_erase(DaemonKey dmk) +void DaemonStateIndex::_erase(const DaemonKey& dmk) { assert(lock.is_locked_by_me()); - const auto dm = all.at(dmk); + const auto to_erase = all.find(dmk); + assert(to_erase != all.end()); + const auto dm = to_erase->second; auto &server_collection = by_server[dm->hostname]; server_collection.erase(dm->key); if (server_collection.empty()) { by_server.erase(dm->hostname); } - all.erase(dmk); + all.erase(to_erase); } DaemonStateCollection DaemonStateIndex::get_by_type(uint8_t type) const @@ -85,25 +87,25 @@ DaemonStatePtr DaemonStateIndex::get(const DaemonKey &key) } void DaemonStateIndex::cull(entity_type_t daemon_type, - std::set names_exist) + const std::set& names_exist) { - Mutex::Locker l(lock); - - std::set victims; - - for (const auto &i : all) { - if (i.first.first != daemon_type) { - continue; - } + std::vector victims; - if (names_exist.count(i.first.second) == 0) { - victims.insert(i.first); + Mutex::Locker l(lock); + auto begin = all.lower_bound({daemon_type, ""}); + auto end = all.end(); + for (auto &i = begin; i != end; ++i) { + const auto& daemon_key = i->first; + if (daemon_key.first != daemon_type) + break; + if (names_exist.count(daemon_key.second) == 0) { + victims.push_back(daemon_key.second); } } - for (const auto &i : victims) { + for (auto &i : victims) { dout(4) << "Removing data for " << i << dendl; - _erase(i); + _erase({daemon_type, i}); } } diff --git a/ceph/src/mgr/DaemonState.h b/ceph/src/mgr/DaemonState.h index 78fd03652..91160d7f0 100644 --- a/ceph/src/mgr/DaemonState.h +++ b/ceph/src/mgr/DaemonState.h @@ -141,7 +141,7 @@ class DaemonStateIndex PerfCounterTypes types; void insert(DaemonStatePtr dm); - void _erase(DaemonKey dmk); + void _erase(const DaemonKey& dmk); bool exists(const DaemonKey &key) const; DaemonStatePtr get(const DaemonKey &key); @@ -164,7 +164,7 @@ class DaemonStateIndex * a cluster map and want to ensure that anything absent in the map * is also absent in this class. */ - void cull(entity_type_t daemon_type, std::set names_exist); + void cull(entity_type_t daemon_type, const std::set& names_exist); }; #endif diff --git a/ceph/src/mgr/Gil.h b/ceph/src/mgr/Gil.h new file mode 100644 index 000000000..522d4b0e1 --- /dev/null +++ b/ceph/src/mgr/Gil.h @@ -0,0 +1,96 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 SUSE LLC + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef GIL_H_ +#define GIL_H_ + +#include "Python.h" + +#include "common/debug.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_mgr +#undef dout_prefix +#define dout_prefix *_dout << "mgr " << __func__ << " " + +// +// Use one of these in any scope in which you need to hold Python's +// Global Interpreter Lock. +// +// Do *not* nest these, as a second GIL acquire will deadlock (see +// https://docs.python.org/2/c-api/init.html#c.PyEval_RestoreThread) +// +// If in doubt, explicitly put a scope around the block of code you +// know you need the GIL in. +// +// See the comment below for when to set new_thread == true +// +class Gil { +public: + Gil(const Gil&) = delete; + Gil& operator=(const Gil&) = delete; + + Gil(PyThreadState *ts, bool new_thread = false) : pThreadState(ts) + { + assert(pThreadState != nullptr); + + // Acquire the GIL, set the current thread state + PyEval_RestoreThread(pThreadState); + dout(20) << "GIL acquired for thread state " << pThreadState << dendl; + + // + // If called from a separate OS thread (i.e. a thread not created + // by Python, that does't already have a python thread state that + // was created when that thread was active), we need to manually + // create and switch to a python thread state specifically for this + // OS thread. + // + // Note that instead of requring the caller to set new_thread == true + // when calling this from a separate OS thread, we could figure out + // if this was necessary automatically, as follows: + // + // if (pThreadState->thread_id != PyThread_get_thread_ident()) { + // + // However, this means we're accessing pThreadState->thread_id, but + // the Python C API docs say that "The only public data member is + // PyInterpreterState *interp", i.e. doing this would violate + // something that's meant to be a black box. + // + if (new_thread) { + pNewThreadState = PyThreadState_New(pThreadState->interp); + PyThreadState_Swap(pNewThreadState); + dout(20) << "Switched to new thread state " << pNewThreadState << dendl; + } + } + + ~Gil() + { + if (pNewThreadState != nullptr) { + dout(20) << "Destroying new thread state " << pNewThreadState << dendl; + PyThreadState_Swap(pThreadState); + PyThreadState_Clear(pNewThreadState); + PyThreadState_Delete(pNewThreadState); + } + // Release the GIL, reset the thread state to NULL + PyEval_SaveThread(); + dout(20) << "GIL released for thread state " << pThreadState << dendl; + } + +private: + PyThreadState *pThreadState; + PyThreadState *pNewThreadState = nullptr; +}; + +#endif + diff --git a/ceph/src/mgr/Mgr.cc b/ceph/src/mgr/Mgr.cc index 9df32239b..15fae8502 100644 --- a/ceph/src/mgr/Mgr.cc +++ b/ceph/src/mgr/Mgr.cc @@ -345,9 +345,10 @@ void Mgr::load_config() std::ostringstream cmd_json; cmd_json << "{\"prefix\": \"config-key get\", \"key\": \"" << key << "\"}"; get_cmd.run(monc, cmd_json.str()); + lock.Unlock(); get_cmd.wait(); + lock.Lock(); assert(get_cmd.r == 0); - loaded[key] = get_cmd.outbl.to_str(); } } @@ -466,16 +467,6 @@ bool Mgr::ms_dispatch(Message *m) handle_mgr_digest(static_cast(m)); break; case CEPH_MSG_MON_MAP: - // FIXME: we probably never get called here because MonClient - // has consumed the message. For consuming OSDMap we need - // to be the tail dispatcher, but to see MonMap we would - // need to be at the head. - // Result is that ClusterState has access to monmap (it reads - // from monclient anyway), but we don't see notifications. Hook - // into MonClient to get notifications instead of messing - // with message delivery to achieve it? - ceph_abort(); - py_modules.notify_all("mon_map", ""); m->put(); break; @@ -593,3 +584,8 @@ void Mgr::handle_mgr_digest(MMgrDigest* m) m->put(); } +void Mgr::tick() +{ + dout(0) << dendl; + server.send_report(); +} diff --git a/ceph/src/mgr/Mgr.h b/ceph/src/mgr/Mgr.h index 2efb2683f..0aa5b5c5b 100644 --- a/ceph/src/mgr/Mgr.h +++ b/ceph/src/mgr/Mgr.h @@ -86,6 +86,8 @@ public: bool ms_dispatch(Message *m); + void tick(); + void background_init(); void shutdown(); }; diff --git a/ceph/src/mgr/MgrClient.cc b/ceph/src/mgr/MgrClient.cc index 2f558c061..c7774959d 100644 --- a/ceph/src/mgr/MgrClient.cc +++ b/ceph/src/mgr/MgrClient.cc @@ -59,7 +59,10 @@ void MgrClient::shutdown() command_table.clear(); timer.shutdown(); - session.reset(); + if (session) { + session->con->mark_down(); + session.reset(); + } } bool MgrClient::ms_dispatch(Message *m) @@ -233,10 +236,10 @@ void MgrClient::send_report() session->declared.insert(path); } - ::encode(static_cast(data.u64.read()), report->packed); + ::encode(static_cast(data.u64), report->packed); if (data.type & PERFCOUNTER_LONGRUNAVG) { - ::encode(static_cast(data.avgcount.read()), report->packed); - ::encode(static_cast(data.avgcount2.read()), report->packed); + ::encode(static_cast(data.avgcount), report->packed); + ::encode(static_cast(data.avgcount2), report->packed); } } ENCODE_FINISH(report->packed); @@ -256,9 +259,13 @@ void MgrClient::send_report() timer.add_event_after(stats_period, report_callback); } - if (pgstats_cb) { - MPGStats *m_stats = pgstats_cb(); - session->con->send_message(m_stats); + send_pgstats(); +} + +void MgrClient::send_pgstats() +{ + if (pgstats_cb && session) { + session->con->send_message(pgstats_cb()); } } diff --git a/ceph/src/mgr/MgrClient.h b/ceph/src/mgr/MgrClient.h index f9385b8be..87df28650 100644 --- a/ceph/src/mgr/MgrClient.h +++ b/ceph/src/mgr/MgrClient.h @@ -92,6 +92,7 @@ public: bool handle_command_reply(MCommandReply *m); void send_report(); + void send_pgstats(); void set_pgstats_cb(std::function cb_) { diff --git a/ceph/src/mgr/MgrCommands.h b/ceph/src/mgr/MgrCommands.h index 17de3a8c7..7df74d730 100644 --- a/ceph/src/mgr/MgrCommands.h +++ b/ceph/src/mgr/MgrCommands.h @@ -59,6 +59,9 @@ COMMAND("osd perf", \ "osd", \ "r", \ "cli,rest") +COMMAND("osd df " \ + "name=output_method,type=CephChoices,strings=plain|tree,req=false", \ + "show OSD utilization", "osd", "r", "cli,rest") COMMAND("osd blocked-by", \ "print histogram of which OSDs are blocking their peers", \ "osd", "r", "cli,rest") @@ -94,3 +97,13 @@ COMMAND("osd test-reweight-by-pg " \ "name=pools,type=CephPoolname,n=N,req=false", \ "dry run of reweight OSDs by PG distribution [overload-percentage-for-consideration, default 120]", \ "osd", "rw", "cli,rest") + +COMMAND("osd scrub " \ + "name=who,type=CephString", \ + "initiate scrub on osd ", "osd", "rw", "cli,rest") +COMMAND("osd deep-scrub " \ + "name=who,type=CephString", \ + "initiate deep scrub on osd ", "osd", "rw", "cli,rest") +COMMAND("osd repair " \ + "name=who,type=CephString", \ + "initiate repair on osd ", "osd", "rw", "cli,rest") diff --git a/ceph/src/mgr/MgrPyModule.cc b/ceph/src/mgr/MgrPyModule.cc index 078f7f503..fda9bf652 100644 --- a/ceph/src/mgr/MgrPyModule.cc +++ b/ceph/src/mgr/MgrPyModule.cc @@ -11,6 +11,8 @@ * Foundation. See file COPYING. */ +#include "PyState.h" +#include "Gil.h" #include "PyFormatter.h" @@ -46,32 +48,121 @@ std::string handle_pyerror() #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mgr + +#undef dout_prefix +#define dout_prefix *_dout << "mgr[py] " + +namespace { + PyObject* log_write(PyObject*, PyObject* args) { + char* m = nullptr; + if (PyArg_ParseTuple(args, "s", &m)) { + auto len = strlen(m); + if (len && m[len-1] == '\n') { + m[len-1] = '\0'; + } + dout(4) << m << dendl; + } + Py_RETURN_NONE; + } + + PyObject* log_flush(PyObject*, PyObject*){ + Py_RETURN_NONE; + } + + static PyMethodDef log_methods[] = { + {"write", log_write, METH_VARARGS, "write stdout and stderr"}, + {"flush", log_flush, METH_VARARGS, "flush"}, + {nullptr, nullptr, 0, nullptr} + }; +} + #undef dout_prefix #define dout_prefix *_dout << "mgr " << __func__ << " " -MgrPyModule::MgrPyModule(const std::string &module_name_) +MgrPyModule::MgrPyModule(const std::string &module_name_, const std::string &sys_path, PyThreadState *main_ts_) : module_name(module_name_), - pClassInstance(nullptr) -{} - -MgrPyModule::~MgrPyModule() + pClassInstance(nullptr), + pMainThreadState(main_ts_) { - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + assert(pMainThreadState != nullptr); + + Gil gil(pMainThreadState); + + pMyThreadState = Py_NewInterpreter(); + if (pMyThreadState == nullptr) { + derr << "Failed to create python sub-interpreter for '" << module_name << '"' << dendl; + } else { + // Some python modules do not cope with an unpopulated argv, so lets + // fake one. This step also picks up site-packages into sys.path. + const char *argv[] = {"ceph-mgr"}; + PySys_SetArgv(1, (char**)argv); + + if (g_conf->daemonize) { + auto py_logger = Py_InitModule("ceph_logger", log_methods); +#if PY_MAJOR_VERSION >= 3 + PySys_SetObject("stderr", py_logger); + PySys_SetObject("stdout", py_logger); +#else + PySys_SetObject(const_cast("stderr"), py_logger); + PySys_SetObject(const_cast("stdout"), py_logger); +#endif + } + // Populate python namespace with callable hooks + Py_InitModule("ceph_state", CephStateMethods); - Py_XDECREF(pClassInstance); + PySys_SetPath(const_cast(sys_path.c_str())); + } +} - PyGILState_Release(gstate); +MgrPyModule::~MgrPyModule() +{ + if (pMyThreadState != nullptr) { + Gil gil(pMyThreadState); + + Py_XDECREF(pClassInstance); + + // + // Ideally, now, we'd be able to do this: + // + // Py_EndInterpreter(pMyThreadState); + // PyThreadState_Swap(pMainThreadState); + // + // Unfortunately, if the module has any other *python* threads active + // at this point, Py_EndInterpreter() will abort with: + // + // Fatal Python error: Py_EndInterpreter: not the last thread + // + // This can happen when using CherryPy in a module, becuase CherryPy + // runs an extra thread as a timeout monitor, which spends most of its + // life inside a time.sleep(60). Unless you are very, very lucky with + // the timing calling this destructor, that thread will still be stuck + // in a sleep, and Py_EndInterpreter() will abort. + // + // This could of course also happen with a poorly written module which + // made no attempt to clean up any additional threads it created. + // + // The safest thing to do is just not call Py_EndInterpreter(), and + // let Py_Finalize() kill everything after all modules are shut down. + // + } } int MgrPyModule::load() { + if (pMyThreadState == nullptr) { + derr << "No python sub-interpreter exists for module '" << module_name << "'" << dendl; + return -EINVAL; + } + + Gil gil(pMyThreadState); + // Load the module PyObject *pName = PyString_FromString(module_name.c_str()); auto pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule == nullptr) { derr << "Module not found: '" << module_name << "'" << dendl; + derr << handle_pyerror() << dendl; return -ENOENT; } @@ -81,6 +172,7 @@ int MgrPyModule::load() Py_DECREF(pModule); if (pClass == nullptr) { derr << "Class not found in module '" << module_name << "'" << dendl; + derr << handle_pyerror() << dendl; return -EINVAL; } @@ -95,6 +187,7 @@ int MgrPyModule::load() Py_DECREF(pArgs); if (pClassInstance == nullptr) { derr << "Failed to construct class in '" << module_name << "'" << dendl; + derr << handle_pyerror() << dendl; return -EINVAL; } else { dout(1) << "Constructed class from module: " << module_name << dendl; @@ -107,8 +200,9 @@ int MgrPyModule::serve() { assert(pClassInstance != nullptr); - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + // This method is called from a separate OS thread (i.e. a thread not + // created by Python), so tell Gil to wrap this in a new thread state. + Gil gil(pMyThreadState, true); auto pValue = PyObject_CallMethod(pClassInstance, const_cast("serve"), nullptr); @@ -122,8 +216,6 @@ int MgrPyModule::serve() return -EINVAL; } - PyGILState_Release(gstate); - return r; } @@ -132,8 +224,7 @@ void MgrPyModule::shutdown() { assert(pClassInstance != nullptr); - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + Gil gil(pMyThreadState); auto pValue = PyObject_CallMethod(pClassInstance, const_cast("shutdown"), nullptr); @@ -144,16 +235,13 @@ void MgrPyModule::shutdown() derr << "Failed to invoke shutdown() on " << module_name << dendl; derr << handle_pyerror() << dendl; } - - PyGILState_Release(gstate); } void MgrPyModule::notify(const std::string ¬ify_type, const std::string ¬ify_id) { assert(pClassInstance != nullptr); - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + Gil gil(pMyThreadState); // Execute auto pValue = PyObject_CallMethod(pClassInstance, @@ -170,16 +258,13 @@ void MgrPyModule::notify(const std::string ¬ify_type, const std::string ¬i // a hook to unload misbehaving modules when they have an // error somewhere like this } - - PyGILState_Release(gstate); } void MgrPyModule::notify_clog(const LogEntry &log_entry) { assert(pClassInstance != nullptr); - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + Gil gil(pMyThreadState); // Construct python-ized LogEntry PyFormatter f; @@ -201,15 +286,12 @@ void MgrPyModule::notify_clog(const LogEntry &log_entry) // a hook to unload misbehaving modules when they have an // error somewhere like this } - - PyGILState_Release(gstate); } int MgrPyModule::load_commands() { - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - + // Don't need a Gil here -- this is called from MgrPyModule::load(), + // which already has one. PyObject *command_list = PyObject_GetAttrString(pClassInstance, "COMMANDS"); assert(command_list != nullptr); const size_t list_size = PyList_Size(command_list); @@ -239,8 +321,6 @@ int MgrPyModule::load_commands() } Py_DECREF(command_list); - PyGILState_Release(gstate); - dout(10) << "loaded " << commands.size() << " commands" << dendl; return 0; @@ -254,8 +334,7 @@ int MgrPyModule::handle_command( assert(ss != nullptr); assert(ds != nullptr); - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + Gil gil(pMyThreadState); PyFormatter f; cmdmap_dump(cmdmap, &f); @@ -283,8 +362,6 @@ int MgrPyModule::handle_command( r = -EINVAL; } - PyGILState_Release(gstate); - return r; } diff --git a/ceph/src/mgr/MgrPyModule.h b/ceph/src/mgr/MgrPyModule.h index 7d91275ea..14be1566f 100644 --- a/ceph/src/mgr/MgrPyModule.h +++ b/ceph/src/mgr/MgrPyModule.h @@ -44,13 +44,15 @@ class MgrPyModule private: const std::string module_name; PyObject *pClassInstance; + PyThreadState *pMainThreadState; + PyThreadState *pMyThreadState = nullptr; std::vector commands; int load_commands(); public: - MgrPyModule(const std::string &module_name); + MgrPyModule(const std::string &module_name, const std::string &sys_path, PyThreadState *main_ts); ~MgrPyModule(); int load(); diff --git a/ceph/src/mgr/MgrSession.h b/ceph/src/mgr/MgrSession.h index 790d76b8a..72afd7a67 100644 --- a/ceph/src/mgr/MgrSession.h +++ b/ceph/src/mgr/MgrSession.h @@ -18,6 +18,8 @@ struct MgrSession : public RefCountedObject { EntityName entity_name; entity_inst_t inst; + int osd_id = -1; ///< osd id (if an osd) + // mon caps are suitably generic for mgr MonCap caps; diff --git a/ceph/src/mgr/MgrStandby.cc b/ceph/src/mgr/MgrStandby.cc index 1bfcadd71..d46dc194a 100644 --- a/ceph/src/mgr/MgrStandby.cc +++ b/ceph/src/mgr/MgrStandby.cc @@ -14,6 +14,8 @@ #include #include "common/errno.h" +#include "common/signal.h" +#include "include/compat.h" #include "include/stringify.h" #include "global/global_context.h" @@ -33,7 +35,7 @@ #define dout_prefix *_dout << "mgr " << __func__ << " " -MgrStandby::MgrStandby() : +MgrStandby::MgrStandby(int argc, const char **argv) : Dispatcher(g_ceph_context), monc{g_ceph_context}, client_messenger(Messenger::create_client_messenger(g_ceph_context, "mgr")), @@ -44,7 +46,9 @@ MgrStandby::MgrStandby() : audit_clog(log_client.create_channel(CLOG_CHANNEL_AUDIT)), lock("MgrStandby::lock"), timer(g_ceph_context, lock), - active_mgr(nullptr) + active_mgr(nullptr), + orig_argc(argc), + orig_argv(argv) { } @@ -134,7 +138,7 @@ int MgrStandby::init() client.init(); timer.init(); - send_beacon(); + tick(); dout(4) << "Complete." << dendl; return 0; @@ -155,9 +159,20 @@ void MgrStandby::send_beacon() available); monc.send_mon_message(m); - timer.add_event_after(g_conf->mgr_beacon_period, new FunctionContext( +} + +void MgrStandby::tick() +{ + dout(0) << __func__ << dendl; + send_beacon(); + + if (active_mgr) { + active_mgr->tick(); + } + + timer.add_event_after(g_conf->mgr_tick_period, new FunctionContext( [this](int r){ - send_beacon(); + tick(); } )); } @@ -191,6 +206,45 @@ void MgrStandby::shutdown() client_messenger->shutdown(); } +void MgrStandby::respawn() +{ + char *new_argv[orig_argc+1]; + dout(1) << " e: '" << orig_argv[0] << "'" << dendl; + for (int i=0; i log_to_monitors; @@ -238,8 +292,7 @@ void MgrStandby::handle_mgr_map(MMgrMap* mmap) } else { if (active_mgr != nullptr) { derr << "I was active but no longer am" << dendl; - active_mgr->shutdown(); - active_mgr.reset(); + respawn(); } } @@ -251,22 +304,18 @@ bool MgrStandby::ms_dispatch(Message *m) Mutex::Locker l(lock); dout(4) << state_str() << " " << *m << dendl; - switch (m->get_type()) { - case MSG_MGR_MAP: - handle_mgr_map(static_cast(m)); - break; - - default: - if (active_mgr) { - lock.Unlock(); - active_mgr->ms_dispatch(m); - lock.Lock(); - } else { - return false; - } + if (m->get_type() == MSG_MGR_MAP) { + handle_mgr_map(static_cast(m)); + return true; + } else if (active_mgr) { + auto am = active_mgr; + lock.Unlock(); + bool handled = am->ms_dispatch(m); + lock.Lock(); + return handled; + } else { + return false; } - - return true; } diff --git a/ceph/src/mgr/MgrStandby.h b/ceph/src/mgr/MgrStandby.h index d33c633dc..79cdaa0c0 100644 --- a/ceph/src/mgr/MgrStandby.h +++ b/ceph/src/mgr/MgrStandby.h @@ -53,15 +53,19 @@ protected: Mutex lock; SafeTimer timer; - std::unique_ptr active_mgr; + std::shared_ptr active_mgr; + + int orig_argc; + const char **orig_argv; std::string state_str(); void handle_mgr_map(MMgrMap *m); void _update_log_config(); + void send_beacon(); public: - MgrStandby(); + MgrStandby(int argc, const char **argv); ~MgrStandby() override; bool ms_dispatch(Message *m) override; @@ -73,10 +77,10 @@ public: int init(); void shutdown(); - void usage() {} + void respawn(); int main(vector args); void handle_signal(int signum); - void send_beacon(); + void tick(); }; #endif diff --git a/ceph/src/mgr/PyFormatter.cc b/ceph/src/mgr/PyFormatter.cc index abeb420c0..4c9aec305 100644 --- a/ceph/src/mgr/PyFormatter.cc +++ b/ceph/src/mgr/PyFormatter.cc @@ -17,6 +17,8 @@ #include "PyFormatter.h" +#define LARGE_SIZE 1024 + void PyFormatter::open_array_section(const char *name) { @@ -85,8 +87,10 @@ std::ostream& PyFormatter::dump_stream(const char *name) void PyFormatter::dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) { - // TODO - ceph_abort(); + char buf[LARGE_SIZE]; + vsnprintf(buf, LARGE_SIZE, fmt, ap); + + dump_pyobject(name, PyString_FromString(buf)); } /** diff --git a/ceph/src/mgr/PyModules.cc b/ceph/src/mgr/PyModules.cc index 3e00822fc..988e16ba6 100644 --- a/ceph/src/mgr/PyModules.cc +++ b/ceph/src/mgr/PyModules.cc @@ -13,6 +13,7 @@ // Include this first to get python headers earlier #include "PyState.h" +#include "Gil.h" #include #include "common/errno.h" @@ -29,47 +30,23 @@ #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mgr - #undef dout_prefix -#define dout_prefix *_dout << "mgr[py] " - -namespace { - PyObject* log_write(PyObject*, PyObject* args) { - char* m = nullptr; - if (PyArg_ParseTuple(args, "s", &m)) { - auto len = strlen(m); - if (len && m[len-1] == '\n') { - m[len-1] = '\0'; - } - dout(4) << m << dendl; - } - Py_RETURN_NONE; - } +#define dout_prefix *_dout << "mgr " << __func__ << " " - PyObject* log_flush(PyObject*, PyObject*){ - Py_RETURN_NONE; - } +// definition for non-const static member +std::string PyModules::config_prefix; - static PyMethodDef log_methods[] = { - {"write", log_write, METH_VARARGS, "write stdout and stderr"}, - {"flush", log_flush, METH_VARARGS, "flush"}, - {nullptr, nullptr, 0, nullptr} - }; -} +// constructor/destructor implementations cannot be in .h, +// because ServeThread is still an "incomplete" type there -#undef dout_prefix -#define dout_prefix *_dout << "mgr " << __func__ << " " - -PyModules::PyModules(DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, - Objecter &objecter_, Client &client_, - Finisher &f) +PyModules::PyModules(DaemonStateIndex &ds, ClusterState &cs, + MonClient &mc, Objecter &objecter_, Client &client_, + Finisher &f) : daemon_state(ds), cluster_state(cs), monc(mc), - objecter(objecter_), client(client_), - finisher(f) + objecter(objecter_), client(client_), finisher(f), + lock("PyModules") {} -// we can not have the default destructor in header, because ServeThread is -// still an "incomplete" type. so we need to define the destructor here. PyModules::~PyModules() = default; void PyModules::dump_server(const std::string &hostname, @@ -260,7 +237,7 @@ PyObject *PyModules::get_python(const std::string &what) cluster_state.with_pgmap( [&osd_map, &f](const PGMap &pg_map) { pg_map.dump_fs_stats(nullptr, &f, true); - pg_map.dump_pool_stats(osd_map, nullptr, &f, true); + pg_map.dump_pool_stats_full(osd_map, nullptr, &f, true); }); }); return f.get(); @@ -361,61 +338,46 @@ int PyModules::init() Mutex::Locker locker(lock); global_handle = this; + // namespace in config-key prefixed by "mgr/" + config_prefix = std::string(g_conf->name.get_type_str()) + "/"; // Set up global python interpreter Py_SetProgramName(const_cast(PYTHON_EXECUTABLE)); Py_InitializeEx(0); - // Some python modules do not cope with an unpopulated argv, so lets - // fake one. This step also picks up site-packages into sys.path. - const char *argv[] = {"ceph-mgr"}; - PySys_SetArgv(1, (char**)argv); - - if (g_conf->daemonize) { - auto py_logger = Py_InitModule("ceph_logger", log_methods); -#if PY_MAJOR_VERSION >= 3 - PySys_SetObject("stderr", py_logger); - PySys_SetObject("stdout", py_logger); -#else - PySys_SetObject(const_cast("stderr"), py_logger); - PySys_SetObject(const_cast("stdout"), py_logger); -#endif + // Let CPython know that we will be calling it back from other + // threads in future. + if (! PyEval_ThreadsInitialized()) { + PyEval_InitThreads(); } - // Populate python namespace with callable hooks - Py_InitModule("ceph_state", CephStateMethods); // Configure sys.path to include mgr_module_path std::string sys_path = std::string(Py_GetPath()) + ":" + get_site_packages() + ":" + g_conf->mgr_module_path; dout(10) << "Computed sys.path '" << sys_path << "'" << dendl; - PySys_SetPath((char*)(sys_path.c_str())); - // Let CPython know that we will be calling it back from other - // threads in future. - if (! PyEval_ThreadsInitialized()) { - PyEval_InitThreads(); - } + // Drop the GIL and remember the main thread state (current + // thread state becomes NULL) + pMainThreadState = PyEval_SaveThread(); // Load python code boost::tokenizer<> tok(g_conf->mgr_modules); for(const auto& module_name : tok) { dout(1) << "Loading python module '" << module_name << "'" << dendl; - auto mod = std::unique_ptr(new MgrPyModule(module_name)); + auto mod = std::unique_ptr(new MgrPyModule(module_name, sys_path, pMainThreadState)); int r = mod->load(); if (r != 0) { + // Don't use handle_pyerror() here; we don't have the GIL + // or the right thread state (this is deliberate). derr << "Error loading module '" << module_name << "': " << cpp_strerror(r) << dendl; - derr << handle_pyerror() << dendl; // Don't drop out here, load the other modules } else { // Success! modules[module_name] = std::move(mod); } - } + } - // Drop the GIL - PyEval_SaveThread(); - return 0; } @@ -424,19 +386,20 @@ class ServeThread : public Thread MgrPyModule *mod; public: + bool running; + ServeThread(MgrPyModule *mod_) : mod(mod_) {} void *entry() override { - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); + running = true; + // No need to acquire the GIL here; the module does it. dout(4) << "Entering thread for " << mod->get_name() << dendl; mod->serve(); - PyGILState_Release(gstate); - + running = false; return nullptr; } }; @@ -469,7 +432,9 @@ void PyModules::shutdown() auto module = i.second.get(); const auto& name = i.first; dout(10) << "waiting for module " << name << " to shutdown" << dendl; + lock.Unlock(); module->shutdown(); + lock.Lock(); dout(10) << "module " << name << " shutdown" << dendl; } @@ -484,7 +449,7 @@ void PyModules::shutdown() modules.clear(); - PyGILState_Ensure(); + PyEval_RestoreThread(pMainThreadState); Py_Finalize(); // nobody needs me anymore. @@ -499,6 +464,8 @@ void PyModules::notify_all(const std::string ¬ify_type, dout(10) << __func__ << ": notify_all " << notify_type << dendl; for (auto& i : modules) { auto module = i.second.get(); + if (!serve_threads[i.first]->running) + continue; // Send all python calls down a Finisher to avoid blocking // C++ code, and avoid any potential lock cycles. finisher.queue(new FunctionContext([module, notify_type, notify_id](int r){ @@ -514,6 +481,8 @@ void PyModules::notify_all(const LogEntry &log_entry) dout(10) << __func__ << ": notify_all (clog)" << dendl; for (auto& i : modules) { auto module = i.second.get(); + if (!serve_threads[i.first]->running) + continue; // Send all python calls down a Finisher to avoid blocking // C++ code, and avoid any potential lock cycles. // @@ -533,7 +502,9 @@ bool PyModules::get_config(const std::string &handle, Mutex::Locker l(lock); PyEval_RestoreThread(tstate); - const std::string global_key = config_prefix + handle + "." + key; + const std::string global_key = config_prefix + handle + "/" + key; + + dout(4) << __func__ << "key: " << global_key << dendl; if (config_cache.count(global_key)) { *val = config_cache.at(global_key); @@ -543,10 +514,30 @@ bool PyModules::get_config(const std::string &handle, } } +PyObject *PyModules::get_config_prefix(const std::string &handle, + const std::string &prefix) const +{ + PyThreadState *tstate = PyEval_SaveThread(); + Mutex::Locker l(lock); + PyEval_RestoreThread(tstate); + + const std::string base_prefix = config_prefix + handle + "/"; + const std::string global_prefix = base_prefix + prefix; + dout(4) << __func__ << "prefix: " << global_prefix << dendl; + + PyFormatter f; + for (auto p = config_cache.lower_bound(global_prefix); + p != config_cache.end() && p->first.find(global_prefix) == 0; + ++p) { + f.dump_string(p->first.c_str() + base_prefix.size(), p->second); + } + return f.get(); +} + void PyModules::set_config(const std::string &handle, const std::string &key, const std::string &val) { - const std::string global_key = config_prefix + handle + "." + key; + const std::string global_key = config_prefix + handle + "/" + key; Command set_cmd; { diff --git a/ceph/src/mgr/PyModules.h b/ceph/src/mgr/PyModules.h index 8e9291130..6a71b6493 100644 --- a/ceph/src/mgr/PyModules.h +++ b/ceph/src/mgr/PyModules.h @@ -43,8 +43,10 @@ class PyModules std::string get_site_packages(); + PyThreadState *pMainThreadState = nullptr; + public: - static constexpr auto config_prefix = "mgr."; + static std::string config_prefix; PyModules(DaemonStateIndex &ds, ClusterState &cs, MonClient &mc, Objecter &objecter_, Client &client_, @@ -90,6 +92,8 @@ public: bool get_config(const std::string &handle, const std::string &key, std::string *val) const; + PyObject *get_config_prefix(const std::string &handle, + const std::string &prefix) const; void set_config(const std::string &handle, const std::string &key, const std::string &val); diff --git a/ceph/src/mgr/PyState.cc b/ceph/src/mgr/PyState.cc index ca62c762b..ce71dcd3f 100644 --- a/ceph/src/mgr/PyState.cc +++ b/ceph/src/mgr/PyState.cc @@ -19,11 +19,14 @@ #include "Mgr.h" #include "mon/MonClient.h" +#include "common/errno.h" #include "common/version.h" #include "PyState.h" +#include "Gil.h" #define dout_context g_ceph_context +#define dout_subsys ceph_subsys_mgr PyModules *global_handle = NULL; @@ -32,13 +35,14 @@ class MonCommandCompletion : public Context { PyObject *python_completion; const std::string tag; + PyThreadState *pThreadState; public: std::string outs; bufferlist outbl; - MonCommandCompletion(PyObject* ev, const std::string &tag_) - : python_completion(ev), tag(tag_) + MonCommandCompletion(PyObject* ev, const std::string &tag_, PyThreadState *ts_) + : python_completion(ev), tag(tag_), pThreadState(ts_) { assert(python_completion != nullptr); Py_INCREF(python_completion); @@ -51,28 +55,28 @@ public: void finish(int r) override { - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); - - auto set_fn = PyObject_GetAttrString(python_completion, "complete"); - assert(set_fn != nullptr); - - auto pyR = PyInt_FromLong(r); - auto pyOutBl = PyString_FromString(outbl.to_str().c_str()); - auto pyOutS = PyString_FromString(outs.c_str()); - auto args = PyTuple_Pack(3, pyR, pyOutBl, pyOutS); - Py_DECREF(pyR); - Py_DECREF(pyOutBl); - Py_DECREF(pyOutS); - - auto rtn = PyObject_CallObject(set_fn, args); - if (rtn != nullptr) { - Py_DECREF(rtn); + dout(10) << "MonCommandCompletion::finish()" << dendl; + { + // Scoped so the Gil is released before calling notify_all() + Gil gil(pThreadState); + + auto set_fn = PyObject_GetAttrString(python_completion, "complete"); + assert(set_fn != nullptr); + + auto pyR = PyInt_FromLong(r); + auto pyOutBl = PyString_FromString(outbl.to_str().c_str()); + auto pyOutS = PyString_FromString(outs.c_str()); + auto args = PyTuple_Pack(3, pyR, pyOutBl, pyOutS); + Py_DECREF(pyR); + Py_DECREF(pyOutBl); + Py_DECREF(pyOutS); + + auto rtn = PyObject_CallObject(set_fn, args); + if (rtn != nullptr) { + Py_DECREF(rtn); + } + Py_DECREF(args); } - Py_DECREF(args); - - PyGILState_Release(gstate); - global_handle->notify_all("command", tag); } }; @@ -105,7 +109,7 @@ ceph_send_command(PyObject *self, PyObject *args) } Py_DECREF(set_fn); - auto c = new MonCommandCompletion(completion, tag); + auto c = new MonCommandCompletion(completion, tag, PyThreadState_Get()); if (std::string(type) == "mon") { global_handle->get_monc().start_mon_command( {cmd_json}, @@ -117,7 +121,10 @@ ceph_send_command(PyObject *self, PyObject *args) std::string err; uint64_t osd_id = strict_strtoll(name, 10, &err); if (!err.empty()) { - // TODO: raise exception + delete c; + string msg("invalid osd_id: "); + msg.append("\"").append(name).append("\""); + PyErr_SetString(PyExc_ValueError, msg.c_str()); return nullptr; } @@ -139,14 +146,18 @@ ceph_send_command(PyObject *self, PyObject *args) &c->outs, c); if (r != 0) { - // TODO: raise exception + string msg("failed to send command to mds: "); + msg.append(cpp_strerror(r)); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); return nullptr; } } else if (std::string(type) == "pg") { // TODO: expose objecter::pg_command return nullptr; } else { - // TODO: raise exception + string msg("unknown service type: "); + msg.append(type); + PyErr_SetString(PyExc_ValueError, msg.c_str()); return nullptr; } @@ -183,6 +194,12 @@ ceph_get_server(PyObject *self, PyObject *args) } } +static PyObject* +ceph_get_mgr_id(PyObject *self, PyObject *args) +{ + return PyString_FromString(g_conf->name.get_id().c_str()); +} + static PyObject* ceph_config_get(PyObject *self, PyObject *args) { @@ -196,14 +213,27 @@ ceph_config_get(PyObject *self, PyObject *args) std::string value; bool found = global_handle->get_config(handle, what, &value); if (found) { - derr << "Found" << dendl; + dout(10) << "ceph_config_get " << what << " found: " << value.c_str() << dendl; return PyString_FromString(value.c_str()); } else { - derr << "Not found" << dendl; + derr << "ceph_config_get " << what << " not found " << dendl; Py_RETURN_NONE; } } +static PyObject* +ceph_config_get_prefix(PyObject *self, PyObject *args) +{ + char *handle = nullptr; + char *prefix = nullptr; + if (!PyArg_ParseTuple(args, "ss:ceph_config_get", &handle, &prefix)) { + derr << "Invalid args!" << dendl; + return nullptr; + } + + return global_handle->get_config_prefix(handle, prefix); +} + static PyObject* ceph_config_set(PyObject *self, PyObject *args) { @@ -310,8 +340,12 @@ PyMethodDef CephStateMethods[] = { "Get a service's metadata"}, {"send_command", ceph_send_command, METH_VARARGS, "Send a mon command"}, + {"get_mgr_id", ceph_get_mgr_id, METH_NOARGS, + "Get the mgr id"}, {"get_config", ceph_config_get, METH_VARARGS, "Get a configuration value"}, + {"get_config_prefix", ceph_config_get_prefix, METH_VARARGS, + "Get all configuration values with a given prefix"}, {"set_config", ceph_config_set, METH_VARARGS, "Set a configuration value"}, {"get_counter", get_counter, METH_VARARGS, diff --git a/ceph/src/mon/AuthMonitor.cc b/ceph/src/mon/AuthMonitor.cc index 48f334a00..e6473c5e4 100644 --- a/ceph/src/mon/AuthMonitor.cc +++ b/ceph/src/mon/AuthMonitor.cc @@ -17,6 +17,8 @@ #include "mon/AuthMonitor.h" #include "mon/Monitor.h" #include "mon/MonitorDBStore.h" +#include "mon/ConfigKeyService.h" +#include "mon/OSDMonitor.h" #include "messages/MMonCommand.h" #include "messages/MAuth.h" @@ -26,6 +28,7 @@ #include "auth/AuthServiceHandler.h" #include "auth/KeyRing.h" +#include "include/stringify.h" #include "include/assert.h" #define dout_subsys ceph_subsys_mon @@ -656,14 +659,344 @@ int AuthMonitor::import_keyring(KeyRing& keyring) dout(0) << "import: no caps supplied" << dendl; return -EINVAL; } - KeyServerData::Incremental auth_inc; - auth_inc.name = p->first; - auth_inc.auth = p->second; - auth_inc.op = KeyServerData::AUTH_INC_ADD; - dout(10) << " importing " << auth_inc.name << dendl; - dout(30) << " " << auth_inc.auth << dendl; - push_cephx_inc(auth_inc); + int err = add_entity(p->first, p->second); + assert(err == 0); + } + return 0; +} + +int AuthMonitor::remove_entity(const EntityName &entity) +{ + dout(10) << __func__ << " " << entity << dendl; + if (!mon->key_server.contains(entity)) + return -ENOENT; + + KeyServerData::Incremental auth_inc; + auth_inc.name = entity; + auth_inc.op = KeyServerData::AUTH_INC_DEL; + push_cephx_inc(auth_inc); + + return 0; +} + +bool AuthMonitor::entity_is_pending(EntityName& entity) +{ + // are we about to have it? + for (auto& p : pending_auth) { + if (p.inc_type == AUTH_DATA) { + KeyServerData::Incremental inc; + bufferlist::iterator q = p.auth_data.begin(); + ::decode(inc, q); + if (inc.op == KeyServerData::AUTH_INC_ADD && + inc.name == entity) { + return true; + } + } + } + return false; +} + +int AuthMonitor::exists_and_matches_entity( + const auth_entity_t& entity, + bool has_secret, + stringstream& ss) +{ + return exists_and_matches_entity(entity.name, entity.auth, + entity.auth.caps, has_secret, ss); +} + +int AuthMonitor::exists_and_matches_entity( + const EntityName& name, + const EntityAuth& auth, + const map& caps, + bool has_secret, + stringstream& ss) +{ + + dout(20) << __func__ << " entity " << name << " auth " << auth + << " caps " << caps << " has_secret " << has_secret << dendl; + + EntityAuth existing_auth; + // does entry already exist? + if (mon->key_server.get_auth(name, existing_auth)) { + // key match? + if (has_secret) { + if (existing_auth.key.get_secret().cmp(auth.key.get_secret())) { + ss << "entity " << name << " exists but key does not match"; + return -EEXIST; + } + } + + // caps match? + if (caps.size() != existing_auth.caps.size()) { + ss << "entity " << name << " exists but caps do not match"; + return -EINVAL; + } + for (auto& it : caps) { + if (existing_auth.caps.count(it.first) == 0 || + !existing_auth.caps[it.first].contents_equal(it.second)) { + ss << "entity " << name << " exists but cap " + << it.first << " does not match"; + return -EINVAL; + } + } + + // they match, no-op + return 0; + } + return -ENOENT; +} + +int AuthMonitor::add_entity( + const EntityName& name, + const EntityAuth& auth) +{ + + // okay, add it. + KeyServerData::Incremental auth_inc; + auth_inc.op = KeyServerData::AUTH_INC_ADD; + auth_inc.name = name; + auth_inc.auth = auth; + + dout(10) << " importing " << auth_inc.name << dendl; + dout(30) << " " << auth_inc.auth << dendl; + push_cephx_inc(auth_inc); + return 0; +} + +int AuthMonitor::validate_osd_destroy( + int32_t id, + const uuid_d& uuid, + EntityName& cephx_entity, + EntityName& lockbox_entity, + stringstream& ss) +{ + assert(paxos->is_plugged()); + + dout(10) << __func__ << " id " << id << " uuid " << uuid << dendl; + + string cephx_str = "osd." + stringify(id); + string lockbox_str = "client.osd-lockbox." + stringify(uuid); + + if (!cephx_entity.from_str(cephx_str)) { + dout(10) << __func__ << " invalid cephx entity '" + << cephx_str << "'" << dendl; + ss << "invalid cephx key entity '" << cephx_str << "'"; + return -EINVAL; + } + + if (!lockbox_entity.from_str(lockbox_str)) { + dout(10) << __func__ << " invalid lockbox entity '" + << lockbox_str << "'" << dendl; + ss << "invalid lockbox key entity '" << lockbox_str << "'"; + return -EINVAL; + } + + if (!mon->key_server.contains(cephx_entity) && + !mon->key_server.contains(lockbox_entity)) { + return -ENOENT; + } + + return 0; +} + +int AuthMonitor::do_osd_destroy( + const EntityName& cephx_entity, + const EntityName& lockbox_entity) +{ + assert(paxos->is_plugged()); + + dout(10) << __func__ << " cephx " << cephx_entity + << " lockbox " << lockbox_entity << dendl; + + bool removed = false; + + int err = remove_entity(cephx_entity); + if (err == -ENOENT) { + dout(10) << __func__ << " " << cephx_entity << " does not exist" << dendl; + } else { + removed = true; + } + + err = remove_entity(lockbox_entity); + if (err == -ENOENT) { + dout(10) << __func__ << " " << lockbox_entity << " does not exist" << dendl; + } else { + removed = true; + } + + if (!removed) { + dout(10) << __func__ << " entities do not exist -- no-op." << dendl; + return 0; + } + + // given we have paxos plugged, this will not result in a proposal + // being triggered, but it will still be needed so that we get our + // pending state encoded into the paxos' pending transaction. + propose_pending(); + return 0; +} + +bufferlist _encode_cap(const string& cap) +{ + bufferlist bl; + ::encode(cap, bl); + return bl; +} + +int _create_auth( + EntityAuth& auth, + const string& key, + const map& caps) +{ + if (key.empty()) + return -EINVAL; + try { + auth.key.decode_base64(key); + } catch (buffer::error& e) { + return -EINVAL; } + auth.caps = caps; + return 0; +} + +int AuthMonitor::validate_osd_new( + int32_t id, + const uuid_d& uuid, + const string& cephx_secret, + const string& lockbox_secret, + auth_entity_t& cephx_entity, + auth_entity_t& lockbox_entity, + stringstream& ss) +{ + + dout(10) << __func__ << " osd." << id << " uuid " << uuid << dendl; + + map cephx_caps = { + { "osd", _encode_cap("allow *") }, + { "mon", _encode_cap("allow profile osd") }, + { "mgr", _encode_cap("allow profile osd") } + }; + map lockbox_caps = { + { "mon", _encode_cap("allow command \"config-key get\" " + "with key=\"dm-crypt/osd/" + + stringify(uuid) + + "/luks\"") } + }; + + bool has_lockbox = !lockbox_secret.empty(); + + string cephx_name = "osd." + stringify(id); + string lockbox_name = "client.osd-lockbox." + stringify(uuid); + + if (!cephx_entity.name.from_str(cephx_name)) { + dout(10) << __func__ << " invalid cephx entity '" + << cephx_name << "'" << dendl; + ss << "invalid cephx key entity '" << cephx_name << "'"; + return -EINVAL; + } + + if (has_lockbox) { + if (!lockbox_entity.name.from_str(lockbox_name)) { + dout(10) << __func__ << " invalid cephx lockbox entity '" + << lockbox_name << "'" << dendl; + ss << "invalid cephx lockbox entity '" << lockbox_name << "'"; + return -EINVAL; + } + } + + if (entity_is_pending(cephx_entity.name) || + (has_lockbox && entity_is_pending(lockbox_entity.name))) { + // If we have pending entities for either the cephx secret or the + // lockbox secret, then our safest bet is to retry the command at + // a later time. These entities may be pending because an `osd new` + // command has been run (which is unlikely, due to the nature of + // the operation, which will force a paxos proposal), or (more likely) + // because a competing client created those entities before we handled + // the `osd new` command. Regardless, let's wait and see. + return -EAGAIN; + } + + if (!is_valid_cephx_key(cephx_secret)) { + ss << "invalid cephx secret."; + return -EINVAL; + } + + if (has_lockbox && !is_valid_cephx_key(lockbox_secret)) { + ss << "invalid cephx lockbox secret."; + return -EINVAL; + } + + int err = _create_auth(cephx_entity.auth, cephx_secret, cephx_caps); + assert(0 == err); + + bool cephx_is_idempotent = false, lockbox_is_idempotent = false; + err = exists_and_matches_entity(cephx_entity, true, ss); + + if (err != -ENOENT) { + if (err < 0) { + return err; + } + assert(0 == err); + cephx_is_idempotent = true; + } + + if (has_lockbox) { + err = _create_auth(lockbox_entity.auth, lockbox_secret, lockbox_caps); + assert(err == 0); + err = exists_and_matches_entity(lockbox_entity, true, ss); + if (err != -ENOENT) { + if (err < 0) { + return err; + } + assert(0 == err); + lockbox_is_idempotent = true; + } + } + + if (cephx_is_idempotent && (!has_lockbox || lockbox_is_idempotent)) { + return EEXIST; + } + + return 0; +} + +int AuthMonitor::do_osd_new( + const auth_entity_t& cephx_entity, + const auth_entity_t& lockbox_entity, + bool has_lockbox) +{ + assert(paxos->is_plugged()); + + dout(10) << __func__ << " cephx " << cephx_entity.name + << " lockbox "; + if (has_lockbox) { + *_dout << lockbox_entity.name; + } else { + *_dout << "n/a"; + } + *_dout << dendl; + + // we must have validated before reaching this point. + // if keys exist, then this means they also match; otherwise we would + // have failed before calling this function. + bool cephx_exists = mon->key_server.contains(cephx_entity.name); + + if (!cephx_exists) { + int err = add_entity(cephx_entity.name, cephx_entity.auth); + assert(0 == err); + } + + if (has_lockbox && + !mon->key_server.contains(lockbox_entity.name)) { + int err = add_entity(lockbox_entity.name, lockbox_entity.auth); + assert(0 == err); + } + + // given we have paxos plugged, this will not result in a proposal + // being triggered, but it will still be needed so that we get our + // pending state encoded into the paxos' pending transaction. + propose_pending(); return 0; } @@ -769,20 +1102,10 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op) } // are we about to have it? - for (vector::iterator p = pending_auth.begin(); - p != pending_auth.end(); - ++p) { - if (p->inc_type == AUTH_DATA) { - KeyServerData::Incremental inc; - bufferlist::iterator q = p->auth_data.begin(); - ::decode(inc, q); - if (inc.op == KeyServerData::AUTH_INC_ADD && - inc.name == entity) { - wait_for_finished_proposal(op, - new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); - return true; - } - } + if (entity_is_pending(entity)) { + wait_for_finished_proposal(op, + new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); + return true; } // build new caps from provided arguments (if available) @@ -814,53 +1137,31 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op) } } - // does entry already exist? - if (mon->key_server.get_auth(auth_inc.name, auth_inc.auth)) { - // key match? - if (has_keyring) { - if (auth_inc.auth.key.get_secret().cmp(new_inc.key.get_secret())) { - ss << "entity " << auth_inc.name << " exists but key does not match"; - err = -EINVAL; - goto done; - } - } - - // caps match? - if (new_caps.size() != auth_inc.auth.caps.size()) { - ss << "entity " << auth_inc.name << " exists but caps do not match"; - err = -EINVAL; - goto done; - } - for (map::iterator it = new_caps.begin(); - it != new_caps.end(); ++it) { - if (auth_inc.auth.caps.count(it->first) == 0 || - !auth_inc.auth.caps[it->first].contents_equal(it->second)) { - ss << "entity " << auth_inc.name << " exists but cap " - << it->first << " does not match"; - err = -EINVAL; - goto done; - } + err = exists_and_matches_entity(auth_inc.name, new_inc, + new_caps, has_keyring, ss); + // if entity/key/caps do not exist in the keyring, just fall through + // and add the entity; otherwise, make sure everything matches (in + // which case it's a no-op), because if not we must fail. + if (err != -ENOENT) { + if (err < 0) { + goto done; } - - // they match, no-op - err = 0; + // no-op. + assert(err == 0); goto done; } + err = 0; // okay, add it. - auth_inc.op = KeyServerData::AUTH_INC_ADD; - auth_inc.auth.caps = new_caps; - if (has_keyring) { - auth_inc.auth.key = new_inc.key; - } else { + if (!has_keyring) { dout(10) << "AuthMonitor::prepare_command generating random key for " - << auth_inc.name << dendl; - auth_inc.auth.key.create(g_ceph_context, CEPH_CRYPTO_AES); + << auth_inc.name << dendl; + new_inc.key.create(g_ceph_context, CEPH_CRYPTO_AES); } + new_inc.caps = new_caps; - dout(10) << " importing " << auth_inc.name << dendl; - dout(30) << " " << auth_inc.auth << dendl; - push_cephx_inc(auth_inc); + err = add_entity(auth_inc.name, new_inc); + assert(err == 0); ss << "added key for " << auth_inc.name; getline(ss, rs); @@ -1015,7 +1316,6 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op) get_last_committed() + 1)); return true; } - done: rdata.append(ds); getline(ss, rs, '\0'); diff --git a/ceph/src/mon/AuthMonitor.h b/ceph/src/mon/AuthMonitor.h index edeb12a3e..18b847d64 100644 --- a/ceph/src/mon/AuthMonitor.h +++ b/ceph/src/mon/AuthMonitor.h @@ -103,6 +103,12 @@ public: } }; + struct auth_entity_t { + EntityName name; + EntityAuth auth; + }; + + private: vector pending_auth; version_t last_rotating_ver; @@ -158,6 +164,23 @@ private: bool prepare_command(MonOpRequestRef op); bool check_rotate(); + + bool entity_is_pending(EntityName& entity); + int exists_and_matches_entity( + const auth_entity_t& entity, + bool has_secret, + stringstream& ss); + int exists_and_matches_entity( + const EntityName& name, + const EntityAuth& auth, + const map& caps, + bool has_secret, + stringstream& ss); + int remove_entity(const EntityName &entity); + int add_entity( + const EntityName& name, + const EntityAuth& auth); + public: AuthMonitor(Monitor *mn, Paxos *p, const string& service_name) : PaxosService(mn, p, service_name), @@ -167,10 +190,45 @@ private: {} void pre_auth(MAuth *m); - + void tick() override; // check state, take actions + int validate_osd_destroy( + int32_t id, + const uuid_d& uuid, + EntityName& cephx_entity, + EntityName& lockbox_entity, + stringstream& ss); + int do_osd_destroy( + const EntityName& cephx_entity, + const EntityName& lockbox_entity); + + int do_osd_new( + const auth_entity_t& cephx_entity, + const auth_entity_t& lockbox_entity, + bool has_lockbox); + int validate_osd_new( + int32_t id, + const uuid_d& uuid, + const string& cephx_secret, + const string& lockbox_secret, + auth_entity_t& cephx_entity, + auth_entity_t& lockbox_entity, + stringstream& ss); + void dump_info(Formatter *f); + + bool is_valid_cephx_key(const string& k) { + if (k.empty()) + return false; + + EntityAuth ea; + try { + ea.key.decode_base64(k); + return true; + } catch (buffer::error& e) { /* fallthrough */ } + return false; + } }; diff --git a/ceph/src/mon/CMakeLists.txt b/ceph/src/mon/CMakeLists.txt index dbd9bd034..9e40ef588 100644 --- a/ceph/src/mon/CMakeLists.txt +++ b/ceph/src/mon/CMakeLists.txt @@ -1,7 +1,3 @@ -set(osd_mon_files - Monitor.cc) -add_library(osd_mon_objs OBJECT ${osd_mon_files}) - set(lib_mon_srcs ${CMAKE_SOURCE_DIR}/src/auth/cephx/CephxKeyServer.cc ${CMAKE_SOURCE_DIR}/src/auth/cephx/CephxServiceHandler.cc @@ -13,6 +9,8 @@ set(lib_mon_srcs MDSMonitor.cc FSCommands.cc MgrMonitor.cc + MgrStatMonitor.cc + Monitor.cc MonmapMonitor.cc LogMonitor.cc AuthMonitor.cc @@ -22,7 +20,8 @@ set(lib_mon_srcs PGMonitor.cc PGMap.cc ConfigKeyService.cc) -add_library(mon STATIC ${lib_mon_srcs} $ - $ $ - $ $) +add_library(mon STATIC + ${lib_mon_srcs} + $ + $) target_link_libraries(mon ${ALLOC_LIBS}) diff --git a/ceph/src/mon/ConfigKeyService.cc b/ceph/src/mon/ConfigKeyService.cc index f685daa05..3adba6dd0 100644 --- a/ceph/src/mon/ConfigKeyService.cc +++ b/ceph/src/mon/ConfigKeyService.cc @@ -19,7 +19,9 @@ #include "mon/Monitor.h" #include "mon/ConfigKeyService.h" #include "mon/MonitorDBStore.h" +#include "mon/OSDMonitor.h" #include "common/errno.h" +#include "include/stringify.h" #define dout_subsys ceph_subsys_mon #undef dout_prefix @@ -55,12 +57,19 @@ void ConfigKeyService::store_put(const string &key, bufferlist &bl, Context *cb) void ConfigKeyService::store_delete(const string &key, Context *cb) { MonitorDBStore::TransactionRef t = paxos->get_pending_transaction(); - t->erase(STORE_PREFIX, key); + store_delete(t, key); if (cb) paxos->queue_pending_finisher(cb); paxos->trigger_propose(); } +void ConfigKeyService::store_delete( + MonitorDBStore::TransactionRef t, + const string &key) +{ + t->erase(STORE_PREFIX, key); +} + bool ConfigKeyService::store_exists(const string &key) { return mon->store->exists(STORE_PREFIX, key); @@ -83,6 +92,22 @@ void ConfigKeyService::store_list(stringstream &ss) f.flush(ss); } +bool ConfigKeyService::store_has_prefix(const string &prefix) +{ + KeyValueDB::Iterator iter = + mon->store->get_iterator(STORE_PREFIX); + + while (iter->valid()) { + string key(iter->key()); + size_t p = key.find(prefix); + if (p != string::npos && p == 0) { + return true; + } + iter->next(); + } + return false; +} + void ConfigKeyService::store_dump(stringstream &ss) { KeyValueDB::Iterator iter = @@ -99,6 +124,24 @@ void ConfigKeyService::store_dump(stringstream &ss) f.flush(ss); } +void ConfigKeyService::store_delete_prefix( + MonitorDBStore::TransactionRef t, + const string &prefix) +{ + KeyValueDB::Iterator iter = + mon->store->get_iterator(STORE_PREFIX); + + while (iter->valid()) { + string key(iter->key()); + + size_t p = key.find(prefix); + if (p != string::npos && p == 0) { + store_delete(t, key); + } + iter->next(); + } +} + bool ConfigKeyService::service_dispatch(MonOpRequestRef op) { Message *m = op->get_req(); @@ -165,8 +208,9 @@ bool ConfigKeyService::service_dispatch(MonOpRequestRef op) goto out; } // we'll reply to the message once the proposal has been handled + ss << "set " << key; store_put(key, data, - new Monitor::C_Command(mon, op, 0, "value stored", 0)); + new Monitor::C_Command(mon, op, 0, ss.str(), 0)); // return for now; we'll put the message once it's done. return true; @@ -208,6 +252,7 @@ bool ConfigKeyService::service_dispatch(MonOpRequestRef op) store_dump(tmp_ss); rdata.append(tmp_ss); ret = 0; + } out: @@ -219,3 +264,76 @@ out: return (ret == 0); } +string _get_dmcrypt_prefix(const uuid_d& uuid, const string k) +{ + return "dm-crypt/osd/" + stringify(uuid) + "/" + k; +} + +int ConfigKeyService::validate_osd_destroy( + const int32_t id, + const uuid_d& uuid) +{ + string dmcrypt_prefix = _get_dmcrypt_prefix(uuid, ""); + string daemon_prefix = + "daemon-private/osd." + stringify(id) + "/"; + + if (!store_has_prefix(dmcrypt_prefix) && + !store_has_prefix(daemon_prefix)) { + return -ENOENT; + } + return 0; +} + +void ConfigKeyService::do_osd_destroy(int32_t id, uuid_d& uuid) +{ + string dmcrypt_prefix = _get_dmcrypt_prefix(uuid, ""); + string daemon_prefix = + "daemon-private/osd." + stringify(id) + "/"; + + MonitorDBStore::TransactionRef t = paxos->get_pending_transaction(); + for (auto p : { dmcrypt_prefix, daemon_prefix }) { + store_delete_prefix(t, p); + } + + paxos->trigger_propose(); +} + +int ConfigKeyService::validate_osd_new( + const uuid_d& uuid, + const string& dmcrypt_key, + stringstream& ss) +{ + string dmcrypt_prefix = _get_dmcrypt_prefix(uuid, "luks"); + bufferlist value; + value.append(dmcrypt_key); + + if (store_exists(dmcrypt_prefix)) { + bufferlist existing_value; + int err = store_get(dmcrypt_prefix, existing_value); + if (err < 0) { + dout(10) << __func__ << " unable to get dm-crypt key from store (r = " + << err << ")" << dendl; + return err; + } + if (existing_value.contents_equal(value)) { + // both values match; this will be an idempotent op. + return EEXIST; + } + ss << "dm-crypt key already exists and does not match"; + return -EEXIST; + } + return 0; +} + +void ConfigKeyService::do_osd_new( + const uuid_d& uuid, + const string& dmcrypt_key) +{ + assert(paxos->is_plugged()); + + string dmcrypt_key_prefix = _get_dmcrypt_prefix(uuid, "luks"); + bufferlist dmcrypt_key_value; + dmcrypt_key_value.append(dmcrypt_key); + // store_put() will call trigger_propose + store_put(dmcrypt_key_prefix, dmcrypt_key_value, nullptr); +} diff --git a/ceph/src/mon/ConfigKeyService.h b/ceph/src/mon/ConfigKeyService.h index 34c70342a..997796873 100644 --- a/ceph/src/mon/ConfigKeyService.h +++ b/ceph/src/mon/ConfigKeyService.h @@ -15,6 +15,7 @@ #define CEPH_MON_CONFIG_KEY_SERVICE_H #include "mon/QuorumService.h" +#include "mon/MonitorDBStore.h" class Paxos; class Monitor; @@ -28,10 +29,15 @@ class ConfigKeyService : public QuorumService int store_get(const string &key, bufferlist &bl); void store_put(const string &key, bufferlist &bl, Context *cb = NULL); + void store_delete(MonitorDBStore::TransactionRef t, const string &key); void store_delete(const string &key, Context *cb = NULL); + void store_delete_prefix( + MonitorDBStore::TransactionRef t, + const string &prefix); void store_list(stringstream &ss); void store_dump(stringstream &ss); bool store_exists(const string &key); + bool store_has_prefix(const string &prefix); static const string STORE_PREFIX; @@ -61,6 +67,14 @@ public: void cleanup() override { } void service_tick() override { } + int validate_osd_destroy(const int32_t id, const uuid_d& uuid); + void do_osd_destroy(int32_t id, uuid_d& uuid); + int validate_osd_new( + const uuid_d& uuid, + const string& dmcrypt_key, + stringstream& ss); + void do_osd_new(const uuid_d& uuid, const string& dmcrypt_key); + int get_type() override { return QuorumService::SERVICE_CONFIG_KEY; } diff --git a/ceph/src/mon/CreatingPGs.h b/ceph/src/mon/CreatingPGs.h index 7c909a5de..4ba91575f 100644 --- a/ceph/src/mon/CreatingPGs.h +++ b/ceph/src/mon/CreatingPGs.h @@ -9,25 +9,79 @@ struct creating_pgs_t { epoch_t last_scan_epoch = 0; + + /// pgs we are currently creating std::map > pgs; + + struct create_info { + epoch_t created; + utime_t modified; + uint64_t start = 0; + uint64_t end = 0; + bool done() const { + return start >= end; + } + void encode(bufferlist& bl) const { + ::encode(created, bl); + ::encode(modified, bl); + ::encode(start, bl); + ::encode(end, bl); + } + void decode(bufferlist::iterator& p) { + ::decode(created, p); + ::decode(modified, p); + ::decode(start, p); + ::decode(end, p); + } + }; + + /// queue of pgs we still need to create (poolid -> ) + map queue; + + /// pools that exist in the osdmap for which at least one pg has been created std::set created_pools; + + bool create_pool(int64_t poolid, uint32_t pg_num, + epoch_t created, utime_t modified) { + if (created_pools.count(poolid) == 0) { + auto& c = queue[poolid]; + c.created = created; + c.modified = modified; + c.end = pg_num; + created_pools.insert(poolid); + return true; + } else { + return false; + } + } + unsigned remove_pool(int64_t removed_pool) { + const unsigned total = pgs.size(); + auto first = pgs.lower_bound(pg_t{0, (uint64_t)removed_pool}); + auto last = pgs.lower_bound(pg_t{0, (uint64_t)removed_pool + 1}); + pgs.erase(first, last); + created_pools.erase(removed_pool); + return total - pgs.size(); + } void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); ::encode(last_scan_epoch, bl); ::encode(pgs, bl); ::encode(created_pools, bl); + ::encode(queue, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); ::decode(last_scan_epoch, bl); ::decode(pgs, bl); ::decode(created_pools, bl); + if (struct_v >= 2) + ::decode(queue, bl); DECODE_FINISH(bl); } void dump(ceph::Formatter *f) const { - f->open_object_section("creating_pgs"); f->dump_unsigned("last_scan_epoch", last_scan_epoch); + f->open_array_section("creating_pgs"); for (auto& pg : pgs) { f->open_object_section("pg"); f->dump_stream("pgid") << pg.first; @@ -36,6 +90,17 @@ struct creating_pgs_t { f->close_section(); } f->close_section(); + f->open_array_section("queue"); + for (auto& p : queue) { + f->open_object_section("pool"); + f->dump_unsigned("pool", p.first); + f->dump_unsigned("created", p.second.created); + f->dump_stream("modified") << p.second.modified; + f->dump_unsigned("ps_start", p.second.start); + f->dump_unsigned("ps_end", p.second.end); + f->close_section(); + } + f->close_section(); f->open_array_section("created_pools"); for (auto pool : created_pools) { f->dump_unsigned("pool", pool); @@ -56,4 +121,5 @@ struct creating_pgs_t { o.push_back(c); } }; +WRITE_CLASS_ENCODER(creating_pgs_t::create_info); WRITE_CLASS_ENCODER(creating_pgs_t); diff --git a/ceph/src/mon/FSCommands.cc b/ceph/src/mon/FSCommands.cc index 630736c39..abdea4333 100644 --- a/ceph/src/mon/FSCommands.cc +++ b/ceph/src/mon/FSCommands.cc @@ -90,7 +90,7 @@ class FsNewHandler : public FileSystemCommandHandler FSMap &fsmap, MonOpRequestRef op, map &cmdmap, - std::stringstream &ss) + std::stringstream &ss) override { string metadata_name; cmd_getval(g_ceph_context, cmdmap, "metadata", metadata_name); @@ -102,11 +102,14 @@ class FsNewHandler : public FileSystemCommandHandler string force; cmd_getval(g_ceph_context,cmdmap, "force", force); - int64_t metadata_num_objects = mon->pgmon()->pg_map.pg_pool_sum[metadata].stats.sum.num_objects; - if (force != "--force" && metadata_num_objects > 0) { - ss << "pool '" << metadata_name - << "' already contains some objects. Use an empty pool instead."; - return -EINVAL; + const pool_stat_t *stat = mon->pgservice->get_pool_stat(metadata); + if (stat) { + int64_t metadata_num_objects = stat->stats.sum.num_objects; + if (force != "--force" && metadata_num_objects > 0) { + ss << "pool '" << metadata_name + << "' already contains some objects. Use an empty pool instead."; + return -EINVAL; + } } string data_name; @@ -152,9 +155,9 @@ class FsNewHandler : public FileSystemCommandHandler } for (auto fs : fsmap.get_filesystems()) { - const set& data_pools = fs->mds_map.get_data_pools(); + const std::vector &data_pools = fs->mds_map.get_data_pools(); string sure; - if ((data_pools.find(data) != data_pools.end() + if ((std::find(data_pools.begin(), data_pools.end(), data) != data_pools.end() || fs->mds_map.get_metadata_pool() == metadata) && ((!cmd_getval(g_ceph_context, cmdmap, "sure", sure) || sure != "--allow-dangerous-metadata-overlay"))) { @@ -295,10 +298,14 @@ public: }); } } else if (var == "balancer") { - ss << "setting the metadata load balancer to " << val; - fsmap.modify_filesystem( - fs->fscid, - [val](std::shared_ptr fs) + if (val.empty()) { + ss << "unsetting the metadata load balancer"; + } else { + ss << "setting the metadata load balancer to " << val; + } + fsmap.modify_filesystem( + fs->fscid, + [val](std::shared_ptr fs) { fs->mds_map.set_balancer(val); }); @@ -488,6 +495,12 @@ class AddDataPoolHandler : public FileSystemCommandHandler return r; } + // no-op when the data_pool already on fs + if (fs->mds_map.is_data_pool(poolid)) { + ss << "data pool " << poolid << " is already on fs " << fs_name; + return 0; + } + fsmap.modify_filesystem( fs->fscid, [poolid](std::shared_ptr fs) diff --git a/ceph/src/mon/LogMonitor.cc b/ceph/src/mon/LogMonitor.cc index c8e746377..cc5fd6bcb 100644 --- a/ceph/src/mon/LogMonitor.cc +++ b/ceph/src/mon/LogMonitor.cc @@ -63,6 +63,7 @@ void LogMonitor::create_initial() dout(10) << "create_initial -- creating initial map" << dendl; LogEntry e; memset(&e.who, 0, sizeof(e.who)); + e.name = g_conf->name; e.stamp = ceph_clock_now(); e.prio = CLOG_INFO; std::stringstream ss; @@ -164,6 +165,7 @@ void LogMonitor::update_from_paxos(bool *need_bootstrap) } summary.version++; + summary.prune(g_conf->mon_log_max_summary); } dout(15) << __func__ << " logging for " @@ -344,6 +346,7 @@ bool LogMonitor::prepare_log(MonOpRequestRef op) pending_log.insert(pair(p->stamp, *p)); } } + pending_summary.prune(g_conf->mon_log_max_summary); wait_for_finished_proposal(op, new C_Log(this, op)); return true; } @@ -370,17 +373,64 @@ bool LogMonitor::should_propose(double& delay) bool LogMonitor::preprocess_command(MonOpRequestRef op) { op->mark_logmon_event("preprocess_command"); - int r = -1; + MMonCommand *m = static_cast(op->get_req()); + int r = -EINVAL; bufferlist rdata; stringstream ss; - if (r != -1) { - string rs; - getline(ss, rs); - mon->reply_command(op, r, rs, rdata, get_last_committed()); + map cmdmap; + if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) { + string rs = ss.str(); + mon->reply_command(op, -EINVAL, rs, get_last_committed()); return true; - } else + } + MonSession *session = m->get_session(); + if (!session) { + mon->reply_command(op, -EACCES, "access denied", get_last_committed()); + return true; + } + + string prefix; + cmd_getval(g_ceph_context, cmdmap, "prefix", prefix); + + string format; + cmd_getval(g_ceph_context, cmdmap, "format", format, string("plain")); + boost::scoped_ptr f(Formatter::create(format)); + + if (prefix == "log last") { + int64_t num = 20; + cmd_getval(g_ceph_context, cmdmap, "num", num); + if (f) { + f->open_array_section("tail"); + } + auto p = summary.tail.end(); + while (num > 0 && p != summary.tail.begin()) { + num--; + --p; + } + ostringstream ss; + for ( ; p != summary.tail.end(); ++p) { + if (f) { + f->dump_object("entry", *p); + } else { + ss << *p << "\n"; + } + } + if (f) { + f->close_section(); + f->flush(rdata); + } else { + rdata.append(ss.str()); + } + r = 0; + } else { return false; + } + + string rs; + getline(ss, rs); + mon->reply_command(op, r, rs, rdata, get_last_committed()); + return true; } @@ -414,11 +464,13 @@ bool LogMonitor::prepare_command(MonOpRequestRef op) cmd_getval(g_ceph_context, cmdmap, "logtext", logtext); LogEntry le; le.who = m->get_orig_source_inst(); + le.name = session->entity_name; le.stamp = m->get_recv_stamp(); le.seq = 0; le.prio = CLOG_INFO; le.msg = str_join(logtext, " "); pending_summary.add(le); + pending_summary.prune(g_conf->mon_log_max_summary); pending_log.insert(pair(le.stamp, le)); wait_for_finished_proposal(op, new Monitor::C_Command( mon, op, 0, string(), get_last_committed() + 1)); diff --git a/ceph/src/mon/MDSMonitor.cc b/ceph/src/mon/MDSMonitor.cc index 16e455295..608e1aeed 100644 --- a/ceph/src/mon/MDSMonitor.cc +++ b/ceph/src/mon/MDSMonitor.cc @@ -53,19 +53,19 @@ static ostream& _prefix(std::ostream *_dout, Monitor *mon, FSMap const& fsmap) { * out strongly-typedef'd types */ template<> bool cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, - std::string k, mds_gid_t &val) + const std::string& k, mds_gid_t &val) { return cmd_getval(cct, cmdmap, k, (int64_t&)val); } template<> bool cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, - std::string k, mds_rank_t &val) + const std::string& k, mds_rank_t &val) { return cmd_getval(cct, cmdmap, k, (int64_t&)val); } template<> bool cmd_getval(CephContext *cct, const cmdmap_t& cmdmap, - std::string k, MDSMap::DaemonState &val) + const std::string& k, MDSMap::DaemonState &val) { return cmd_getval(cct, cmdmap, k, (int64_t&)val); } @@ -503,6 +503,7 @@ bool MDSMonitor::prepare_beacon(MonOpRequestRef op) mon->osdmon()->wait_for_writeable(op, new C_RetryMessage(this, op)); return false; } + mon->clog->info() << "MDS daemon '" << m->get_name() << "' restarted"; fail_mds_gid(existing); failed_mds = true; } @@ -969,6 +970,20 @@ bool MDSMonitor::preprocess_command(MonOpRequestRef op) f->close_section(); } f->flush(ds); + } else if (prefix == "mds versions") { + if (!f) + f.reset(Formatter::create("json-pretty")); + count_metadata("ceph_version", f.get()); + f->flush(ds); + r = 0; + } else if (prefix == "mds count-metadata") { + if (!f) + f.reset(Formatter::create("json-pretty")); + string field; + cmd_getval(g_ceph_context, cmdmap, "property", field); + count_metadata(field, f.get()); + f->flush(ds); + r = 0; } else if (prefix == "mds getmap") { epoch_t e; int64_t epocharg; @@ -1071,9 +1086,8 @@ bool MDSMonitor::preprocess_command(MonOpRequestRef op) ds << "name: " << mds_map.fs_name << ", metadata pool: " << md_pool_name << ", data pools: ["; - for (std::set::iterator dpi = mds_map.data_pools.begin(); - dpi != mds_map.data_pools.end(); ++dpi) { - const string &pool_name = mon->osdmon()->osdmap.get_pool_name(*dpi); + for (auto dpi : mds_map.data_pools) { + const string &pool_name = mon->osdmon()->osdmap.get_pool_name(dpi); ds << pool_name << " "; } ds << "]" << std::endl; @@ -1120,13 +1134,15 @@ bool MDSMonitor::fail_mds_gid(mds_gid_t gid) mds_gid_t MDSMonitor::gid_from_arg(const std::string& arg, std::ostream &ss) { + const FSMap *relevant_fsmap = mon->is_leader() ? &pending_fsmap : &fsmap; + // Try parsing as a role mds_role_t role; std::ostringstream ignore_err; // Don't spam 'ss' with parse_role errors int r = parse_role(arg, &role, ignore_err); if (r == 0) { // See if a GID is assigned to this role - auto fs = pending_fsmap.get_filesystem(role.fscid); + auto fs = relevant_fsmap->get_filesystem(role.fscid); assert(fs != nullptr); // parse_role ensures it exists if (fs->mds_map.is_up(role.rank)) { dout(10) << __func__ << ": validated rank/GID " << role @@ -1140,7 +1156,7 @@ mds_gid_t MDSMonitor::gid_from_arg(const std::string& arg, std::ostream &ss) unsigned long long maybe_gid = strict_strtoll(arg.c_str(), 10, &err); if (!err.empty()) { // Not a role or a GID, try as a daemon name - const MDSMap::mds_info_t *mds_info = fsmap.find_by_name(arg); + const MDSMap::mds_info_t *mds_info = relevant_fsmap->find_by_name(arg); if (!mds_info) { ss << "MDS named '" << arg << "' does not exist, or is not up"; @@ -1153,14 +1169,9 @@ mds_gid_t MDSMonitor::gid_from_arg(const std::string& arg, std::ostream &ss) // Not a role, but parses as a an integer, might be a GID dout(10) << __func__ << ": treating MDS reference '" << arg << "' as an integer " << maybe_gid << dendl; - if (mon->is_leader()) { - if (pending_fsmap.gid_exists(mds_gid_t(maybe_gid))) { - return mds_gid_t(maybe_gid); - } - } else { - if (fsmap.gid_exists(mds_gid_t(maybe_gid))) { - return mds_gid_t(maybe_gid); - } + + if (relevant_fsmap->gid_exists(mds_gid_t(maybe_gid))) { + return mds_gid_t(maybe_gid); } } @@ -1328,6 +1339,10 @@ int MDSMonitor::filesystem_command( ss << "can't tell the root (" << fs->mds_map.get_root() << ") or tableserver (" << fs->mds_map.get_tableserver() << ") to deactivate"; + } else if (role.rank != fs->mds_map.get_last_in_mds()) { + r = -EINVAL; + ss << "mds." << role << " doesn't have the max rank (" + << fs->mds_map.get_last_in_mds() << ")"; } else if (fs->mds_map.get_num_in_mds() <= size_t(fs->mds_map.get_max_mds())) { r = -EBUSY; ss << "must decrease max_mds or else MDS will immediately reactivate"; @@ -1774,6 +1789,26 @@ int MDSMonitor::load_metadata(map& m) return 0; } +void MDSMonitor::count_metadata(const string& field, Formatter *f) +{ + map by_val; + map meta; + load_metadata(meta); + for (auto& p : meta) { + auto q = p.second.find(field); + if (q == p.second.end()) { + by_val["unknown"]++; + } else { + by_val[q->second]++; + } + } + f->open_object_section(field.c_str()); + for (auto& p : by_val) { + f->dump_int(p.first.c_str(), p.second); + } + f->close_section(); +} + int MDSMonitor::dump_metadata(const std::string &who, Formatter *f, ostream& err) { assert(f); @@ -1886,12 +1921,24 @@ void MDSMonitor::maybe_replace_gid(mds_gid_t gid, << " " << ceph_mds_state_name(info.state) << " since " << beacon.stamp << dendl; + // We will only take decisive action (replacing/removing a daemon) + // if we have some indicating that some other daemon(s) are successfully + // getting beacons through recently. + utime_t latest_beacon; + for (const auto & i : last_beacon) { + latest_beacon = MAX(i.second.stamp, latest_beacon); + } + const bool may_replace = latest_beacon > + (ceph_clock_now() - + MAX(g_conf->mds_beacon_interval, g_conf->mds_beacon_grace * 0.5)); + // are we in? // and is there a non-laggy standby that can take over for us? mds_gid_t sgid; if (info.rank >= 0 && info.state != MDSMap::STATE_STANDBY && info.state != MDSMap::STATE_STANDBY_REPLAY && + may_replace && !pending_fsmap.get_filesystem(fscid)->mds_map.test_flag(CEPH_MDSMAP_DOWN) && (sgid = pending_fsmap.find_replacement_for({fscid, info.rank}, info.name, g_conf->mon_force_standby_active)) != MDS_GID_NONE) @@ -1903,6 +1950,11 @@ void MDSMonitor::maybe_replace_gid(mds_gid_t gid, << " " << ceph_mds_state_name(info.state) << " with " << sgid << "/" << si.name << " " << si.addr << dendl; + mon->clog->warn() << "MDS daemon '" << info.name << "'" + << " is not responding, replacing it " + << "as rank " << info.rank + << " with standby '" << si.name << "'"; + // Remember what NS the old one was in const fs_cluster_id_t fscid = pending_fsmap.mds_roles.at(gid); @@ -1914,11 +1966,14 @@ void MDSMonitor::maybe_replace_gid(mds_gid_t gid, pending_fsmap.promote(sgid, fs, info.rank); *mds_propose = true; - } else if (info.state == MDSMap::STATE_STANDBY_REPLAY || - info.state == MDSMap::STATE_STANDBY) { + } else if ((info.state == MDSMap::STATE_STANDBY_REPLAY || + info.state == MDSMap::STATE_STANDBY) && may_replace) { dout(10) << " failing and removing " << gid << " " << info.addr << " mds." << info.rank << "." << info.inc << " " << ceph_mds_state_name(info.state) << dendl; + mon->clog->info() << "MDS standby '" << info.name + << "' is not responding, removing it from the set of " + << "standbys"; fail_mds_gid(gid); *mds_propose = true; } else if (!info.laggy()) { diff --git a/ceph/src/mon/MDSMonitor.h b/ceph/src/mon/MDSMonitor.h index 39cbeebfc..05946b51c 100644 --- a/ceph/src/mon/MDSMonitor.h +++ b/ceph/src/mon/MDSMonitor.h @@ -135,10 +135,10 @@ class MDSMonitor : public PaxosService { int dump_metadata(const string& who, Formatter *f, ostream& err); - MDSMap *generate_mds_map(fs_cluster_id_t fscid); void update_metadata(mds_gid_t gid, const Metadata& metadata); void remove_from_metadata(MonitorDBStore::TransactionRef t); int load_metadata(map& m); + void count_metadata(const string& field, Formatter *f); // MDS daemon GID to latest health state from that GID std::map pending_daemon_health; diff --git a/ceph/src/mon/MgrMap.h b/ceph/src/mon/MgrMap.h index e522ab4ba..5a7d33397 100644 --- a/ceph/src/mon/MgrMap.h +++ b/ceph/src/mon/MgrMap.h @@ -126,17 +126,18 @@ public: dump(f); } else { if (get_active_gid() != 0) { - *ss << "active: " << get_active_name(); + *ss << get_active_name(); if (!available) { // If the daemon hasn't gone active yet, indicate that. - *ss << "(starting)"; + *ss << "(active, starting)"; + } else { + *ss << "(active)"; } - *ss << " "; } else { - *ss << "no daemons active "; + *ss << "no daemons active"; } if (standbys.size()) { - *ss << "standbys: "; + *ss << ", standbys: "; bool first = true; for (const auto &i : standbys) { if (!first) { diff --git a/ceph/src/mon/MgrMonitor.cc b/ceph/src/mon/MgrMonitor.cc index b36da2fce..863672afe 100644 --- a/ceph/src/mon/MgrMonitor.cc +++ b/ceph/src/mon/MgrMonitor.cc @@ -15,8 +15,7 @@ #include "messages/MMgrMap.h" #include "messages/MMgrDigest.h" -#include "PGMap.h" -#include "PGMonitor.h" +#include "PGStatService.h" #include "include/stringify.h" #include "mgr/MgrContext.h" #include "OSDMonitor.h" @@ -33,6 +32,7 @@ static ostream& _prefix(std::ostream *_dout, Monitor *mon, << ").mgr e" << mgrmap.get_epoch() << " "; } + void MgrMonitor::create_initial() { } @@ -187,7 +187,7 @@ bool MgrMonitor::prepare_beacon(MonOpRequestRef op) } } - last_beacon[m->get_gid()] = ceph_clock_now(); + last_beacon[m->get_gid()] = ceph::coarse_mono_clock::now(); // Track whether we modified pending_map bool updated = false; @@ -263,7 +263,7 @@ void MgrMonitor::check_sub(Subscription *sub) } } else { assert(sub->type == "mgrdigest"); - if (digest_callback == nullptr) { + if (digest_event == nullptr) { send_digests(); } } @@ -275,7 +275,11 @@ void MgrMonitor::check_sub(Subscription *sub) */ void MgrMonitor::send_digests() { - digest_callback = nullptr; + cancel_timer(); + + if (!is_active()) { + return; + } const std::string type = "mgrdigest"; if (mon->session_map.subs.count(type) == 0) @@ -298,10 +302,18 @@ void MgrMonitor::send_digests() sub->session->con->send_message(mdigest); } - digest_callback = new C_MonContext(mon, [this](int){ + digest_event = new C_MonContext(mon, [this](int){ send_digests(); }); - mon->timer.add_event_after(g_conf->mon_mgr_digest_period, digest_callback); + mon->timer.add_event_after(g_conf->mon_mgr_digest_period, digest_event); +} + +void MgrMonitor::cancel_timer() +{ + if (digest_event) { + mon->timer.cancel_event(digest_event); + digest_event = nullptr; + } } void MgrMonitor::on_active() @@ -329,7 +341,7 @@ void MgrMonitor::get_health( if (!map.available) { auto level = HEALTH_WARN; // do not escalate to ERR if they are still upgrading to jewel. - if (mon->osdmon()->osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { utime_t now = ceph_clock_now(); if (first_seen_inactive != utime_t() && now - first_seen_inactive > g_conf->mon_mgr_inactive_grace) { @@ -345,9 +357,8 @@ void MgrMonitor::tick() if (!is_active() || !mon->is_leader()) return; - const utime_t now = ceph_clock_now(); - utime_t cutoff = now; - cutoff -= g_conf->mon_mgr_beacon_grace; + const auto now = ceph::coarse_mono_clock::now(); + const auto cutoff = now - std::chrono::seconds(g_conf->mon_mgr_beacon_grace); // Populate any missing beacons (i.e. no beacon since MgrMonitor // instantiation) with the current time, so that they will @@ -444,8 +455,60 @@ void MgrMonitor::drop_standby(uint64_t gid) bool MgrMonitor::preprocess_command(MonOpRequestRef op) { - return false; + MMonCommand *m = static_cast(op->get_req()); + std::stringstream ss; + bufferlist rdata; + + std::map cmdmap; + if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) { + string rs = ss.str(); + mon->reply_command(op, -EINVAL, rs, rdata, get_last_committed()); + return true; + } + MonSession *session = m->get_session(); + if (!session) { + mon->reply_command(op, -EACCES, "access denied", rdata, + get_last_committed()); + return true; + } + + string format; + cmd_getval(g_ceph_context, cmdmap, "format", format, string("json-pretty")); + boost::scoped_ptr f(Formatter::create(format)); + + string prefix; + cmd_getval(g_ceph_context, cmdmap, "prefix", prefix); + int r = 0; + + if (prefix == "mgr dump") { + int64_t epoch = 0; + cmd_getval(g_ceph_context, cmdmap, "epoch", epoch, (int64_t)map.get_epoch()); + if (epoch == (int64_t)map.get_epoch()) { + f->dump_object("mgrmap", map); + } else { + bufferlist bl; + int err = get_version(epoch, bl); + if (err == -ENOENT) { + r = -ENOENT; + ss << "there is no map for epoch " << epoch; + goto reply; + } + MgrMap m; + auto p = bl.begin(); + m.decode(p); + f->dump_object("mgrmap", m); + } + f->flush(rdata); + } else { + return false; + } + +reply: + string rs; + getline(ss, rs); + mon->reply_command(op, r, rs, rdata, get_last_committed()); + return true; } bool MgrMonitor::prepare_command(MonOpRequestRef op) @@ -538,15 +601,14 @@ bool MgrMonitor::prepare_command(MonOpRequestRef op) void MgrMonitor::init() { - if (digest_callback == nullptr) { + if (digest_event == nullptr) { send_digests(); // To get it to schedule its own event } } void MgrMonitor::on_shutdown() { - if (digest_callback) { - mon->timer.cancel_event(digest_callback); - } + cancel_timer(); } + diff --git a/ceph/src/mon/MgrMonitor.h b/ceph/src/mon/MgrMonitor.h index a582d95b1..ea1a0a91a 100644 --- a/ceph/src/mon/MgrMonitor.h +++ b/ceph/src/mon/MgrMonitor.h @@ -11,20 +11,21 @@ * Foundation. See file COPYING. */ +#ifndef CEPH_MGRMONITOR_H +#define CEPH_MGRMONITOR_H #include "include/Context.h" #include "MgrMap.h" #include "PaxosService.h" - -class MgrMonitor : public PaxosService +class MgrMonitor: public PaxosService { MgrMap map; MgrMap pending_map; utime_t first_seen_inactive; - std::map last_beacon; + std::map last_beacon; /** * If a standby is available, make it active, given that @@ -36,14 +37,16 @@ class MgrMonitor : public PaxosService void drop_active(); void drop_standby(uint64_t gid); - Context *digest_callback; + Context *digest_event = nullptr; + void cancel_timer(); bool check_caps(MonOpRequestRef op, const uuid_d& fsid); public: MgrMonitor(Monitor *mn, Paxos *p, const string& service_name) - : PaxosService(mn, p, service_name), digest_callback(nullptr) + : PaxosService(mn, p, service_name) {} + ~MgrMonitor() override {} void init() override; void on_shutdown() override; @@ -83,3 +86,4 @@ public: friend class C_Updated; }; +#endif diff --git a/ceph/src/mon/MgrStatMonitor.cc b/ceph/src/mon/MgrStatMonitor.cc new file mode 100644 index 000000000..df92265d3 --- /dev/null +++ b/ceph/src/mon/MgrStatMonitor.cc @@ -0,0 +1,262 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "MgrStatMonitor.h" +#include "mon/OSDMonitor.h" +#include "mon/PGMap.h" +#include "mon/PGMonitor.h" +#include "messages/MGetPoolStats.h" +#include "messages/MGetPoolStatsReply.h" +#include "messages/MMonMgrReport.h" +#include "messages/MStatfs.h" +#include "messages/MStatfsReply.h" + +class MgrPGStatService : public MonPGStatService { + PGMapDigest& digest; +public: + MgrPGStatService(PGMapDigest& d) : digest(d) {} + + const pool_stat_t* get_pool_stat(int poolid) const override { + auto i = digest.pg_pool_sum.find(poolid); + if (i != digest.pg_pool_sum.end()) { + return &i->second; + } + return nullptr; + } + + ceph_statfs get_statfs() const override { + return digest.get_statfs(); + } + + void print_summary(Formatter *f, ostream *out) const override { + digest.print_summary(f, out); + } + void dump_info(Formatter *f) const override { + digest.dump(f); + } + void dump_fs_stats(stringstream *ss, + Formatter *f, + bool verbose) const override { + digest.dump_fs_stats(ss, f, verbose); + } + void dump_pool_stats(const OSDMap& osdm, stringstream *ss, Formatter *f, + bool verbose) const override { + digest.dump_pool_stats_full(osdm, ss, f, verbose); + } +}; + + +#define dout_subsys ceph_subsys_mon +#undef dout_prefix +#define dout_prefix _prefix(_dout, mon) +static ostream& _prefix(std::ostream *_dout, Monitor *mon) { + return *_dout << "mon." << mon->name << "@" << mon->rank + << "(" << mon->get_state_name() + << ").mgrstat "; +} + +MgrStatMonitor::MgrStatMonitor(Monitor *mn, Paxos *p, const string& service_name) + : PaxosService(mn, p, service_name), + pgservice(new MgrPGStatService(digest)) +{ +} + +MgrStatMonitor::~MgrStatMonitor() = default; + +MonPGStatService *MgrStatMonitor::get_pg_stat_service() +{ + return pgservice.get(); +} + +void MgrStatMonitor::create_initial() +{ + dout(10) << dendl; + version = 0; +} + +void MgrStatMonitor::update_from_paxos(bool *need_bootstrap) +{ + version = get_last_committed(); + dout(10) << " " << version << dendl; + bufferlist bl; + get_version(version, bl); + if (version) { + assert(bl.length()); + auto p = bl.begin(); + ::decode(digest, p); + ::decode(health_summary, p); + ::decode(health_detail, p); + } +} + +void MgrStatMonitor::create_pending() +{ + dout(10) << " " << version << dendl; + pending_digest = digest; + pending_health_summary = health_summary; + pending_health_detail = health_detail; +} + +void MgrStatMonitor::encode_pending(MonitorDBStore::TransactionRef t) +{ + ++version; + if (version < mon->pgmon()->get_last_committed()) { + // fast-forward to pgmon version to ensure clients don't see a + // jump back in time for MGetPoolStats and MStatFs. + version = mon->pgmon()->get_last_committed() + 1; + } + dout(10) << " " << version << dendl; + bufferlist bl; + ::encode(pending_digest, bl, mon->get_quorum_con_features()); + ::encode(pending_health_summary, bl); + ::encode(pending_health_detail, bl); + put_version(t, version, bl); + put_last_committed(t, version); +} + +version_t MgrStatMonitor::get_trim_to() +{ + // we don't actually need *any* old states, but keep a few. + if (version > 5) { + return version - 5; + } + return 0; +} + +void MgrStatMonitor::on_active() +{ +} + +void MgrStatMonitor::get_health(list >& summary, + list > *detail, + CephContext *cct) const +{ + summary.insert(summary.end(), health_summary.begin(), health_summary.end()); + if (detail) { + detail->insert(detail->end(), health_detail.begin(), health_detail.end()); + } +} + +void MgrStatMonitor::tick() +{ +} + +void MgrStatMonitor::print_summary(Formatter *f, std::ostream *ss) const +{ + pgservice->print_summary(f, ss); +} + +bool MgrStatMonitor::preprocess_query(MonOpRequestRef op) +{ + auto m = static_cast(op->get_req()); + switch (m->get_type()) { + case CEPH_MSG_STATFS: + return preprocess_statfs(op); + case MSG_MON_MGR_REPORT: + return preprocess_report(op); + case MSG_GETPOOLSTATS: + return preprocess_getpoolstats(op); + default: + mon->no_reply(op); + derr << "Unhandled message type " << m->get_type() << dendl; + return true; + } +} + +bool MgrStatMonitor::prepare_update(MonOpRequestRef op) +{ + auto m = static_cast(op->get_req()); + switch (m->get_type()) { + case MSG_MON_MGR_REPORT: + return prepare_report(op); + default: + mon->no_reply(op); + derr << "Unhandled message type " << m->get_type() << dendl; + return true; + } +} + +bool MgrStatMonitor::preprocess_report(MonOpRequestRef op) +{ + return false; +} + +bool MgrStatMonitor::prepare_report(MonOpRequestRef op) +{ + auto m = static_cast(op->get_req()); + bufferlist bl = m->get_data(); + auto p = bl.begin(); + ::decode(pending_digest, p); + dout(10) << __func__ << " " << pending_digest << dendl; + pending_health_summary.swap(m->health_summary); + pending_health_detail.swap(m->health_detail); + return true; +} + +bool MgrStatMonitor::preprocess_getpoolstats(MonOpRequestRef op) +{ + op->mark_pgmon_event(__func__); + auto m = static_cast(op->get_req()); + auto session = m->get_session(); + if (!session) + return true; + if (!session->is_capable("pg", MON_CAP_R)) { + dout(0) << "MGetPoolStats received from entity with insufficient caps " + << session->caps << dendl; + return true; + } + if (m->fsid != mon->monmap->fsid) { + dout(0) << __func__ << " on fsid " + << m->fsid << " != " << mon->monmap->fsid << dendl; + return true; + } + epoch_t ver = 0; + if (mon->pgservice == get_pg_stat_service()) { + ver = get_last_committed(); + } else { + ver = mon->pgmon()->get_last_committed(); + } + auto reply = new MGetPoolStatsReply(m->fsid, m->get_tid(), ver); + for (const auto& pool_name : m->pools) { + const auto pool_id = mon->osdmon()->osdmap.lookup_pg_pool_name(pool_name); + if (pool_id == -ENOENT) + continue; + auto pool_stat = mon->pgservice->get_pool_stat(pool_id); + if (!pool_stat) + continue; + reply->pool_stats[pool_name] = *pool_stat; + } + mon->send_reply(op, reply); + return true; +} + +bool MgrStatMonitor::preprocess_statfs(MonOpRequestRef op) +{ + op->mark_pgmon_event(__func__); + auto statfs = static_cast(op->get_req()); + auto session = statfs->get_session(); + if (!session) + return true; + if (!session->is_capable("pg", MON_CAP_R)) { + dout(0) << "MStatfs received from entity with insufficient privileges " + << session->caps << dendl; + return true; + } + if (statfs->fsid != mon->monmap->fsid) { + dout(0) << __func__ << " on fsid " << statfs->fsid + << " != " << mon->monmap->fsid << dendl; + return true; + } + dout(10) << __func__ << " " << *statfs + << " from " << statfs->get_orig_source() << dendl; + epoch_t ver = 0; + if (mon->pgservice == get_pg_stat_service()) { + ver = get_last_committed(); + } else { + ver = mon->pgmon()->get_last_committed(); + } + auto reply = new MStatfsReply(statfs->fsid, statfs->get_tid(), ver); + reply->h.st = mon->pgservice->get_statfs(); + mon->send_reply(op, reply); + return true; +} diff --git a/ceph/src/mon/MgrStatMonitor.h b/ceph/src/mon/MgrStatMonitor.h new file mode 100644 index 000000000..7ecbc9d37 --- /dev/null +++ b/ceph/src/mon/MgrStatMonitor.h @@ -0,0 +1,71 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "include/Context.h" +#include "PaxosService.h" +#include "mon/PGMap.h" + +class MonPGStatService; +class MgrPGStatService; + +class MgrStatMonitor : public PaxosService { + // live version + version_t version = 0; + PGMapDigest digest; + list> health_summary; + list> health_detail; + + // pending commit + PGMapDigest pending_digest; + list> pending_health_summary; + list> pending_health_detail; + + std::unique_ptr pgservice; + +public: + MgrStatMonitor(Monitor *mn, Paxos *p, const string& service_name); + ~MgrStatMonitor() override; + + void init() override {} + void on_shutdown() override {} + + void create_initial() override; + void update_from_paxos(bool *need_bootstrap) override; + void create_pending() override; + void encode_pending(MonitorDBStore::TransactionRef t) override; + version_t get_trim_to() override; + + bool preprocess_query(MonOpRequestRef op) override; + bool prepare_update(MonOpRequestRef op) override; + + void encode_full(MonitorDBStore::TransactionRef t) override { } + + bool preprocess_report(MonOpRequestRef op); + bool prepare_report(MonOpRequestRef op); + + bool preprocess_getpoolstats(MonOpRequestRef op); + bool preprocess_statfs(MonOpRequestRef op); + + void check_sub(Subscription *sub); + void check_subs(); + void send_digests(); + + void on_active() override; + void get_health(list >& summary, + list > *detail, + CephContext *cct) const override; + void tick() override; + + uint64_t get_last_osd_stat_seq(int osd) { + return digest.get_last_osd_stat_seq(osd); + } + + + void print_summary(Formatter *f, std::ostream *ss) const; + + MonPGStatService *get_pg_stat_service(); + + friend class C_Updated; +}; diff --git a/ceph/src/mon/MonCap.cc b/ceph/src/mon/MonCap.cc index 558e67d9c..af98eb2d8 100644 --- a/ceph/src/mon/MonCap.cc +++ b/ceph/src/mon/MonCap.cc @@ -44,7 +44,7 @@ using std::vector; #define dout_subsys ceph_subsys_mon -ostream& operator<<(ostream& out, mon_rwxa_t p) +ostream& operator<<(ostream& out, const mon_rwxa_t& p) { if (p == MON_CAP_ANY) return out << "*"; @@ -165,15 +165,17 @@ void MonCapGrant::expand_profile_mon(const EntityName& name) const profile_grants.push_back(MonCapGrant("osd", MON_CAP_R)); // This command grant is checked explicitly in MRemoveSnaps handling profile_grants.push_back(MonCapGrant("osd pool rmsnap")); + profile_grants.push_back(MonCapGrant("osd blacklist")); profile_grants.push_back(MonCapGrant("log", MON_CAP_W)); } if (profile == "mgr") { profile_grants.push_back(MonCapGrant("mgr", MON_CAP_ALL)); - profile_grants.push_back(MonCapGrant("log", MON_CAP_W)); - profile_grants.push_back(MonCapGrant("mon", MON_CAP_R)); - profile_grants.push_back(MonCapGrant("mds", MON_CAP_R)); + profile_grants.push_back(MonCapGrant("log", MON_CAP_R | MON_CAP_W)); + profile_grants.push_back(MonCapGrant("mon", MON_CAP_R | MON_CAP_W)); + profile_grants.push_back(MonCapGrant("mds", MON_CAP_R | MON_CAP_W)); profile_grants.push_back(MonCapGrant("osd", MON_CAP_R | MON_CAP_W)); - profile_grants.push_back(MonCapGrant("config-key", MON_CAP_R)); + profile_grants.push_back(MonCapGrant("auth", MON_CAP_R | MON_CAP_X)); + profile_grants.push_back(MonCapGrant("config-key", MON_CAP_R | MON_CAP_W)); string prefix = string("daemon-private/mgr/"); profile_grants.push_back(MonCapGrant("config-key get", "key", StringConstraint("", prefix))); diff --git a/ceph/src/mon/MonCap.h b/ceph/src/mon/MonCap.h index 25684d307..46acb1e42 100644 --- a/ceph/src/mon/MonCap.h +++ b/ceph/src/mon/MonCap.h @@ -32,7 +32,7 @@ struct mon_rwxa_t { } }; -ostream& operator<<(ostream& out, mon_rwxa_t p); +ostream& operator<<(ostream& out, const mon_rwxa_t& p); struct StringConstraint { string value; diff --git a/ceph/src/mon/MonClient.cc b/ceph/src/mon/MonClient.cc index da843269a..6f9ab9e4a 100644 --- a/ceph/src/mon/MonClient.cc +++ b/ceph/src/mon/MonClient.cc @@ -39,7 +39,6 @@ #include "auth/AuthMethodList.h" #include "auth/RotatingKeyRing.h" - #define dout_subsys ceph_subsys_monc #undef dout_prefix #define dout_prefix *_dout << "monclient" << (_hunting() ? "(hunting)":"") << ": " @@ -48,7 +47,8 @@ MonClient::MonClient(CephContext *cct_) : Dispatcher(cct_), messenger(NULL), monc_lock("MonClient::monc_lock"), - timer(cct_, monc_lock), finisher(cct_), + timer(cct_, monc_lock), + finisher(cct_), initialized(false), no_keyring_disabled_cephx(false), log_client(NULL), @@ -267,6 +267,11 @@ bool MonClient::ms_dispatch(Message *m) switch (m->get_type()) { case CEPH_MSG_MON_MAP: handle_monmap(static_cast(m)); + if (passthrough_monmap) { + return false; + } else { + m->put(); + } break; case CEPH_MSG_AUTH_REPLY: handle_auth(static_cast(m)); @@ -311,6 +316,8 @@ void MonClient::flush_log() send_log(); } +/* Unlike all the other message-handling functions, we don't put away a reference +* because we want to support MMonMap passthrough to other Dispatchers. */ void MonClient::handle_monmap(MMonMap *m) { ldout(cct, 10) << __func__ << " " << *m << dendl; @@ -337,8 +344,6 @@ void MonClient::handle_monmap(MMonMap *m) map_cond.Signal(); want_monmap = false; - - m->put(); } // ---------------------- @@ -408,7 +413,10 @@ void MonClient::shutdown() delete version_requests.begin()->second; version_requests.erase(version_requests.begin()); } - + while (!mon_commands.empty()) { + auto tid = mon_commands.begin()->first; + _cancel_mon_command(tid); + } while (!waiting_for_session.empty()) { ldout(cct, 20) << __func__ << " discarding pending message " << *waiting_for_session.front() << dendl; waiting_for_session.front()->put(); @@ -1003,7 +1011,7 @@ void MonClient::handle_mon_command_ack(MMonCommandAck *ack) ack->put(); } -int MonClient::_cancel_mon_command(uint64_t tid, int r) +int MonClient::_cancel_mon_command(uint64_t tid) { assert(monc_lock.is_locked()); @@ -1053,7 +1061,7 @@ void MonClient::start_mon_command(const vector& cmd, public: C_CancelMonCommand(uint64_t tid, MonClient *monc) : tid(tid), monc(monc) {} void finish(int r) override { - monc->_cancel_mon_command(tid, -ETIMEDOUT); + monc->_cancel_mon_command(tid); } }; r->ontimeout = new C_CancelMonCommand(r->tid, this); diff --git a/ceph/src/mon/MonClient.h b/ceph/src/mon/MonClient.h index 9656db0ee..283f2335c 100644 --- a/ceph/src/mon/MonClient.h +++ b/ceph/src/mon/MonClient.h @@ -187,7 +187,8 @@ private: // monclient bool want_monmap; Cond map_cond; -private: + bool passthrough_monmap = false; + // authenticate std::unique_ptr auth; uint32_t want_keys = 0; @@ -339,6 +340,21 @@ public: int build_initial_monmap(); int get_monmap(); int get_monmap_privately(); + /** + * If you want to see MonMap messages, set this and + * the MonClient will tell the Messenger it hasn't + * dealt with it. + * Note that if you do this, *you* are of course responsible for + * putting the message reference! + */ + void set_passthrough_monmap() { + Mutex::Locker l(monc_lock); + passthrough_monmap = true; + } + void unset_passthrough_monmap() { + Mutex::Locker l(monc_lock); + passthrough_monmap = false; + } /** * Ping monitor with ID @p mon_id and record the resulting * reply in @p result_reply. @@ -432,7 +448,7 @@ private: void _send_command(MonCommand *r); void _resend_mon_commands(); - int _cancel_mon_command(uint64_t tid, int r); + int _cancel_mon_command(uint64_t tid); void _finish_command(MonCommand *r, int ret, string rs); void _finish_auth(); void handle_mon_command_ack(MMonCommandAck *ack); diff --git a/ceph/src/mon/MonCommands.h b/ceph/src/mon/MonCommands.h index 970a30b43..00a1642e0 100644 --- a/ceph/src/mon/MonCommands.h +++ b/ceph/src/mon/MonCommands.h @@ -29,7 +29,7 @@ * helpstring: displays in CLI help, API help (nice if it refers to * parameter names from signature, 40-a few hundred chars) * modulename: the monitor module or daemon this applies to: - * mds, osd, pg (osd), mon, auth, log, config-key + * mds, osd, pg (osd), mon, auth, log, config-key, mgr * req perms: required permission in that modulename space to execute command * this also controls what type of REST command is accepted * availability: cli, rest, or both @@ -133,6 +133,9 @@ COMMAND("pg set_nearfull_ratio name=ratio,type=CephFloat,range=0.0|1.0", \ COMMAND("pg map name=pgid,type=CephPgid", "show mapping of pg to osds", \ "pg", "r", "cli,rest") +COMMAND("osd last-stat-seq name=id,type=CephOsdName", \ + "get the last pg stats sequence number reported for this osd", \ + "osd", "r", "cli,rest") /* * auth commands AuthMonitor.cc @@ -194,6 +197,9 @@ COMMAND_WITH_FLAG("scrub", "scrub the monitor stores", \ COMMAND("fsid", "show cluster FSID/UUID", "mon", "r", "cli,rest") COMMAND("log name=logtext,type=CephString,n=N", \ "log supplied text to the monitor log", "mon", "rw", "cli,rest") +COMMAND("log last name=num,type=CephInt,range=1,req=false", \ + "print last few lines of the cluster log", \ + "mon", "rw", "cli,rest") COMMAND_WITH_FLAG("injectargs " \ "name=injected_args,type=CephString,n=N", \ "inject config arguments into monitor", "mon", "rw", "cli,rest", @@ -206,6 +212,8 @@ COMMAND("df name=detail,type=CephChoices,strings=detail,req=false", \ COMMAND("report name=tags,type=CephString,n=N,req=false", \ "report full status of cluster, optional title tag strings", \ "mon", "r", "cli,rest") +COMMAND("features", "report of connected features", \ + "mon", "r", "cli,rest") COMMAND("quorum_status", "report status of monitor quorum", \ "mon", "r", "cli,rest") @@ -253,6 +261,12 @@ COMMAND_WITH_FLAG("mon sync force " \ COMMAND("mon metadata name=id,type=CephString,req=false", "fetch metadata for mon ", "mon", "r", "cli,rest") +COMMAND("mon count-metadata name=property,type=CephString", + "count mons by metadata field property", + "mon", "r", "cli,rest") +COMMAND("mon versions", + "check running versions of monitors", + "mon", "r", "cli,rest") /* @@ -273,6 +287,12 @@ COMMAND_WITH_FLAG("mds getmap " \ COMMAND("mds metadata name=who,type=CephString,req=false", "fetch metadata for mds ", "mds", "r", "cli,rest") +COMMAND("mds count-metadata name=property,type=CephString", + "count MDSs by metadata field property", + "mds", "r", "cli,rest") +COMMAND("mds versions", + "check running versions of MDSs", + "mds", "r", "cli,rest") COMMAND_WITH_FLAG("mds tell " \ "name=who,type=CephString " \ "name=args,type=CephString,n=N", \ @@ -421,7 +441,8 @@ COMMAND("osd dump " \ "name=epoch,type=CephInt,range=0,req=false", "print summary of OSD map", "osd", "r", "cli,rest") COMMAND("osd tree " \ - "name=epoch,type=CephInt,range=0,req=false", \ + "name=epoch,type=CephInt,range=0,req=false " \ + "name=states,type=CephChoices,strings=up|down|in|out,n=N,req=false", \ "print OSD tree", "osd", "r", "cli,rest") COMMAND("osd ls " \ "name=epoch,type=CephInt,range=0,req=false", \ @@ -433,6 +454,11 @@ COMMAND("osd getcrushmap " \ "name=epoch,type=CephInt,range=0,req=false", \ "get CRUSH map", "osd", "r", "cli,rest") COMMAND("osd getmaxosd", "show largest OSD id", "osd", "r", "cli,rest") +COMMAND("osd ls-tree " \ + "name=epoch,type=CephInt,range=0,req=false " + "name=name,type=CephString,req=true", \ + "show OSD ids under bucket in the CRUSH map", \ + "osd", "r", "cli,rest") COMMAND("osd find " \ "name=id,type=CephOsdName", \ "find osd in the CRUSH map and show its location", \ @@ -441,20 +467,17 @@ COMMAND("osd metadata " \ "name=id,type=CephOsdName,req=false", \ "fetch metadata for osd {id} (default all)", \ "osd", "r", "cli,rest") +COMMAND("osd count-metadata name=property,type=CephString", + "count OSDs by metadata field property", + "osd", "r", "cli,rest") +COMMAND("osd versions", \ + "check running versions of OSDs", + "osd", "r", "cli,rest") COMMAND("osd map " \ "name=pool,type=CephPoolname " \ "name=object,type=CephObjectname " \ "name=nspace,type=CephString,req=false", \ "find pg for in with [namespace]", "osd", "r", "cli,rest") -COMMAND("osd scrub " \ - "name=who,type=CephString", \ - "initiate scrub on osd ", "osd", "rw", "cli,rest") -COMMAND("osd deep-scrub " \ - "name=who,type=CephString", \ - "initiate deep scrub on osd ", "osd", "rw", "cli,rest") -COMMAND("osd repair " \ - "name=who,type=CephString", \ - "initiate repair on osd ", "osd", "rw", "cli,rest") COMMAND("osd lspools " \ "name=auid,type=CephInt,req=false", \ "list pools", "osd", "r", "cli,rest") @@ -470,9 +493,11 @@ COMMAND("osd crush rule dump " \ COMMAND("osd crush dump", \ "dump crush map", \ "osd", "r", "cli,rest") -COMMAND("osd setcrushmap", "set crush map from input file", \ +COMMAND("osd setcrushmap name=prior_version,type=CephInt,req=false", \ + "set crush map from input file", \ "osd", "rw", "cli,rest") -COMMAND("osd crush set", "set crush map from input file", \ +COMMAND("osd crush set name=prior_version,type=CephInt,req=false", \ + "set crush map from input file", \ "osd", "rw", "cli,rest") COMMAND("osd crush add-bucket " \ "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ @@ -512,6 +537,12 @@ COMMAND("osd crush move " \ "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ "move existing entry for to location ", \ "osd", "rw", "cli,rest") +COMMAND("osd crush swap-bucket " \ + "name=source,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=dest,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=force,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ + "swap existing bucket contents from (orphan) bucket and ", \ + "osd", "rw", "cli,rest") COMMAND("osd crush link " \ "name=name,type=CephString " \ "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ @@ -604,7 +635,8 @@ COMMAND("osd set-nearfull-ratio " \ "set usage ratio at which OSDs are marked near-full", "osd", "rw", "cli,rest") COMMAND("osd set-require-min-compat-client " \ - "name=version,type=CephString", + "name=version,type=CephString " \ + "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ "set the minimum client version we will maintain compatibility with", "osd", "rw", "cli,rest") COMMAND("osd pause", "pause osd", "osd", "rw", "cli,rest") @@ -626,25 +658,81 @@ COMMAND("osd erasure-code-profile ls", \ "list all erasure code profiles", \ "osd", "r", "cli,rest") COMMAND("osd set " \ - "name=key,type=CephChoices,strings=full|pause|noup|nodown|noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|notieragent|sortbitwise|require_jewel_osds|require_kraken_osds|require_luminous_osds", \ + "name=key,type=CephChoices,strings=full|pause|noup|nodown|noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|notieragent|sortbitwise|require_jewel_osds|require_kraken_osds", \ "set ", "osd", "rw", "cli,rest") COMMAND("osd unset " \ "name=key,type=CephChoices,strings=full|pause|noup|nodown|noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|notieragent", \ "unset ", "osd", "rw", "cli,rest") +COMMAND("osd require-osd-release "\ + "name=release,type=CephChoices,strings=luminous", + "set the minimum allowed OSD release to participate in the cluster", + "osd", "rw", "cli,rest") COMMAND("osd cluster_snap", "take cluster snapshot (disabled)", \ "osd", "r", "") COMMAND("osd down " \ "type=CephString,name=ids,n=N", \ - "set osd(s) [...] down", "osd", "rw", "cli,rest") + "set osd(s) [...] down, " \ + "or use to set all osds down", \ + "osd", "rw", "cli,rest") COMMAND("osd out " \ "name=ids,type=CephString,n=N", \ - "set osd(s) [...] out", "osd", "rw", "cli,rest") + "set osd(s) [...] out, " \ + "or use to set all osds out", \ + "osd", "rw", "cli,rest") COMMAND("osd in " \ "name=ids,type=CephString,n=N", \ - "set osd(s) [...] in", "osd", "rw", "cli,rest") + "set osd(s) [...] in, " + "can use to automatically set all previously out osds in", \ + "osd", "rw", "cli,rest") COMMAND("osd rm " \ "name=ids,type=CephString,n=N", \ - "remove osd(s) [...] in", "osd", "rw", "cli,rest") + "remove osd(s) [...], " + "or use to remove all osds", \ + "osd", "rw", "cli,rest") +COMMAND("osd add-noup " \ + "name=ids,type=CephString,n=N", \ + "mark osd(s) [...] as noup, " \ + "or use to mark all osds as noup", \ + "osd", "rw", "cli,rest") +COMMAND("osd add-nodown " \ + "name=ids,type=CephString,n=N", \ + "mark osd(s) [...] as nodown, " \ + "or use to mark all osds as nodown", \ + "osd", "rw", "cli,rest") +COMMAND("osd add-noin " \ + "name=ids,type=CephString,n=N", \ + "mark osd(s) [...] as noin, " \ + "or use to mark all osds as noin", \ + "osd", "rw", "cli,rest") +COMMAND("osd add-noout " \ + "name=ids,type=CephString,n=N", \ + "mark osd(s) [...] as noout, " \ + "or use to mark all osds as noout", \ + "osd", "rw", "cli,rest") +COMMAND("osd rm-noup " \ + "name=ids,type=CephString,n=N", \ + "allow osd(s) [...] to be marked up " \ + "(if they are currently marked as noup), " \ + "can use to automatically filter out all noup osds", \ + "osd", "rw", "cli,rest") +COMMAND("osd rm-nodown " \ + "name=ids,type=CephString,n=N", \ + "allow osd(s) [...] to be marked down " \ + "(if they are currently marked as nodown), " \ + "can use to automatically filter out all nodown osds", \ + "osd", "rw", "cli,rest") +COMMAND("osd rm-noin " \ + "name=ids,type=CephString,n=N", \ + "allow osd(s) [...] to be marked in " \ + "(if they are currently marked as noin), " \ + "can use to automatically filter out all noin osds", \ + "osd", "rw", "cli,rest") +COMMAND("osd rm-noout " \ + "name=ids,type=CephString,n=N", \ + "allow osd(s) [...] to be marked out " \ + "(if they are currently marked as noout), " \ + "can use to automatically filter out all noout osds", \ + "osd", "rw", "cli,rest") COMMAND("osd reweight " \ "name=id,type=CephOsdName " \ "type=CephFloat,name=weight,range=0.0|1.0", \ @@ -687,15 +775,36 @@ COMMAND("osd primary-affinity " \ "type=CephFloat,name=weight,range=0.0|1.0", \ "adjust osd primary-affinity from 0.0 <= <= 1.0", \ "osd", "rw", "cli,rest") +COMMAND("osd destroy " \ + "name=id,type=CephOsdName " \ + "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ + "mark osd as being destroyed. Keeps the ID intact (allowing reuse), " \ + "but removes cephx keys, config-key data and lockbox keys, "\ + "rendering data permanently unreadable.", \ + "osd", "rw", "cli,rest") +COMMAND("osd purge " \ + "name=id,type=CephOsdName " \ + "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ + "purge all osd data from the monitors. Combines `osd destroy`, " \ + "`osd rm`, and `osd crush rm`.", \ + "osd", "rw", "cli,rest") COMMAND("osd lost " \ "name=id,type=CephOsdName " \ "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ "mark osd as permanently lost. THIS DESTROYS DATA IF NO MORE REPLICAS EXIST, BE CAREFUL", \ "osd", "rw", "cli,rest") -COMMAND("osd create " \ +COMMAND_WITH_FLAG("osd create " \ "name=uuid,type=CephUUID,req=false " \ "name=id,type=CephOsdName,req=false", \ - "create new osd (with optional UUID and ID)", "osd", "rw", "cli,rest") + "create new osd (with optional UUID and ID)", "osd", "rw", "cli,rest", + FLAG(DEPRECATED)) +COMMAND("osd new " \ + "name=uuid,type=CephUUID,req=true " \ + "name=id,type=CephOsdName,req=false", \ + "Create a new OSD. If supplied, the `id` to be replaced needs to " \ + "exist and have been previously destroyed. " \ + "Reads secrets from JSON file via `-i ` (see man page).", \ + "osd", "rw", "cli,rest") COMMAND("osd blacklist " \ "name=blacklistop,type=CephChoices,strings=add|rm " \ "name=addr,type=CephEntityAddr " \ @@ -719,7 +828,7 @@ COMMAND("osd pool create " \ "name=pgp_num,type=CephInt,range=0,req=false " \ "name=pool_type,type=CephChoices,strings=replicated|erasure,req=false " \ "name=erasure_code_profile,type=CephString,req=false,goodchars=[A-Za-z0-9-_.] " \ - "name=ruleset,type=CephString,req=false " \ + "name=rule,type=CephString,req=false " \ "name=expected_num_objects,type=CephInt,req=false", \ "create pool", "osd", "rw", "cli,rest") COMMAND("osd pool delete " \ @@ -740,11 +849,11 @@ COMMAND("osd pool rename " \ "rename to ", "osd", "rw", "cli,rest") COMMAND("osd pool get " \ "name=pool,type=CephPoolname " \ - "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_rule|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|auid|target_max_objects|target_max_bytes|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|erasure_code_profile|min_read_recency_for_promote|all|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n|scrub_min_interval|scrub_max_interval|deep_scrub_interval|recovery_priority|recovery_op_priority|scrub_priority|compression_mode|compression_algorithm|compression_required_ratio|compression_max_blob_size|compression_min_blob_size|csum_type|csum_min_block|csum_max_block", \ + "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_rule|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|auid|target_max_objects|target_max_bytes|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|erasure_code_profile|min_read_recency_for_promote|all|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n|scrub_min_interval|scrub_max_interval|deep_scrub_interval|recovery_priority|recovery_op_priority|scrub_priority|compression_mode|compression_algorithm|compression_required_ratio|compression_max_blob_size|compression_min_blob_size|csum_type|csum_min_block|csum_max_block", \ "get pool parameter ", "osd", "r", "cli,rest") COMMAND("osd pool set " \ "name=pool,type=CephPoolname " \ - "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_rule|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|use_gmt_hitset|debug_fake_ec_pool|target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|auid|min_read_recency_for_promote|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n|scrub_min_interval|scrub_max_interval|deep_scrub_interval|recovery_priority|recovery_op_priority|scrub_priority|compression_mode|compression_algorithm|compression_required_ratio|compression_max_blob_size|compression_min_blob_size|csum_type|csum_min_block|csum_max_block|allow_ec_overwrites " \ + "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_rule|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|use_gmt_hitset|debug_fake_ec_pool|target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|auid|min_read_recency_for_promote|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n|scrub_min_interval|scrub_max_interval|deep_scrub_interval|recovery_priority|recovery_op_priority|scrub_priority|compression_mode|compression_algorithm|compression_required_ratio|compression_max_blob_size|compression_min_blob_size|csum_type|csum_min_block|csum_max_block|allow_ec_overwrites " \ "name=val,type=CephString " \ "name=force,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \ "set pool parameter to ", "osd", "rw", "cli,rest") @@ -763,9 +872,6 @@ COMMAND("osd pool get-quota " \ COMMAND("osd utilization", "get basic pg distribution stats", "osd", "r", "cli,rest") -COMMAND("osd df " \ - "name=output_method,type=CephChoices,strings=plain|tree,req=false", \ - "show OSD utilization", "osd", "r", "cli,rest") // tiering COMMAND("osd tier add " \ @@ -834,5 +940,9 @@ COMMAND("config-key dump", "dump keys and values", "config-key", "r", "cli,rest" /* * mon/MgrMonitor.cc */ +COMMAND("mgr dump " \ + "name=epoch,type=CephInt,range=0,req=false", \ + "dump the latest MgrMap", \ + "mgr", "rw", "cli,rest") COMMAND("mgr fail name=who,type=CephString", \ "treat the named manager daemon as failed", "mgr", "rw", "cli,rest") diff --git a/ceph/src/mon/MonOpRequest.h b/ceph/src/mon/MonOpRequest.h index bd85f11f6..a5000efe4 100644 --- a/ceph/src/mon/MonOpRequest.h +++ b/ceph/src/mon/MonOpRequest.h @@ -218,4 +218,30 @@ public: typedef MonOpRequest::Ref MonOpRequestRef; +struct C_MonOp : public Context +{ + MonOpRequestRef op; + + explicit C_MonOp(MonOpRequestRef o) : + op(o) { } + + void finish(int r) override { + if (op && r == -ECANCELED) { + op->mark_event("callback canceled"); + } else if (op && r == -EAGAIN) { + op->mark_event("callback retry"); + } else if (op && r == 0) { + op->mark_event("callback finished"); + } + _finish(r); + } + + void mark_op_event(const string &event) { + if (op) + op->mark_event_string(event); + } + + virtual void _finish(int r) = 0; +}; + #endif /* MON_OPREQUEST_H_ */ diff --git a/ceph/src/mon/Monitor.cc b/ceph/src/mon/Monitor.cc index 2a1e6ad11..9a7304fca 100644 --- a/ceph/src/mon/Monitor.cc +++ b/ceph/src/mon/Monitor.cc @@ -36,6 +36,7 @@ #include "messages/MGenericMessage.h" #include "messages/MMonCommand.h" #include "messages/MMonCommandAck.h" +#include "messages/MMonHealth.h" #include "messages/MMonMetadata.h" #include "messages/MMonSync.h" #include "messages/MMonScrub.h" @@ -51,7 +52,6 @@ #include "messages/MAuthReply.h" #include "messages/MTimeCheck.h" -#include "messages/MMonHealth.h" #include "messages/MPing.h" #include "common/strtol.h" @@ -75,6 +75,7 @@ #include "LogMonitor.h" #include "AuthMonitor.h" #include "MgrMonitor.h" +#include "MgrStatMonitor.h" #include "mon/QuorumService.h" #include "mon/HealthMonitor.h" #include "mon/ConfigKeyService.h" @@ -124,29 +125,6 @@ MonCommand mon_commands[] = { }; -long parse_pos_long(const char *s, ostream *pss) -{ - if (*s == '-' || *s == '+') { - if (pss) - *pss << "expected numerical value, got: " << s; - return -EINVAL; - } - - string err; - long r = strict_strtol(s, 10, &err); - if ((r == 0) && !err.empty()) { - if (pss) - *pss << err; - return -1; - } - if (r < 0) { - if (pss) - *pss << "unable to parse positive integer '" << s << "'"; - return -1; - } - return r; -} - void C_MonContext::finish(int r) { if (mon->is_shutdown()) return; @@ -179,6 +157,7 @@ Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s, leader_supported_mon_commands_size(0), mgr_messenger(mgr_m), mgr_client(cct_, mgr_m), + pgservice(nullptr), store(s), state(STATE_PROBING), @@ -224,6 +203,7 @@ Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s, paxos_service[PAXOS_LOG] = new LogMonitor(this, paxos, "logm"); paxos_service[PAXOS_AUTH] = new AuthMonitor(this, paxos, "auth"); paxos_service[PAXOS_MGR] = new MgrMonitor(this, paxos, "mgr"); + paxos_service[PAXOS_MGRSTAT] = new MgrStatMonitor(this, paxos, "mgrstat"); health_monitor = new HealthMonitor(this); config_key_service = new ConfigKeyService(this, paxos); @@ -242,6 +222,9 @@ Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s, int cmdsize; get_locally_supported_monitor_commands(&cmds, &cmdsize); set_leader_supported_commands(cmds, cmdsize); + + // note: OSDMonitor may update this based on the luminous flag. + pgservice = mgrstatmon()->get_pg_stat_service(); } PaxosService *Monitor::get_paxos_service_by_name(const string& name) @@ -1091,6 +1074,7 @@ void Monitor::_reset() } quorum.clear(); outside_quorum.clear(); + quorum_feature_map.clear(); scrub_reset(); @@ -2111,6 +2095,16 @@ void Monitor::calc_quorum_requirements() dout(10) << __func__ << " required_features " << required_features << dendl; } +void Monitor::get_combined_feature_map(FeatureMap *fm) +{ + *fm += session_map.feature_map; + for (auto id : quorum) { + if (id != rank) { + *fm += quorum_feature_map[id]; + } + } +} + void Monitor::sync_force(Formatter *f, ostream& ss) { bool free_formatter = false; @@ -2242,6 +2236,7 @@ void Monitor::get_mon_status(Formatter *f, ostream& ss) monmap->dump(f); f->close_section(); + f->dump_object("feature_map", session_map.feature_map); f->close_section(); // mon_status if (free_formatter) { @@ -2576,7 +2571,7 @@ void Monitor::get_cluster_status(stringstream &ss, Formatter *f) osdmon()->osdmap.print_summary(f, cout); f->close_section(); f->open_object_section("pgmap"); - pgmon()->pg_map.print_summary(f, NULL); + pgservice->print_summary(f, NULL); f->close_section(); f->open_object_section("fsmap"); mdsmon()->get_fsmap().print_summary(f, NULL); @@ -2587,23 +2582,41 @@ void Monitor::get_cluster_status(stringstream &ss, Formatter *f) f->close_section(); f->close_section(); } else { - ss << " cluster " << monmap->get_fsid() << "\n"; - ss << " health " << joinify(health.begin(), health.end(), - string("\n ")) << "\n"; - ss << " monmap " << *monmap << "\n"; - ss << " election epoch " << get_epoch() - << ", quorum " << get_quorum() << " " << get_quorum_names() << "\n"; - if (mdsmon()->get_fsmap().filesystem_count() > 0) { - ss << " fsmap " << mdsmon()->get_fsmap() << "\n"; + + ss << " cluster:\n"; + ss << " id: " << monmap->get_fsid() << "\n"; + ss << " health: " << joinify(health.begin(), health.end(), + string("\n ")) << "\n"; + ss << "\n \n services:\n"; + const auto quorum_names = get_quorum_names(); + const auto mon_count = monmap->mon_info.size(); + ss << " mon: " << mon_count << " daemons, quorum " + << quorum_names; + if (quorum_names.size() != mon_count) { + std::list out_of_q; + for (size_t i = 0; i < monmap->ranks.size(); ++i) { + if (quorum.count(i) == 0) { + out_of_q.push_back(monmap->ranks[i]); + } + } + ss << ", out of quorum: " << joinify(out_of_q.begin(), + out_of_q.end(), std::string(", ")); } + ss << "\n"; if (mgrmon()->in_use()) { - ss << " mgr "; + ss << " mgr: "; mgrmon()->get_map().print_summary(nullptr, &ss); ss << "\n"; } - + if (mdsmon()->get_fsmap().filesystem_count() > 0) { + ss << " mds: " << mdsmon()->get_fsmap() << "\n"; + } + ss << " osd: "; osdmon()->osdmap.print_summary(NULL, ss); - pgmon()->pg_map.print_summary(NULL, &ss); + + ss << "\n \n data:\n"; + pgservice->print_summary(NULL, &ss); + ss << "\n "; } } @@ -2792,7 +2805,7 @@ void Monitor::handle_command(MonOpRequestRef op) Formatter *f = Formatter::create("json"); // hide mgr commands until luminous upgrade is complete bool hide_mgr_flag = - !osdmon()->osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS); + osdmon()->osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS; format_command_descriptions(leader_supported_mon_commands, leader_supported_mon_commands_size, f, &rdata, hide_mgr_flag); @@ -2907,7 +2920,7 @@ void Monitor::handle_command(MonOpRequestRef op) << "cmd=" << m->cmd << ": dispatch"; if (mon_cmd->is_mgr() && - osdmon()->osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { const auto& hdr = m->get_header(); uint64_t size = hdr.front_len + hdr.middle_len + hdr.data_len; uint64_t max = @@ -2934,7 +2947,8 @@ void Monitor::handle_command(MonOpRequestRef op) mdsmon()->dispatch(op); return; } - if (module == "osd" || prefix == "pg map") { + if ((module == "osd" || prefix == "pg map") && + prefix != "osd last-stat-seq") { osdmon()->dispatch(op); return; } @@ -2952,7 +2966,9 @@ void Monitor::handle_command(MonOpRequestRef op) prefix != "mon compact" && prefix != "mon scrub" && prefix != "mon sync force" && - prefix != "mon metadata") { + prefix != "mon metadata" && + prefix != "mon versions" && + prefix != "mon count-metadata") { monmon()->dispatch(op); return; } @@ -3068,10 +3084,10 @@ void Monitor::handle_command(MonOpRequestRef op) if (f) f->open_object_section("stats"); - pgmon()->pg_map.dump_fs_stats(&ds, f.get(), verbose); + pgservice->dump_fs_stats(&ds, f.get(), verbose); if (!f) ds << '\n'; - pgmon()->pg_map.dump_pool_stats(osdmon()->osdmap, &ds, f.get(), verbose); + pgservice->dump_pool_stats(osdmon()->osdmap, &ds, f.get(), verbose); if (f) { f->close_section(); @@ -3109,8 +3125,8 @@ void Monitor::handle_command(MonOpRequestRef op) monmon()->dump_info(f.get()); osdmon()->dump_info(f.get()); mdsmon()->dump_info(f.get()); - pgmon()->dump_info(f.get()); authmon()->dump_info(f.get()); + pgservice->dump_info(f.get()); paxos->dump_info(f.get()); @@ -3121,6 +3137,19 @@ void Monitor::handle_command(MonOpRequestRef op) ss2 << "report " << rdata.crc32c(CEPH_MON_PORT); rs = ss2.str(); r = 0; + } else if (prefix == "osd last-stat-seq") { + int64_t osd; + cmd_getval(g_ceph_context, cmdmap, "id", osd); + uint64_t seq = mgrstatmon()->get_last_osd_stat_seq(osd); + if (f) { + f->dump_unsigned("seq", seq); + f->flush(ds); + } else { + ds << seq; + rdata.append(ds); + } + rs = ""; + r = 0; } else if (prefix == "node ls") { string node_type("all"); cmd_getval(g_ceph_context, cmdmap, "type", node_type); @@ -3143,6 +3172,24 @@ void Monitor::handle_command(MonOpRequestRef op) rdata.append(ds); rs = ""; r = 0; + } else if (prefix == "features") { + if (!is_leader() && !is_peon()) { + dout(10) << " waiting for quorum" << dendl; + waitfor_quorum.push_back(new C_RetryMessage(this, op)); + return; + } + if (!is_leader()) { + forward_request_leader(op); + return; + } + if (!f) + f.reset(Formatter::create("json-pretty")); + FeatureMap fm; + get_combined_feature_map(&fm); + f->dump_object("features", fm); + f->flush(rdata); + rs = ""; + r = 0; } else if (prefix == "mon metadata") { if (!f) f.reset(Formatter::create("json-pretty")); @@ -3187,6 +3234,24 @@ void Monitor::handle_command(MonOpRequestRef op) f->flush(ds); rdata.append(ds); rs = ""; + } else if (prefix == "mon versions") { + if (!f) + f.reset(Formatter::create("json-pretty")); + count_metadata("ceph_version", f.get()); + f->flush(ds); + rdata.append(ds); + rs = ""; + r = 0; + } else if (prefix == "mon count-metadata") { + if (!f) + f.reset(Formatter::create("json-pretty")); + string field; + cmd_getval(g_ceph_context, cmdmap, "property", field); + count_metadata(field, f.get()); + f->flush(ds); + rdata.append(ds); + rs = ""; + r = 0; } else if (prefix == "quorum_status") { // make sure our map is readable and up to date if (!is_leader() && !is_peon()) { @@ -3816,10 +3881,15 @@ void Monitor::dispatch_op(MonOpRequestRef op) paxos_service[PAXOS_MGR]->dispatch(op); break; - // pg + // MgrStat + case MSG_MON_MGR_REPORT: case CEPH_MSG_STATFS: - case MSG_PGSTATS: case MSG_GETPOOLSTATS: + paxos_service[PAXOS_MGRSTAT]->dispatch(op); + break; + + // pg + case MSG_PGSTATS: paxos_service[PAXOS_PGMAP]->dispatch(op); break; @@ -4683,6 +4753,26 @@ int Monitor::get_mon_metadata(int mon, Formatter *f, ostream& err) return 0; } +void Monitor::count_metadata(const string& field, Formatter *f) +{ + map meta; + load_metadata(meta); + map by_val; + for (auto& p : meta) { + auto q = p.second.find(field); + if (q == p.second.end()) { + by_val["unknown"]++; + } else { + by_val[q->second]++; + } + } + f->open_object_section(field.c_str()); + for (auto& p : by_val) { + f->dump_int(p.first.c_str(), p.second); + } + f->close_section(); +} + int Monitor::print_nodes(Formatter *f, ostream& err) { map metadata; diff --git a/ceph/src/mon/Monitor.h b/ceph/src/mon/Monitor.h index 3f8b59508..a7a00642a 100644 --- a/ceph/src/mon/Monitor.h +++ b/ceph/src/mon/Monitor.h @@ -35,6 +35,7 @@ #include "Elector.h" #include "Paxos.h" #include "Session.h" +#include "PGStatService.h" #include "common/LogClient.h" #include "auth/cephx/CephxKeyServer.h" @@ -169,6 +170,8 @@ public: MgrClient mgr_client; uint64_t mgr_proxy_bytes = 0; // in-flight proxied mgr command message bytes + const MonPGStatService *pgservice; + private: void new_tick(); @@ -230,6 +233,11 @@ private: set quorum; // current active set of monitors (if !starting) utime_t leader_since; // when this monitor became the leader, if it is the leader utime_t exited_quorum; // time detected as not in quorum; 0 if in + + // map of counts of connected clients, by type and features, for + // each quorum mon + map quorum_feature_map; + /** * Intersection of quorum member's connection feature bits. */ @@ -571,6 +579,8 @@ public: void apply_monmap_to_compatset_features(); void calc_quorum_requirements(); + void get_combined_feature_map(FeatureMap *fm); + private: void _reset(); ///< called from bootstrap, start_, or join_election void wait_for_paxos_write(); @@ -632,6 +642,10 @@ public: return (class MgrMonitor*) paxos_service[PAXOS_MGR]; } + class MgrStatMonitor *mgrstatmon() { + return (class MgrStatMonitor*) paxos_service[PAXOS_MGRSTAT]; + } + friend class Paxos; friend class OSDMonitor; friend class MDSMonitor; @@ -861,6 +875,7 @@ public: void update_mon_metadata(int from, Metadata&& m); int load_metadata(map& m); + void count_metadata(const string& field, Formatter *f); // features static CompatSet get_initial_supported_features(); @@ -943,8 +958,6 @@ public: #define CEPH_MON_FEATURE_INCOMPAT_KRAKEN CompatSet::Feature(8, "support monmap features") // make sure you add your feature to Monitor::get_supported_features -long parse_pos_long(const char *s, ostream *pss = NULL); - struct MonCommand { string cmdstring; string helpstring; diff --git a/ceph/src/mon/MonitorDBStore.h b/ceph/src/mon/MonitorDBStore.h index e6732384c..707d635af 100644 --- a/ceph/src/mon/MonitorDBStore.h +++ b/ceph/src/mon/MonitorDBStore.h @@ -629,9 +629,13 @@ class MonitorDBStore int open(ostream &out) { string kv_type; int r = read_meta("kv_backend", &kv_type); - if (r < 0 || kv_type.length() == 0) + if (r < 0 || kv_type.empty()) { + // assume old monitors that did not mark the type were leveldb. kv_type = "leveldb"; - + r = write_meta("kv_backend", kv_type); + if (r < 0) + return r; + } _open(kv_type); r = db->open(out); if (r < 0) @@ -646,8 +650,7 @@ class MonitorDBStore string kv_type; int r = read_meta("kv_backend", &kv_type); if (r < 0) { - // assume old monitors that did not mark the type were leveldb. - kv_type = "leveldb"; + kv_type = g_conf->mon_keyvaluedb; r = write_meta("kv_backend", kv_type); if (r < 0) return r; diff --git a/ceph/src/mon/MonmapMonitor.cc b/ceph/src/mon/MonmapMonitor.cc index 6633009b3..b5ac990df 100644 --- a/ceph/src/mon/MonmapMonitor.cc +++ b/ceph/src/mon/MonmapMonitor.cc @@ -40,6 +40,14 @@ void MonmapMonitor::create_initial() dout(10) << "create_initial using current monmap" << dendl; pending_map = *mon->monmap; pending_map.epoch = 1; + + if (g_conf->mon_debug_no_initial_persistent_features) { + derr << __func__ << " mon_debug_no_initial_persistent_features=true" + << dendl; + } else { + // initialize with default persistent features for new clusters + pending_map.persistent_features = ceph::features::mon::get_persistent(); + } } void MonmapMonitor::update_from_paxos(bool *need_bootstrap) @@ -718,10 +726,6 @@ bool MonmapMonitor::should_propose(double& delay) return true; } -void MonmapMonitor::tick() -{ -} - void MonmapMonitor::get_health(list >& summary, list > *detail, CephContext *cct) const diff --git a/ceph/src/mon/MonmapMonitor.h b/ceph/src/mon/MonmapMonitor.h index c4a309768..99a2d9130 100644 --- a/ceph/src/mon/MonmapMonitor.h +++ b/ceph/src/mon/MonmapMonitor.h @@ -80,8 +80,6 @@ class MonmapMonitor : public PaxosService { */ bool should_propose(double& delay) override; - void tick() override; - void check_sub(Subscription *sub); private: diff --git a/ceph/src/mon/OSDMonitor.cc b/ceph/src/mon/OSDMonitor.cc index 9b82b4a9f..ddfeb2a29 100644 --- a/ceph/src/mon/OSDMonitor.cc +++ b/ceph/src/mon/OSDMonitor.cc @@ -19,13 +19,16 @@ #include #include -#include "OSDMonitor.h" -#include "Monitor.h" -#include "MDSMonitor.h" -#include "PGMonitor.h" +#include "mon/OSDMonitor.h" +#include "mon/Monitor.h" +#include "mon/MDSMonitor.h" +#include "mon/PGMonitor.h" +#include "mon/MgrStatMonitor.h" +#include "mon/AuthMonitor.h" +#include "mon/ConfigKeyService.h" -#include "MonitorDBStore.h" -#include "Session.h" +#include "mon/MonitorDBStore.h" +#include "mon/Session.h" #include "crush/CrushWrapper.h" #include "crush/CrushTester.h" @@ -220,17 +223,23 @@ void OSDMonitor::create_initial() newmap.set_flag(CEPH_OSDMAP_SORTBITWISE); // new cluster should require latest by default - newmap.set_flag(CEPH_OSDMAP_REQUIRE_JEWEL); - newmap.set_flag(CEPH_OSDMAP_REQUIRE_KRAKEN); - if (!g_conf->mon_debug_no_require_luminous) { - newmap.set_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS); + if (g_conf->mon_debug_no_require_luminous) { + newmap.require_osd_release = CEPH_RELEASE_KRAKEN; + derr << __func__ << " mon_debug_no_require_luminous=true" << dendl; + } else { + newmap.require_osd_release = CEPH_RELEASE_LUMINOUS; newmap.full_ratio = g_conf->mon_osd_full_ratio; if (newmap.full_ratio > 1.0) newmap.full_ratio /= 100; newmap.backfillfull_ratio = g_conf->mon_osd_backfillfull_ratio; if (newmap.backfillfull_ratio > 1.0) newmap.backfillfull_ratio /= 100; newmap.nearfull_ratio = g_conf->mon_osd_nearfull_ratio; if (newmap.nearfull_ratio > 1.0) newmap.nearfull_ratio /= 100; - newmap.require_min_compat_client = g_conf->mon_osd_initial_require_min_compat_client; + int r = ceph_release_from_name( + g_conf->mon_osd_initial_require_min_compat_client.c_str()); + if (r <= 0) { + assert(0 == "mon_osd_initial_require_min_compat_client is not valid"); + } + newmap.require_min_compat_client = r; } // encode into pending incremental @@ -256,6 +265,15 @@ void OSDMonitor::update_from_paxos(bool *need_bootstrap) dout(15) << "update_from_paxos paxos e " << version << ", my e " << osdmap.epoch << dendl; + if (mapping_job) { + if (!mapping_job->is_done()) { + dout(1) << __func__ << " mapping job " + << mapping_job.get() << " did not complete, " + << mapping_job->shards << " left, canceling" << dendl; + mapping_job->abort(); + } + mapping_job.reset(); + } /* * We will possibly have a stashed latest that *we* wrote, and we will @@ -325,6 +343,15 @@ void OSDMonitor::update_from_paxos(bool *need_bootstrap) } } + // make sure we're using the right pg service.. remove me post-luminous! + if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + dout(10) << __func__ << " pgservice is mgrstat" << dendl; + mon->pgservice = mon->mgrstatmon()->get_pg_stat_service(); + } else { + dout(10) << __func__ << " pgservice is pg" << dendl; + mon->pgservice = mon->pgmon()->get_pg_stat_service(); + } + // walk through incrementals MonitorDBStore::TransactionRef t; size_t tx_size = 0; @@ -386,6 +413,15 @@ void OSDMonitor::update_from_paxos(bool *need_bootstrap) t->erase("mkfs", "osdmap"); } + // make sure we're using the right pg service.. remove me post-luminous! + if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + dout(10) << __func__ << " pgservice is mgrstat" << dendl; + mon->pgservice = mon->mgrstatmon()->get_pg_stat_service(); + } else { + dout(10) << __func__ << " pgservice is pg" << dendl; + mon->pgservice = mon->pgmon()->get_pg_stat_service(); + } + if (tx_size > g_conf->mon_sync_max_payload_size*2) { mon->store->apply_transaction(t); t = MonitorDBStore::TransactionRef(); @@ -393,7 +429,6 @@ void OSDMonitor::update_from_paxos(bool *need_bootstrap) } if (mon->monmap->get_required_features().contains_all( ceph::features::mon::FEATURE_LUMINOUS)) { - creating_pgs = update_pending_pgs(inc); for (const auto &osd_state : inc.new_state) { if (osd_state.second & CEPH_OSD_UP) { // could be marked up *or* down, but we're too lazy to check which @@ -509,6 +544,23 @@ void OSDMonitor::on_active() void OSDMonitor::on_restart() { last_osd_report.clear(); + + if (mon->is_leader()) { + // fix ruleset != ruleid + if (osdmap.crush->has_legacy_rulesets() && + !osdmap.crush->has_multirule_rulesets()) { + CrushWrapper newcrush; + _get_pending_crush(newcrush); + int r = newcrush.renumber_rules_by_ruleset(); + if (r >= 0) { + dout(1) << __func__ << " crush map has ruleset != rule id; fixing" << dendl; + pending_inc.crush.clear(); + newcrush.encode(pending_inc.crush, mon->get_quorum_con_features()); + } else { + dout(10) << __func__ << " unable to renumber rules by ruleset" << dendl; + } + } + } } void OSDMonitor::on_shutdown() @@ -536,326 +588,6 @@ void OSDMonitor::update_logger() mon->cluster_logger->set(l_cluster_osd_epoch, osdmap.get_epoch()); } -template -class OSDUtilizationDumper : public CrushTreeDumper::Dumper { -public: - typedef CrushTreeDumper::Dumper Parent; - - OSDUtilizationDumper(const CrushWrapper *crush, const OSDMap *osdmap_, - const PGMap *pgm_, bool tree_) : - Parent(crush), - osdmap(osdmap_), - pgm(pgm_), - tree(tree_), - average_util(average_utilization()), - min_var(-1), - max_var(-1), - stddev(0), - sum(0) { - } - -protected: - void dump_stray(F *f) { - for (int i = 0; i < osdmap->get_max_osd(); i++) { - if (osdmap->exists(i) && !this->is_touched(i)) - dump_item(CrushTreeDumper::Item(i, 0, 0), f); - } - } - - void dump_item(const CrushTreeDumper::Item &qi, F *f) override { - if (!tree && qi.is_bucket()) - return; - - float reweight = qi.is_bucket() ? -1 : osdmap->get_weightf(qi.id); - int64_t kb = 0, kb_used = 0, kb_avail = 0; - double util = 0; - if (get_bucket_utilization(qi.id, &kb, &kb_used, &kb_avail)) - if (kb_used && kb) - util = 100.0 * (double)kb_used / (double)kb; - - double var = 1.0; - if (average_util) - var = util / average_util; - - size_t num_pgs = qi.is_bucket() ? 0 : pgm->get_num_pg_by_osd(qi.id); - - dump_item(qi, reweight, kb, kb_used, kb_avail, util, var, num_pgs, f); - - if (!qi.is_bucket() && reweight > 0) { - if (min_var < 0 || var < min_var) - min_var = var; - if (max_var < 0 || var > max_var) - max_var = var; - - double dev = util - average_util; - dev *= dev; - stddev += reweight * dev; - sum += reweight; - } - } - - virtual void dump_item(const CrushTreeDumper::Item &qi, - float &reweight, - int64_t kb, - int64_t kb_used, - int64_t kb_avail, - double& util, - double& var, - const size_t num_pgs, - F *f) = 0; - - double dev() { - return sum > 0 ? sqrt(stddev / sum) : 0; - } - - double average_utilization() { - int64_t kb = 0, kb_used = 0; - for (int i = 0; i < osdmap->get_max_osd(); i++) { - if (!osdmap->exists(i) || osdmap->get_weight(i) == 0) - continue; - int64_t kb_i, kb_used_i, kb_avail_i; - if (get_osd_utilization(i, &kb_i, &kb_used_i, &kb_avail_i)) { - kb += kb_i; - kb_used += kb_used_i; - } - } - return kb > 0 ? 100.0 * (double)kb_used / (double)kb : 0; - } - - bool get_osd_utilization(int id, int64_t* kb, int64_t* kb_used, - int64_t* kb_avail) const { - typedef ceph::unordered_map OsdStat; - OsdStat::const_iterator p = pgm->osd_stat.find(id); - if (p == pgm->osd_stat.end()) - return false; - *kb = p->second.kb; - *kb_used = p->second.kb_used; - *kb_avail = p->second.kb_avail; - return *kb > 0; - } - - bool get_bucket_utilization(int id, int64_t* kb, int64_t* kb_used, - int64_t* kb_avail) const { - if (id >= 0) { - if (osdmap->is_out(id)) { - *kb = 0; - *kb_used = 0; - *kb_avail = 0; - return true; - } - return get_osd_utilization(id, kb, kb_used, kb_avail); - } - - *kb = 0; - *kb_used = 0; - *kb_avail = 0; - - for (int k = osdmap->crush->get_bucket_size(id) - 1; k >= 0; k--) { - int item = osdmap->crush->get_bucket_item(id, k); - int64_t kb_i = 0, kb_used_i = 0, kb_avail_i = 0; - if (!get_bucket_utilization(item, &kb_i, &kb_used_i, &kb_avail_i)) - return false; - *kb += kb_i; - *kb_used += kb_used_i; - *kb_avail += kb_avail_i; - } - return *kb > 0; - } - -protected: - const OSDMap *osdmap; - const PGMap *pgm; - bool tree; - double average_util; - double min_var; - double max_var; - double stddev; - double sum; -}; - -class OSDUtilizationPlainDumper : public OSDUtilizationDumper { -public: - typedef OSDUtilizationDumper Parent; - - OSDUtilizationPlainDumper(const CrushWrapper *crush, const OSDMap *osdmap, - const PGMap *pgm, bool tree) : - Parent(crush, osdmap, pgm, tree) {} - - void dump(TextTable *tbl) { - tbl->define_column("ID", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("WEIGHT", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("REWEIGHT", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("SIZE", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("USE", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("%USE", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("VAR", TextTable::LEFT, TextTable::RIGHT); - tbl->define_column("PGS", TextTable::LEFT, TextTable::RIGHT); - if (tree) - tbl->define_column("TYPE NAME", TextTable::LEFT, TextTable::LEFT); - - Parent::dump(tbl); - - dump_stray(tbl); - - *tbl << "" << "" << "TOTAL" - << si_t(pgm->osd_sum.kb << 10) - << si_t(pgm->osd_sum.kb_used << 10) - << si_t(pgm->osd_sum.kb_avail << 10) - << lowprecision_t(average_util) - << "" - << TextTable::endrow; - } - -protected: - struct lowprecision_t { - float v; - explicit lowprecision_t(float _v) : v(_v) {} - }; - friend std::ostream &operator<<(ostream& out, const lowprecision_t& v); - - using OSDUtilizationDumper::dump_item; - void dump_item(const CrushTreeDumper::Item &qi, - float &reweight, - int64_t kb, - int64_t kb_used, - int64_t kb_avail, - double& util, - double& var, - const size_t num_pgs, - TextTable *tbl) override { - *tbl << qi.id - << weightf_t(qi.weight) - << weightf_t(reweight) - << si_t(kb << 10) - << si_t(kb_used << 10) - << si_t(kb_avail << 10) - << lowprecision_t(util) - << lowprecision_t(var); - - if (qi.is_bucket()) { - *tbl << "-"; - } else { - *tbl << num_pgs; - } - - if (tree) { - ostringstream name; - for (int k = 0; k < qi.depth; k++) - name << " "; - if (qi.is_bucket()) { - int type = crush->get_bucket_type(qi.id); - name << crush->get_type_name(type) << " " - << crush->get_item_name(qi.id); - } else { - name << "osd." << qi.id; - } - *tbl << name.str(); - } - - *tbl << TextTable::endrow; - } - -public: - string summary() { - ostringstream out; - out << "MIN/MAX VAR: " << lowprecision_t(min_var) - << "/" << lowprecision_t(max_var) << " " - << "STDDEV: " << lowprecision_t(dev()); - return out.str(); - } -}; - -ostream& operator<<(ostream& out, - const OSDUtilizationPlainDumper::lowprecision_t& v) -{ - if (v.v < -0.01) { - return out << "-"; - } else if (v.v < 0.001) { - return out << "0"; - } else { - std::streamsize p = out.precision(); - return out << std::fixed << std::setprecision(2) << v.v << std::setprecision(p); - } -} - -class OSDUtilizationFormatDumper : public OSDUtilizationDumper { -public: - typedef OSDUtilizationDumper Parent; - - OSDUtilizationFormatDumper(const CrushWrapper *crush, const OSDMap *osdmap, - const PGMap *pgm, bool tree) : - Parent(crush, osdmap, pgm, tree) {} - - void dump(Formatter *f) { - f->open_array_section("nodes"); - Parent::dump(f); - f->close_section(); - - f->open_array_section("stray"); - dump_stray(f); - f->close_section(); - } - -protected: - using OSDUtilizationDumper::dump_item; - void dump_item(const CrushTreeDumper::Item &qi, - float &reweight, - int64_t kb, - int64_t kb_used, - int64_t kb_avail, - double& util, - double& var, - const size_t num_pgs, - Formatter *f) override { - f->open_object_section("item"); - CrushTreeDumper::dump_item_fields(crush, qi, f); - f->dump_float("reweight", reweight); - f->dump_int("kb", kb); - f->dump_int("kb_used", kb_used); - f->dump_int("kb_avail", kb_avail); - f->dump_float("utilization", util); - f->dump_float("var", var); - f->dump_unsigned("pgs", num_pgs); - CrushTreeDumper::dump_bucket_children(crush, qi, f); - f->close_section(); - } - -public: - void summary(Formatter *f) { - f->open_object_section("summary"); - f->dump_int("total_kb", pgm->osd_sum.kb); - f->dump_int("total_kb_used", pgm->osd_sum.kb_used); - f->dump_int("total_kb_avail", pgm->osd_sum.kb_avail); - f->dump_float("average_utilization", average_util); - f->dump_float("min_var", min_var); - f->dump_float("max_var", max_var); - f->dump_float("dev", dev()); - f->close_section(); - } -}; - -void OSDMonitor::print_utilization(ostream &out, Formatter *f, bool tree) const -{ - const PGMap *pgm = &mon->pgmon()->pg_map; - const CrushWrapper *crush = osdmap.crush.get(); - - if (f) { - f->open_object_section("df"); - OSDUtilizationFormatDumper d(crush, &osdmap, pgm, tree); - d.dump(f); - d.summary(f); - f->close_section(); - f->flush(out); - } else { - OSDUtilizationPlainDumper d(crush, &osdmap, pgm, tree); - TextTable tbl; - d.dump(&tbl); - out << tbl - << d.summary() << "\n"; - } -} - void OSDMonitor::create_pending() { pending_inc = OSDMap::Incremental(osdmap.epoch+1); @@ -876,18 +608,20 @@ void OSDMonitor::create_pending() dout(1) << __func__ << " setting backfillfull_ratio = " << pending_inc.new_backfillfull_ratio << dendl; } - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (osdmap.get_epoch() > 0 && + osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { // transition full ratios from PGMap to OSDMap (on upgrade) - PGMap *pg_map = &mon->pgmon()->pg_map; - if (osdmap.full_ratio != pg_map->full_ratio) { + float full_ratio = mon->pgservice->get_full_ratio(); + float nearfull_ratio = mon->pgservice->get_nearfull_ratio(); + if (osdmap.full_ratio != full_ratio) { dout(10) << __func__ << " full_ratio " << osdmap.full_ratio - << " -> " << pg_map->full_ratio << " (from pgmap)" << dendl; - pending_inc.new_full_ratio = pg_map->full_ratio; + << " -> " << full_ratio << " (from pgmap)" << dendl; + pending_inc.new_full_ratio = full_ratio; } - if (osdmap.nearfull_ratio != pg_map->nearfull_ratio) { + if (osdmap.nearfull_ratio != nearfull_ratio) { dout(10) << __func__ << " nearfull_ratio " << osdmap.nearfull_ratio - << " -> " << pg_map->nearfull_ratio << " (from pgmap)" << dendl; - pending_inc.new_nearfull_ratio = pg_map->nearfull_ratio; + << " -> " << nearfull_ratio << " (from pgmap)" << dendl; + pending_inc.new_nearfull_ratio = nearfull_ratio; } } else { // safety check (this shouldn't really happen) @@ -911,51 +645,93 @@ void OSDMonitor::create_pending() creating_pgs_t OSDMonitor::update_pending_pgs(const OSDMap::Incremental& inc) { + dout(10) << __func__ << dendl; creating_pgs_t pending_creatings; { std::lock_guard l(creating_pgs_lock); pending_creatings = creating_pgs; } - if (pending_creatings.last_scan_epoch > inc.epoch) { - return pending_creatings; - } - for (auto& pg : pending_created_pgs) { - pending_creatings.created_pools.insert(pg.pool()); - pending_creatings.pgs.erase(pg); - } - pending_created_pgs.clear(); - // PAXOS_PGMAP is less than PAXOS_OSDMAP, so PGMonitor::update_from_paxos() - // should have prepared the latest pgmap if any - const auto& pgm = mon->pgmon()->pg_map; - if (pgm.last_pg_scan >= creating_pgs.last_scan_epoch) { - // TODO: please stop updating pgmap with pgstats once the upgrade is completed - for (auto& pgid : pgm.creating_pgs) { - auto st = pgm.pg_stat.find(pgid); - assert(st != pgm.pg_stat.end()); - auto created = make_pair(st->second.created, st->second.last_scrub_stamp); - // no need to add the pg, if it already exists in creating_pgs - pending_creatings.pgs.emplace(pgid, created); - } - } - for (auto old_pool : inc.old_pools) { - pending_creatings.created_pools.erase(old_pool); - const auto removed_pool = (uint64_t)old_pool; - auto first = - pending_creatings.pgs.lower_bound(pg_t{0, removed_pool}); - auto last = - pending_creatings.pgs.lower_bound(pg_t{0, removed_pool + 1}); - pending_creatings.pgs.erase(first, last); - last_epoch_clean.remove_pool(removed_pool); - } - scan_for_creating_pgs(osdmap.get_pools(), - inc.old_pools, - inc.modified, - &pending_creatings); - scan_for_creating_pgs(inc.new_pools, - inc.old_pools, - inc.modified, - &pending_creatings); - pending_creatings.last_scan_epoch = osdmap.get_epoch(); + // check for new or old pools + if (pending_creatings.last_scan_epoch < inc.epoch) { + if (osdmap.get_epoch() && + osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + auto added = + mon->pgservice->maybe_add_creating_pgs(creating_pgs.last_scan_epoch, + osdmap.get_pools(), + &pending_creatings); + dout(7) << __func__ << " " << added << " pgs added from pgmap" << dendl; + } + unsigned queued = 0; + queued += scan_for_creating_pgs(osdmap.get_pools(), + inc.old_pools, + inc.modified, + &pending_creatings); + queued += scan_for_creating_pgs(inc.new_pools, + inc.old_pools, + inc.modified, + &pending_creatings); + dout(10) << __func__ << " " << queued << " pools queued" << dendl; + for (auto deleted_pool : inc.old_pools) { + auto removed = pending_creatings.remove_pool(deleted_pool); + dout(10) << __func__ << " " << removed + << " pg removed because containing pool deleted: " + << deleted_pool << dendl; + last_epoch_clean.remove_pool(deleted_pool); + } + // pgmon updates its creating_pgs in check_osd_map() which is called by + // on_active() and check_osd_map() could be delayed if lease expires, so its + // creating_pgs could be stale in comparison with the one of osdmon. let's + // trim them here. otherwise, they will be added back after being erased. + unsigned removed = 0; + for (auto& pg : pending_created_pgs) { + dout(20) << __func__ << " noting created pg " << pg << dendl; + pending_creatings.created_pools.insert(pg.pool()); + removed += pending_creatings.pgs.erase(pg); + } + pending_created_pgs.clear(); + dout(10) << __func__ << " " << removed + << " pgs removed because they're created" << dendl; + pending_creatings.last_scan_epoch = osdmap.get_epoch(); + } + + // process queue + unsigned max = MAX(1, g_conf->mon_osd_max_creating_pgs); + const auto total = pending_creatings.pgs.size(); + while (pending_creatings.pgs.size() < max && + !pending_creatings.queue.empty()) { + auto p = pending_creatings.queue.begin(); + int64_t poolid = p->first; + dout(10) << __func__ << " pool " << poolid + << " created " << p->second.created + << " modified " << p->second.modified + << " [" << p->second.start << "-" << p->second.end << ")" + << dendl; + int n = MIN(max - pending_creatings.pgs.size(), + p->second.end - p->second.start); + ps_t first = p->second.start; + ps_t end = first + n; + for (ps_t ps = first; ps < end; ++ps) { + const pg_t pgid{ps, static_cast(poolid)}; + // NOTE: use the *current* epoch as the PG creation epoch so that the + // OSD does not have to generate a long set of PastIntervals. + pending_creatings.pgs.emplace(pgid, make_pair(inc.epoch, + p->second.modified)); + dout(10) << __func__ << " adding " << pgid << dendl; + } + p->second.start = end; + if (p->second.done()) { + dout(10) << __func__ << " done with queue for " << poolid << dendl; + pending_creatings.queue.erase(p); + } else { + dout(10) << __func__ << " pool " << poolid + << " now [" << p->second.start << "-" << p->second.end << ")" + << dendl; + } + } + dout(10) << __func__ << " queue remaining: " << pending_creatings.queue.size() + << " pools" << dendl; + dout(10) << __func__ << " " << pending_creatings.pgs.size() - total + << " pgs added from queued pools" << dendl; return pending_creatings; } @@ -974,7 +750,7 @@ void OSDMonitor::maybe_prime_pg_temp() // check for interesting OSDs set osds; - for (map::iterator p = pending_inc.new_state.begin(); + for (auto p = pending_inc.new_state.begin(); !all && p != pending_inc.new_state.end(); ++p) { if ((p->second & CEPH_OSD_UP) && @@ -1066,12 +842,12 @@ void OSDMonitor::prime_pg_temp( { if (mon->monmap->get_required_features().contains_all( ceph::features::mon::FEATURE_LUMINOUS)) { + // TODO: remove this creating_pgs direct access? if (creating_pgs.pgs.count(pgid)) { return; } } else { - const auto& pg_map = mon->pgmon()->pg_map; - if (pg_map.creating_pgs.count(pgid)) { + if (mon->pgservice->is_creating_pg(pgid)) { return; } } @@ -1151,7 +927,7 @@ void OSDMonitor::encode_pending(MonitorDBStore::TransactionRef t) tmp.deepish_copy_from(osdmap); tmp.apply_incremental(pending_inc); - if (tmp.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (tmp.require_osd_release >= CEPH_RELEASE_LUMINOUS) { // set or clear full/nearfull? int full, backfill, nearfull; tmp.count_full_nearfull_osds(&full, &backfill, &nearfull); @@ -1180,19 +956,19 @@ void OSDMonitor::encode_pending(MonitorDBStore::TransactionRef t) } // min_compat_client? - if (tmp.require_min_compat_client.empty()) { + if (tmp.require_min_compat_client == 0) { auto mv = tmp.get_min_compat_client(); - dout(1) << __func__ << " setting require_min_compat_client to current " << mv - << dendl; - mon->clog->info() << "setting require_min_compat_client to currently required " - << mv; - pending_inc.new_require_min_compat_client = mv.first; + dout(1) << __func__ << " setting require_min_compat_client to currently " + << "required " << ceph_release_name(mv) << dendl; + mon->clog->info() << "setting require_min_compat_client to currently " + << "required " << ceph_release_name(mv); + pending_inc.new_require_min_compat_client = mv; } } } // tell me about it - for (map::iterator i = pending_inc.new_state.begin(); + for (auto i = pending_inc.new_state.begin(); i != pending_inc.new_state.end(); ++i) { int s = i->second ? i->second : CEPH_OSD_UP; @@ -1229,21 +1005,21 @@ void OSDMonitor::encode_pending(MonitorDBStore::TransactionRef t) tmp.apply_incremental(pending_inc); // determine appropriate features - if (!tmp.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (tmp.require_osd_release < CEPH_RELEASE_LUMINOUS) { dout(10) << __func__ << " encoding without feature SERVER_LUMINOUS" << dendl; features &= ~CEPH_FEATURE_SERVER_LUMINOUS; } - if (!tmp.test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { - dout(10) << __func__ << " encoding without feature SERVER_JEWEL" << dendl; - features &= ~CEPH_FEATURE_SERVER_JEWEL; - } - if (!tmp.test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + if (tmp.require_osd_release < CEPH_RELEASE_KRAKEN) { dout(10) << __func__ << " encoding without feature SERVER_KRAKEN | " << "MSG_ADDR2" << dendl; features &= ~(CEPH_FEATURE_SERVER_KRAKEN | CEPH_FEATURE_MSG_ADDR2); } + if (tmp.require_osd_release < CEPH_RELEASE_JEWEL) { + dout(10) << __func__ << " encoding without feature SERVER_JEWEL" << dendl; + features &= ~CEPH_FEATURE_SERVER_JEWEL; + } dout(10) << __func__ << " encoding full map with " << features << dendl; bufferlist fullbl; @@ -1283,10 +1059,11 @@ void OSDMonitor::encode_pending(MonitorDBStore::TransactionRef t) if (mon->monmap->get_required_features().contains_all( ceph::features::mon::FEATURE_LUMINOUS)) { auto pending_creatings = update_pending_pgs(pending_inc); - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (osdmap.get_epoch() && + osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { dout(7) << __func__ << " in the middle of upgrading, " << " trimming pending creating_pgs using pgmap" << dendl; - trim_creating_pgs(&pending_creatings, mon->pgmon()->pg_map); + mon->pgservice->maybe_trim_creating_pgs(&pending_creatings); } bufferlist creatings_bl; ::encode(pending_creatings, creatings_bl); @@ -1295,17 +1072,16 @@ void OSDMonitor::encode_pending(MonitorDBStore::TransactionRef t) } void OSDMonitor::trim_creating_pgs(creating_pgs_t* creating_pgs, - const PGMap& pgm) + const ceph::unordered_map& pg_stat) { auto p = creating_pgs->pgs.begin(); while (p != creating_pgs->pgs.end()) { - auto q = pgm.pg_stat.find(p->first); - if (q != pgm.pg_stat.end() && + auto q = pg_stat.find(p->first); + if (q != pg_stat.end() && !(q->second.state & PG_STATE_CREATING)) { dout(20) << __func__ << " pgmap shows " << p->first << " is created" << dendl; p = creating_pgs->pgs.erase(p); - creating_pgs->created_pools.insert(q->first.pool()); } else { ++p; } @@ -1330,6 +1106,28 @@ int OSDMonitor::load_metadata(int osd, map& m, ostream *err) return 0; } +void OSDMonitor::count_metadata(const string& field, Formatter *f) +{ + map by_val; + for (int osd = 0; osd < osdmap.get_max_osd(); ++osd) { + if (osdmap.is_up(osd)) { + map meta; + load_metadata(osd, meta, nullptr); + auto p = meta.find(field); + if (p == meta.end()) { + by_val["unknown"]++; + } else { + by_val[p->second]++; + } + } + } + f->open_object_section(field.c_str()); + for (auto& p : by_val) { + f->dump_int(p.first.c_str(), p.second); + } + f->close_section(); +} + int OSDMonitor::get_osd_objectstore_type(int osd, string *type) { map metadata; @@ -1425,11 +1223,16 @@ void OSDMonitor::share_map_with_random_osd() version_t OSDMonitor::get_trim_to() { - epoch_t floor; + if (mon->get_quorum().empty()) { + dout(10) << __func__ << ": quorum not formed" << dendl; + return 0; + } + epoch_t floor; if (mon->monmap->get_required_features().contains_all( ceph::features::mon::FEATURE_LUMINOUS)) { { + // TODO: Get this hidden in PGStatService std::lock_guard l(creating_pgs_lock); if (!creating_pgs.pgs.empty()) { return 0; @@ -1437,12 +1240,12 @@ version_t OSDMonitor::get_trim_to() } floor = get_min_last_epoch_clean(); } else { - if (!mon->pgmon()->is_readable()) + if (!mon->pgservice->is_readable()) return 0; - if (mon->pgmon()->pg_map.creating_pgs.empty()) { + if (mon->pgservice->have_creating_pgs()) { return 0; } - floor = mon->pgmon()->pg_map.get_min_last_epoch_clean(); + floor = mon->pgservice->get_min_last_epoch_clean(); } { dout(10) << " min_last_epoch_clean " << floor << dendl; @@ -1807,18 +1610,26 @@ bool OSDMonitor::prepare_mark_me_down(MonOpRequestRef op) bool OSDMonitor::can_mark_down(int i) { if (osdmap.test_flag(CEPH_OSDMAP_NODOWN)) { - dout(5) << "can_mark_down NODOWN flag set, will not mark osd." << i << " down" << dendl; + dout(5) << __func__ << " NODOWN flag set, will not mark osd." << i + << " down" << dendl; + return false; + } + + if (osdmap.is_nodown(i)) { + dout(5) << __func__ << " osd." << i << " is marked as nodown, " + << "will not mark it down" << dendl; return false; } + int num_osds = osdmap.get_num_osds(); if (num_osds == 0) { - dout(5) << "can_mark_down no osds" << dendl; + dout(5) << __func__ << " no osds" << dendl; return false; } int up = osdmap.get_num_up_osds() - pending_inc.get_net_marked_down(&osdmap); float up_ratio = (float)up / (float)num_osds; if (up_ratio < g_conf->mon_osd_min_up_ratio) { - dout(2) << "can_mark_down current up_ratio " << up_ratio << " < min " + dout(2) << __func__ << " current up_ratio " << up_ratio << " < min " << g_conf->mon_osd_min_up_ratio << ", will not mark osd." << i << " down" << dendl; return false; @@ -1829,9 +1640,17 @@ bool OSDMonitor::can_mark_down(int i) bool OSDMonitor::can_mark_up(int i) { if (osdmap.test_flag(CEPH_OSDMAP_NOUP)) { - dout(5) << "can_mark_up NOUP flag set, will not mark osd." << i << " up" << dendl; + dout(5) << __func__ << " NOUP flag set, will not mark osd." << i + << " up" << dendl; + return false; + } + + if (osdmap.is_noup(i)) { + dout(5) << __func__ << " osd." << i << " is marked as noup, " + << "will not mark it up" << dendl; return false; } + return true; } @@ -1845,6 +1664,13 @@ bool OSDMonitor::can_mark_out(int i) dout(5) << __func__ << " NOOUT flag set, will not mark osds out" << dendl; return false; } + + if (osdmap.is_noout(i)) { + dout(5) << __func__ << " osd." << i << " is marked as noout, " + << "will not mark it out" << dendl; + return false; + } + int num_osds = osdmap.get_num_osds(); if (num_osds == 0) { dout(5) << __func__ << " no osds" << dendl; @@ -1870,9 +1696,17 @@ bool OSDMonitor::can_mark_out(int i) bool OSDMonitor::can_mark_in(int i) { if (osdmap.test_flag(CEPH_OSDMAP_NOIN)) { - dout(5) << "can_mark_in NOIN flag set, will not mark osd." << i << " in" << dendl; + dout(5) << __func__ << " NOIN flag set, will not mark osd." << i + << " in" << dendl; + return false; + } + + if (osdmap.is_noin(i)) { + dout(5) << __func__ << " osd." << i << " is marked as noin, " + << "will not mark it in" << dendl; return false; } + return true; } @@ -1964,8 +1798,12 @@ bool OSDMonitor::check_failure(utime_t now, int target_osd, failure_info_t& fi) << " down" << dendl; pending_inc.new_state[target_osd] = CEPH_OSD_UP; - mon->clog->info() << osdmap.get_inst(target_osd) << " failed (" - << (int)reporters_by_subtree.size() << " reporters from different " + mon->clog->info() << "osd." << target_osd << " failed (" + << osdmap.crush->get_full_location_ordered_string( + target_osd) + << ") (" + << (int)reporters_by_subtree.size() + << " reporters from different " << reporter_subtree_level << " after " << failed_for << " >= grace " << grace << ")"; return true; @@ -1973,7 +1811,7 @@ bool OSDMonitor::check_failure(utime_t now, int target_osd, failure_info_t& fi) return false; } -void OSDMonitor::force_failure(utime_t now, int target_osd) +void OSDMonitor::force_failure(utime_t now, int target_osd, int by) { // already pending failure? if (pending_inc.new_state.count(target_osd) && @@ -1985,7 +1823,9 @@ void OSDMonitor::force_failure(utime_t now, int target_osd) dout(1) << " we're forcing failure of osd." << target_osd << dendl; pending_inc.new_state[target_osd] = CEPH_OSD_UP; - mon->clog->info() << osdmap.get_inst(target_osd) << " failed (forced)"; + mon->clog->info() << "osd." << target_osd << " failed (" + << osdmap.crush->get_full_location_ordered_string(target_osd) + << ") (connection refused reported by osd." << by << ")"; return; } @@ -2012,7 +1852,7 @@ bool OSDMonitor::prepare_failure(MonOpRequestRef op) if (m->is_immediate()) { mon->clog->debug() << m->get_target() << " reported immediately failed by " << m->get_orig_source_inst(); - force_failure(now, target_osd); + force_failure(now, target_osd, reporter); return true; } mon->clog->debug() << m->get_target() << " reported failed by " @@ -2149,7 +1989,7 @@ bool OSDMonitor::preprocess_boot(MonOpRequestRef op) goto ignore; } - if (osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS) && + if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS && !HAVE_FEATURE(m->osd_features, SERVER_LUMINOUS)) { mon->clog->info() << "disallowing boot of OSD " << m->get_orig_source_inst() @@ -2159,7 +1999,7 @@ bool OSDMonitor::preprocess_boot(MonOpRequestRef op) goto ignore; } - if (osdmap.test_flag(CEPH_OSDMAP_REQUIRE_JEWEL) && + if (osdmap.require_osd_release >= CEPH_RELEASE_JEWEL && !(m->osd_features & CEPH_FEATURE_SERVER_JEWEL)) { mon->clog->info() << "disallowing boot of OSD " << m->get_orig_source_inst() @@ -2169,7 +2009,7 @@ bool OSDMonitor::preprocess_boot(MonOpRequestRef op) goto ignore; } - if (osdmap.test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN) && + if (osdmap.require_osd_release >= CEPH_RELEASE_KRAKEN && !HAVE_FEATURE(m->osd_features, SERVER_KRAKEN)) { mon->clog->info() << "disallowing boot of OSD " << m->get_orig_source_inst() @@ -2203,19 +2043,19 @@ bool OSDMonitor::preprocess_boot(MonOpRequestRef op) // make sure upgrades stop at luminous if (HAVE_FEATURE(m->osd_features, SERVER_M) && - !osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { mon->clog->info() << "disallowing boot of post-luminous OSD " << m->get_orig_source_inst() - << " because require_luminous_osds is not set"; + << " because require_osd_release < luminous"; goto ignore; } // make sure upgrades stop at jewel if (HAVE_FEATURE(m->osd_features, SERVER_KRAKEN) && - !osdmap.test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + osdmap.require_osd_release < CEPH_RELEASE_JEWEL) { mon->clog->info() << "disallowing boot of post-jewel OSD " << m->get_orig_source_inst() - << " because require_jewel_osds is not set"; + << " because require_osd_release < jewel"; goto ignore; } @@ -2362,6 +2202,7 @@ bool OSDMonitor::prepare_boot(MonOpRequestRef op) bufferlist osd_metadata; ::encode(m->metadata, osd_metadata); pending_metadata[from] = osd_metadata; + pending_metadata_rm.erase(from); // adjust last clean unmount epoch? const osd_info_t& info = osdmap.get_info(from); @@ -2674,7 +2515,7 @@ bool OSDMonitor::preprocess_pgtemp(MonOpRequestRef op) for (auto p = m->pg_temp.begin(); p != m->pg_temp.end(); ++p) { dout(20) << " " << p->first - << (osdmap.pg_temp->count(p->first) ? (*osdmap.pg_temp)[p->first] : empty) + << (osdmap.pg_temp->count(p->first) ? osdmap.pg_temp->get(p->first) : empty) << " -> " << p->second << dendl; // does the pool exist? @@ -2718,7 +2559,7 @@ bool OSDMonitor::preprocess_pgtemp(MonOpRequestRef op) // an existing pg_primary field to imply a change if (p->second.size() && (osdmap.pg_temp->count(p->first) == 0 || - !vectors_equal((*osdmap.pg_temp)[p->first], p->second) || + !vectors_equal(osdmap.pg_temp->get(p->first), p->second) || osdmap.primary_temp->count(p->first))) return false; } @@ -3007,7 +2848,7 @@ void OSDMonitor::send_incremental(epoch_t first, << " to " << session->inst << dendl; if (first <= session->osd_epoch) { - dout(10) << __func__ << session->inst << " should already have epoch " + dout(10) << __func__ << " " << session->inst << " should already have epoch " << session->osd_epoch << dendl; first = session->osd_epoch + 1; } @@ -3159,16 +3000,17 @@ void OSDMonitor::check_pg_creates_sub(Subscription *sub) } } -void OSDMonitor::scan_for_creating_pgs( +unsigned OSDMonitor::scan_for_creating_pgs( const mempool::osdmap::map& pools, const mempool::osdmap::set& removed_pools, utime_t modified, creating_pgs_t* creating_pgs) const { + unsigned queued = 0; for (auto& p : pools) { int64_t poolid = p.first; const pg_pool_t& pool = p.second; - int ruleno = osdmap.crush->find_rule(pool.get_crush_ruleset(), + int ruleno = osdmap.crush->find_rule(pool.get_crush_rule(), pool.get_type(), pool.get_size()); if (ruleno < 0 || !osdmap.crush->rule_exists(ruleno)) continue; @@ -3185,34 +3027,27 @@ void OSDMonitor::scan_for_creating_pgs( << " " << pool << dendl; continue; } - dout(10) << __func__ << " scanning pool " << poolid + dout(10) << __func__ << " queueing pool create for " << poolid << " " << pool << dendl; - if (creating_pgs->created_pools.count(poolid)) { - // split pgs are skipped by OSD, so drop it early. - continue; - } - // first pgs in this pool - for (ps_t ps = 0; ps < pool.get_pg_num(); ps++) { - const pg_t pgid{ps, static_cast(poolid)}; - if (creating_pgs->pgs.count(pgid)) { - dout(20) << __func__ << " already have " << pgid << dendl; - continue; - } - creating_pgs->pgs.emplace(pgid, make_pair(created, modified)); - dout(10) << __func__ << " adding " << pgid - << " at " << osdmap.get_epoch() << dendl; + if (creating_pgs->create_pool(poolid, pool.get_pg_num(), + created, modified)) { + queued++; } } + return queued; } void OSDMonitor::update_creating_pgs() { + dout(10) << __func__ << " " << creating_pgs.pgs.size() << " pgs creating, " + << creating_pgs.queue.size() << " pools in queue" << dendl; decltype(creating_pgs_by_osd_epoch) new_pgs_by_osd_epoch; std::lock_guard l(creating_pgs_lock); for (auto& pg : creating_pgs.pgs) { int acting_primary = -1; auto pgid = pg.first; auto mapped = pg.second.first; + dout(20) << __func__ << " looking up " << pgid << dendl; mapping.get(pgid, nullptr, nullptr, nullptr, &acting_primary); // check the previous creating_pgs, look for the target to whom the pg was // previously mapped @@ -3230,7 +3065,10 @@ void OSDMonitor::update_creating_pgs() mapped = mapping.get_epoch(); } break; - } + } else { + // newly creating + mapped = mapping.get_epoch(); + } } } dout(10) << __func__ << " will instruct osd." << acting_primary @@ -3296,7 +3134,7 @@ void OSDMonitor::tick() bool do_propose = false; utime_t now = ceph_clock_now(); - if (osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS) && + if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS && mon->monmap->get_required_features().contains_all( ceph::features::mon::FEATURE_LUMINOUS)) { if (handle_osd_timeouts(now, last_osd_report)) { @@ -3399,10 +3237,10 @@ void OSDMonitor::tick() } // if map full setting has changed, get that info out there! - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS) && - mon->pgmon()->is_readable()) { + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS && + mon->pgservice->is_readable()) { // for pre-luminous compat only! - if (!mon->pgmon()->pg_map.full_osds.empty()) { + if (mon->pgservice->have_full_osds()) { dout(5) << "There are full osds, setting full flag" << dendl; add_flag(CEPH_OSDMAP_FULL); } else if (osdmap.test_flag(CEPH_OSDMAP_FULL)){ @@ -3410,7 +3248,7 @@ void OSDMonitor::tick() remove_flag(CEPH_OSDMAP_FULL); } - if (!mon->pgmon()->pg_map.nearfull_osds.empty()) { + if (mon->pgservice->have_nearfull_osds()) { dout(5) << "There are near full osds, setting nearfull flag" << dendl; add_flag(CEPH_OSDMAP_NEARFULL); } else if (osdmap.test_flag(CEPH_OSDMAP_NEARFULL)){ @@ -3458,9 +3296,10 @@ bool OSDMonitor::handle_osd_timeouts(const utime_t &now, } else if (can_mark_down(i)) { utime_t diff = now - t->second; if (diff > timeo) { - mon->clog->info() << "osd." << i << " marked down after no pg stats for " << diff << "seconds"; - derr << "no osd or pg stats from osd." << i << " since " << t->second << ", " << diff - << " seconds ago. marking down" << dendl; + mon->clog->info() << "osd." << i << " marked down after no beacon for " + << diff << " seconds"; + derr << "no beacon from osd." << i << " since " << t->second + << ", " << diff << " seconds ago. marking down" << dendl; pending_inc.new_state[i] = CEPH_OSD_UP; new_down = true; } @@ -3481,45 +3320,149 @@ void OSDMonitor::get_health(list >& summary, int num_in_osds = 0; int num_down_in_osds = 0; set osds; + set down_in_osds; + set up_in_osds; + set subtree_up; + unordered_map > subtree_type_down; + unordered_map num_osds_subtree; + int max_type = osdmap.crush->get_max_type_id(); + for (int i = 0; i < osdmap.get_max_osd(); i++) { if (!osdmap.exists(i)) { if (osdmap.crush->item_exists(i)) { osds.insert(i); } - continue; + continue; } if (osdmap.is_out(i)) continue; ++num_in_osds; + if (down_in_osds.count(i) || up_in_osds.count(i)) + continue; if (!osdmap.is_up(i)) { - ++num_down_in_osds; - if (detail) { - const osd_info_t& info = osdmap.get_info(i); - ostringstream ss; - ss << "osd." << i << " is down since epoch " << info.down_at - << ", last address " << osdmap.get_addr(i); - detail->push_back(make_pair(HEALTH_WARN, ss.str())); + down_in_osds.insert(i); + int parent_id = 0; + int current = i; + for (int type = 0; type <= max_type; type++) { + if (!osdmap.crush->get_type_name(type)) + continue; + int r = osdmap.crush->get_immediate_parent_id(current, &parent_id); + if (r == -ENOENT) + break; + // break early if this parent is already marked as up + if (subtree_up.count(parent_id)) + break; + type = osdmap.crush->get_bucket_type(parent_id); + if (!osdmap.subtree_type_is_down( + g_ceph_context, parent_id, type, + &down_in_osds, &up_in_osds, &subtree_up, &subtree_type_down)) + break; + current = parent_id; + } + } + } + + // calculate the number of down osds in each down subtree and + // store it in num_osds_subtree + for (int type = 1; type <= max_type; type++) { + if (!osdmap.crush->get_type_name(type)) + continue; + for (auto j = subtree_type_down[type].begin(); + j != subtree_type_down[type].end(); + ++j) { + if (type == 1) { + list children; + int num = osdmap.crush->get_children(*j, &children); + num_osds_subtree[*j] = num; + } else { + list children; + int num = 0; + int num_children = osdmap.crush->get_children(*j, &children); + if (num_children == 0) + continue; + for (auto l = children.begin(); l != children.end(); ++l) { + if (num_osds_subtree[*l] > 0) { + num = num + num_osds_subtree[*l]; + } + } + num_osds_subtree[*j] = num; } } } + num_down_in_osds = down_in_osds.size(); assert(num_down_in_osds <= num_in_osds); if (num_down_in_osds > 0) { + // summary of down subtree types and osds + for (int type = max_type; type > 0; type--) { + if (!osdmap.crush->get_type_name(type)) + continue; + if (subtree_type_down[type].size() > 0) { + ostringstream ss; + ss << subtree_type_down[type].size() << " " + << osdmap.crush->get_type_name(type); + if (subtree_type_down[type].size() > 1) { + ss << "s"; + } + int sum_down_osds = 0; + for (auto j = subtree_type_down[type].begin(); + j != subtree_type_down[type].end(); + ++j) { + sum_down_osds = sum_down_osds + num_osds_subtree[*j]; + } + ss << " (" << sum_down_osds << " osds) down"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + } + } ostringstream ss; - ss << num_down_in_osds << "/" << num_in_osds << " in osds are down"; + ss << down_in_osds.size() << " osds down"; summary.push_back(make_pair(HEALTH_WARN, ss.str())); + + if (detail) { + // details of down subtree types + for (int type = max_type; type > 0; type--) { + if (!osdmap.crush->get_type_name(type)) + continue; + for (auto j = subtree_type_down[type].rbegin(); + j != subtree_type_down[type].rend(); + ++j) { + ostringstream ss; + ss << osdmap.crush->get_type_name(type); + ss << " "; + ss << osdmap.crush->get_item_name(*j); + // at the top level, do not print location + if (type != max_type) { + ss << " ("; + ss << osdmap.crush->get_full_location_ordered_string(*j); + ss << ")"; + } + int num = num_osds_subtree[*j]; + ss << " (" << num << " osds)"; + ss << " is down"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + // details of down osds + for (auto it = down_in_osds.begin(); it != down_in_osds.end(); ++it) { + ostringstream ss; + ss << "osd." << *it << " ("; + ss << osdmap.crush->get_full_location_ordered_string(*it); + ss << ") is down"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } } if (!osds.empty()) { ostringstream ss; - ss << "osds were removed from osdmap, but still kept in crushmap"; + ss << osds.size() << " osds exist in the crush map but not in the osdmap"; summary.push_back(make_pair(HEALTH_WARN, ss.str())); if (detail) { - ss << " osds: [" << osds << "]"; + ss << " (osds: " << osds << ")"; detail->push_back(make_pair(HEALTH_WARN, ss.str())); } } - if (osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { // An osd could configure failsafe ratio, to something different // but for now assume it is the same here. float fsr = g_conf->osd_failsafe_full_ratio; @@ -3563,8 +3506,8 @@ void OSDMonitor::get_health(list >& summary, summary.push_back(make_pair(HEALTH_ERR, ss.str())); } - map full, backfillfull, nearfull; - osdmap.get_full_osd_util(mon->pgmon()->pg_map.osd_stat, &full, &backfillfull, &nearfull); + set full, backfillfull, nearfull; + osdmap.get_full_osd_counts(&full, &backfillfull, &nearfull); if (full.size()) { ostringstream ss; ss << full.size() << " full osd(s)"; @@ -3583,20 +3526,72 @@ void OSDMonitor::get_health(list >& summary, if (detail) { for (auto& i: full) { ostringstream ss; - ss << "osd." << i.first << " is full at " << roundf(i.second * 100) << "%"; + ss << "osd." << i << " is full"; detail->push_back(make_pair(HEALTH_ERR, ss.str())); } for (auto& i: backfillfull) { ostringstream ss; - ss << "osd." << i.first << " is backfill full at " << roundf(i.second * 100) << "%"; + ss << "osd." << i << " is backfill full"; detail->push_back(make_pair(HEALTH_WARN, ss.str())); } for (auto& i: nearfull) { ostringstream ss; - ss << "osd." << i.first << " is near full at " << roundf(i.second * 100) << "%"; + ss << "osd." << i << " is near full"; detail->push_back(make_pair(HEALTH_WARN, ss.str())); } } + + // warn if there is any noup osds. + vector noup_osds; + osdmap.get_noup_osds(&noup_osds); + if (noup_osds.size()) { + ostringstream ss; + ss << noup_osds.size() << " noup osd(s)"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) { + ss << ": " << noup_osds; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + + // warn if there is any nodown osds. + vector nodown_osds; + osdmap.get_nodown_osds(&nodown_osds); + if (nodown_osds.size()) { + ostringstream ss; + ss << nodown_osds.size() << " nodown osd(s)"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) { + ss << ": " << nodown_osds; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + + // warn if there is any noin osds. + vector noin_osds; + osdmap.get_noin_osds(&noin_osds); + if (noin_osds.size()) { + ostringstream ss; + ss << noin_osds.size() << " noin osd(s)"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) { + ss << ": " << noin_osds; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + + // warn if there is any noout osds. + vector noout_osds; + osdmap.get_noout_osds(&noout_osds); + if (noout_osds.size()) { + ostringstream ss; + ss << noout_osds.size() << " noout osd(s)"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) { + ss << ": " << noout_osds; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } } // note: we leave it to ceph-mgr to generate details health warnings // with actual osd utilizations @@ -3678,6 +3673,16 @@ void OSDMonitor::get_health(list >& summary, } } + if (osdmap.crush->has_multirule_rulesets()) { + ostringstream ss; + ss << "CRUSH map contains multirule rulesets"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) { + ss << "; please manually fix the map"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + // Not using 'sortbitwise' and should be? if (!osdmap.test_flag(CEPH_OSDMAP_SORTBITWISE) && (osdmap.get_up_osd_features() & @@ -3714,25 +3719,25 @@ void OSDMonitor::get_health(list >& summary, if (g_conf->mon_debug_no_require_luminous) { // ignore these checks } else if (HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_LUMINOUS) && - !osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - string msg = "all OSDs are running luminous or later but the" - " 'require_luminous_osds' osdmap flag is not set"; + osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + string msg = "all OSDs are running luminous or later but" + " require_osd_release < luminous"; summary.push_back(make_pair(HEALTH_WARN, msg)); if (detail) { detail->push_back(make_pair(HEALTH_WARN, msg)); } } else if (HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_KRAKEN) && - !osdmap.test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { - string msg = "all OSDs are running kraken or later but the" - " 'require_kraken_osds' osdmap flag is not set"; + osdmap.require_osd_release < CEPH_RELEASE_KRAKEN) { + string msg = "all OSDs are running kraken or later but" + " require_osd_release < kraken"; summary.push_back(make_pair(HEALTH_WARN, msg)); if (detail) { detail->push_back(make_pair(HEALTH_WARN, msg)); } } else if (HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_JEWEL) && - !osdmap.test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { - string msg = "all OSDs are running jewel or later but the" - " 'require_jewel_osds' osdmap flag is not set"; + osdmap.require_osd_release < CEPH_RELEASE_JEWEL) { + string msg = "all OSDs are running jewel or later but" + " require_osd_release < jewel"; summary.push_back(make_pair(HEALTH_WARN, msg)); if (detail) { detail->push_back(make_pair(HEALTH_WARN, msg)); @@ -3771,7 +3776,7 @@ void OSDMonitor::dump_info(Formatter *f) namespace { enum osd_pool_get_choices { SIZE, MIN_SIZE, CRASH_REPLAY_INTERVAL, - PG_NUM, PGP_NUM, CRUSH_RULE, CRUSH_RULESET, HASHPSPOOL, + PG_NUM, PGP_NUM, CRUSH_RULE, HASHPSPOOL, NODELETE, NOPGCHANGE, NOSIZECHANGE, WRITE_FADVISE_DONTNEED, NOSCRUB, NODEEP_SCRUB, HIT_SET_TYPE, HIT_SET_PERIOD, HIT_SET_COUNT, HIT_SET_FPP, @@ -3838,15 +3843,15 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) } else if (prefix == "osd perf" || prefix == "osd blocked-by") { - const PGMap &pgm = mon->pgmon()->pg_map; - r = process_pg_map_command(prefix, cmdmap, pgm, osdmap, - f.get(), &ss, &rdata); + r = mon->pgservice->process_pg_command(prefix, cmdmap, + osdmap, f.get(), &ss, &rdata); } else if (prefix == "osd dump" || prefix == "osd tree" || prefix == "osd ls" || prefix == "osd getmap" || - prefix == "osd getcrushmap") { + prefix == "osd getcrushmap" || + prefix == "osd ls-tree") { string val; epoch_t epoch = 0; @@ -3908,13 +3913,39 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) } rdata.append(ds); } else if (prefix == "osd tree") { + vector states; + cmd_getval(g_ceph_context, cmdmap, "states", states); + unsigned filter = 0; + for (auto& s : states) { + if (s == "up") { + filter |= OSDMap::DUMP_UP; + } else if (s == "down") { + filter |= OSDMap::DUMP_DOWN; + } else if (s == "in") { + filter |= OSDMap::DUMP_IN; + } else if (s == "out") { + filter |= OSDMap::DUMP_OUT; + } else { + ss << "unrecognized state '" << s << "'"; + r = -EINVAL; + goto reply; + } + } + if ((filter & (OSDMap::DUMP_IN|OSDMap::DUMP_OUT)) == + (OSDMap::DUMP_IN|OSDMap::DUMP_OUT) || + (filter & (OSDMap::DUMP_UP|OSDMap::DUMP_DOWN)) == + (OSDMap::DUMP_UP|OSDMap::DUMP_DOWN)) { + ss << "cannot specify both up and down or both in and out"; + r = -EINVAL; + goto reply; + } if (f) { f->open_object_section("tree"); - p->print_tree(f.get(), NULL); + p->print_tree(f.get(), NULL, filter); f->close_section(); f->flush(ds); } else { - p->print_tree(NULL, &ds); + p->print_tree(NULL, &ds, filter); } rdata.append(ds); } else if (prefix == "osd getmap") { @@ -3922,14 +3953,50 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) ss << "got osdmap epoch " << p->get_epoch(); } else if (prefix == "osd getcrushmap") { p->crush->encode(rdata, mon->get_quorum_con_features()); - ss << "got crush map from osdmap epoch " << p->get_epoch(); + ss << p->get_crush_version(); + } else if (prefix == "osd ls-tree") { + string bucket_name; + cmd_getval(g_ceph_context, cmdmap, "name", bucket_name); + set osds; + r = p->get_osds_by_bucket_name(bucket_name, &osds); + if (r == -ENOENT) { + ss << "\"" << bucket_name << "\" does not exist"; + goto reply; + } else if (r < 0) { + ss << "can not parse bucket name:\"" << bucket_name << "\""; + goto reply; + } + + if (f) { + f->open_array_section("osds"); + for (auto &i : osds) { + if (osdmap.exists(i)) { + f->dump_int("osd", i); + } + } + f->close_section(); + f->flush(ds); + } else { + bool first = true; + for (auto &i : osds) { + if (osdmap.exists(i)) { + if (!first) + ds << "\n"; + first = false; + ds << i; + } + } + } + + rdata.append(ds); } if (p != &osdmap) delete p; } else if (prefix == "osd df") { string method; cmd_getval(g_ceph_context, cmdmap, "output_method", method); - print_utilization(ds, f ? f.get() : NULL, method == "tree"); + print_osd_utilization(osdmap, mon->pgservice, ds, + f.get(), method == "tree"); rdata.append(ds); } else if (prefix == "osd getmaxosd") { if (f) { @@ -4023,6 +4090,20 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) f->close_section(); } f->flush(rdata); + } else if (prefix == "osd versions") { + if (!f) + f.reset(Formatter::create("json-pretty")); + count_metadata("ceph_version", f.get()); + f->flush(rdata); + r = 0; + } else if (prefix == "osd count-metadata") { + if (!f) + f.reset(Formatter::create("json-pretty")); + string field; + cmd_getval(g_ceph_context, cmdmap, "property", field); + count_metadata(field, f.get()); + f->flush(rdata); + r = 0; } else if (prefix == "osd map") { string poolstr, objstr, namespacestr; cmd_getval(g_ceph_context, cmdmap, "pool", poolstr); @@ -4283,7 +4364,6 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) {"crash_replay_interval", CRASH_REPLAY_INTERVAL}, {"pg_num", PG_NUM}, {"pgp_num", PGP_NUM}, {"crush_rule", CRUSH_RULE}, - {"crush_ruleset", CRUSH_RULESET}, {"hashpspool", HASHPSPOOL}, {"nodelete", NODELETE}, {"nopgchange", NOPGCHANGE}, {"nosizechange", NOSIZECHANGE}, {"noscrub", NOSCRUB}, {"nodeep-scrub", NODEEP_SCRUB}, @@ -4402,16 +4482,13 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) p->get_crash_replay_interval()); break; case CRUSH_RULE: - if (osdmap.crush->rule_exists(p->get_crush_ruleset())) { + if (osdmap.crush->rule_exists(p->get_crush_rule())) { f->dump_string("crush_rule", osdmap.crush->get_rule_name( - p->get_crush_ruleset())); + p->get_crush_rule())); } else { - f->dump_string("crush_rule", stringify(p->get_crush_ruleset())); + f->dump_string("crush_rule", stringify(p->get_crush_rule())); } break; - case CRUSH_RULESET: - f->dump_int("crush_ruleset", p->get_crush_ruleset()); - break; case HASHPSPOOL: case NODELETE: case NOPGCHANGE: @@ -4566,16 +4643,13 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) p->get_crash_replay_interval() << "\n"; break; case CRUSH_RULE: - if (osdmap.crush->rule_exists(p->get_crush_ruleset())) { + if (osdmap.crush->rule_exists(p->get_crush_rule())) { ss << "crush_rule: " << osdmap.crush->get_rule_name( - p->get_crush_ruleset()) << "\n"; + p->get_crush_rule()) << "\n"; } else { - ss << "crush_rule: " << p->get_crush_ruleset() << "\n"; + ss << "crush_rule: " << p->get_crush_rule() << "\n"; } break; - case CRUSH_RULESET: - ss << "crush_ruleset: " << p->get_crush_ruleset() << "\n"; - break; case HIT_SET_PERIOD: ss << "hit_set_period: " << p->hit_set_period << "\n"; break; @@ -4704,9 +4778,8 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) } r = 0; } else if (prefix == "osd pool stats") { - const auto &pgm = mon->pgmon()->pg_map; - r = process_pg_map_command(prefix, cmdmap, pgm, osdmap, - f.get(), &ss, &rdata); + r = mon->pgservice->process_pg_command(prefix, cmdmap, + osdmap, f.get(), &ss, &rdata); } else if (prefix == "osd pool get-quota") { string pool_name; cmd_getval(g_ceph_context, cmdmap, "pool", pool_name); @@ -4771,7 +4844,7 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) } else { int ruleno = osdmap.crush->get_rule_id(name); if (ruleno < 0) { - ss << "unknown crush ruleset '" << name << "'"; + ss << "unknown crush rule '" << name << "'"; r = ruleno; goto reply; } @@ -4879,17 +4952,17 @@ void OSDMonitor::update_pool_flags(int64_t pool_id, uint64_t flags) bool OSDMonitor::update_pools_status() { - if (!mon->pgmon()->is_readable()) + if (!mon->pgservice->is_readable()) return false; bool ret = false; auto& pools = osdmap.get_pools(); for (auto it = pools.begin(); it != pools.end(); ++it) { - if (!mon->pgmon()->pg_map.pg_pool_sum.count(it->first)) + const pool_stat_t *pstat = mon->pgservice->get_pool_stat(it->first); + if (!pstat) continue; - pool_stat_t& stats = mon->pgmon()->pg_map.pg_pool_sum[it->first]; - object_stat_sum_t& sum = stats.stats.sum; + const object_stat_sum_t& sum = pstat->stats.sum; const pg_pool_t &pool = it->second; const string& pool_name = osdmap.get_pool_name(it->first); @@ -4935,10 +5008,10 @@ void OSDMonitor::get_pools_health( { auto& pools = osdmap.get_pools(); for (auto it = pools.begin(); it != pools.end(); ++it) { - if (!mon->pgmon()->pg_map.pg_pool_sum.count(it->first)) + const pool_stat_t *pstat = mon->pgservice->get_pool_stat(it->first); + if (!pstat) continue; - pool_stat_t& stats = mon->pgmon()->pg_map.pg_pool_sum[it->first]; - object_stat_sum_t& sum = stats.stats.sum; + const object_stat_sum_t& sum = pstat->stats.sum; const pg_pool_t &pool = it->second; const string& pool_name = osdmap.get_pool_name(it->first); @@ -5023,14 +5096,14 @@ int OSDMonitor::prepare_new_pool(MonOpRequestRef op) return -EPERM; string erasure_code_profile; stringstream ss; - string ruleset_name; + string rule_name; if (m->auid) - return prepare_new_pool(m->name, m->auid, m->crush_rule, ruleset_name, + return prepare_new_pool(m->name, m->auid, m->crush_rule, rule_name, 0, 0, erasure_code_profile, pg_pool_t::TYPE_REPLICATED, 0, FAST_READ_OFF, &ss); else - return prepare_new_pool(m->name, session->auid, m->crush_rule, ruleset_name, + return prepare_new_pool(m->name, session->auid, m->crush_rule, rule_name, 0, 0, erasure_code_profile, pg_pool_t::TYPE_REPLICATED, 0, FAST_READ_OFF, &ss); @@ -5138,14 +5211,14 @@ int OSDMonitor::normalize_profile(const string& profilename, return 0; } -int OSDMonitor::crush_ruleset_create_erasure(const string &name, +int OSDMonitor::crush_rule_create_erasure(const string &name, const string &profile, - int *ruleset, + int *rule, ostream *ss) { int ruleid = osdmap.crush->get_rule_id(name); if (ruleid != -ENOENT) { - *ruleset = osdmap.crush->get_rule_mask_ruleset(ruleid); + *rule = osdmap.crush->get_rule_mask_ruleset(ruleid); return -EEXIST; } @@ -5154,7 +5227,7 @@ int OSDMonitor::crush_ruleset_create_erasure(const string &name, ruleid = newcrush.get_rule_id(name); if (ruleid != -ENOENT) { - *ruleset = newcrush.get_rule_mask_ruleset(ruleid); + *rule = newcrush.get_rule_mask_ruleset(ruleid); return -EALREADY; } else { ErasureCodeInterfaceRef erasure_code; @@ -5168,7 +5241,7 @@ int OSDMonitor::crush_ruleset_create_erasure(const string &name, erasure_code.reset(); if (err < 0) return err; - *ruleset = err; + *rule = err; pending_inc.crush.clear(); newcrush.encode(pending_inc.crush, mon->get_quorum_con_features()); return 0; @@ -5252,12 +5325,12 @@ bool OSDMonitor::validate_crush_against_features(const CrushWrapper *newcrush, newmap.apply_incremental(new_pending); // client compat - if (newmap.require_min_compat_client.length()) { + if (newmap.require_min_compat_client > 0) { auto mv = newmap.get_min_compat_client(); - if (mv.first > newmap.require_min_compat_client) { - ss << "new crush map requires client version " << mv + if (mv > newmap.require_min_compat_client) { + ss << "new crush map requires client version " << ceph_release_name(mv) << " but require_min_compat_client is " - << newmap.require_min_compat_client; + << ceph_release_name(newmap.require_min_compat_client); return false; } } @@ -5398,40 +5471,40 @@ int OSDMonitor::prepare_pool_stripe_width(const unsigned pool_type, return err; } -int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type, +int OSDMonitor::prepare_pool_crush_rule(const unsigned pool_type, const string &erasure_code_profile, - const string &ruleset_name, - int *crush_ruleset, + const string &rule_name, + int *crush_rule, ostream *ss) { - if (*crush_ruleset < 0) { + if (*crush_rule < 0) { switch (pool_type) { case pg_pool_t::TYPE_REPLICATED: { - if (ruleset_name == "") { - //Use default ruleset - *crush_ruleset = osdmap.crush->get_osd_pool_default_crush_replicated_ruleset(g_ceph_context); - if (*crush_ruleset < 0) { - // Errors may happen e.g. if no valid ruleset is available - *ss << "No suitable CRUSH ruleset exists, check " + if (rule_name == "") { + //Use default rule + *crush_rule = osdmap.crush->get_osd_pool_default_crush_replicated_ruleset(g_ceph_context); + if (*crush_rule < 0) { + // Errors may happen e.g. if no valid rule is available + *ss << "No suitable CRUSH rule exists, check " << "'osd pool default crush *' config options"; return -ENOENT; } } else { - return get_crush_ruleset(ruleset_name, crush_ruleset, ss); + return get_crush_rule(rule_name, crush_rule, ss); } } break; case pg_pool_t::TYPE_ERASURE: { - int err = crush_ruleset_create_erasure(ruleset_name, + int err = crush_rule_create_erasure(rule_name, erasure_code_profile, - crush_ruleset, ss); + crush_rule, ss); switch (err) { case -EALREADY: - dout(20) << "prepare_pool_crush_ruleset: ruleset " - << ruleset_name << " try again" << dendl; + dout(20) << "prepare_pool_crush_rule: rule " + << rule_name << " try again" << dendl; // fall through case 0: // need to wait for the crush rule to be proposed before proceeding @@ -5445,14 +5518,14 @@ int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type, } break; default: - *ss << "prepare_pool_crush_ruleset: " << pool_type + *ss << "prepare_pool_crush_rule: " << pool_type << " is not a known pool type"; return -EINVAL; break; } } else { - if (!osdmap.crush->ruleset_exists(*crush_ruleset)) { - *ss << "CRUSH ruleset " << *crush_ruleset << " not found"; + if (!osdmap.crush->ruleset_exists(*crush_rule)) { + *ss << "CRUSH rule " << *crush_rule << " not found"; return -ENOENT; } } @@ -5460,28 +5533,28 @@ int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type, return 0; } -int OSDMonitor::get_crush_ruleset(const string &ruleset_name, - int *crush_ruleset, +int OSDMonitor::get_crush_rule(const string &rule_name, + int *crush_rule, ostream *ss) { int ret; - ret = osdmap.crush->get_rule_id(ruleset_name); + ret = osdmap.crush->get_rule_id(rule_name); if (ret != -ENOENT) { // found it, use it - *crush_ruleset = ret; + *crush_rule = ret; } else { CrushWrapper newcrush; _get_pending_crush(newcrush); - ret = newcrush.get_rule_id(ruleset_name); + ret = newcrush.get_rule_id(rule_name); if (ret != -ENOENT) { // found it, wait for it to be proposed - dout(20) << __func__ << ": ruleset " << ruleset_name + dout(20) << __func__ << ": rule " << rule_name << " try again" << dendl; return -EAGAIN; } else { //Cannot find it , return error - *ss << "specified ruleset " << ruleset_name << " doesn't exist"; + *ss << "specified rule " << rule_name << " doesn't exist"; return ret; } } @@ -5491,8 +5564,8 @@ int OSDMonitor::get_crush_ruleset(const string &ruleset_name, /** * @param name The name of the new pool * @param auid The auid of the pool owner. Can be -1 - * @param crush_ruleset The crush rule to use. If <0, will use the system default - * @param crush_ruleset_name The crush rule to use, if crush_rulset <0 + * @param crush_rule The crush rule to use. If <0, will use the system default + * @param crush_rule_name The crush rule to use, if crush_rulset <0 * @param pg_num The pg_num to use. If set to 0, will use the system default * @param pgp_num The pgp_num to use. If set to 0, will use the system default * @param erasure_code_profile The profile name in OSDMap to be used for erasure code @@ -5504,8 +5577,8 @@ int OSDMonitor::get_crush_ruleset(const string &ruleset_name, * @return 0 on success, negative errno on failure. */ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, - int crush_ruleset, - const string &crush_ruleset_name, + int crush_rule, + const string &crush_rule_name, unsigned pg_num, unsigned pgp_num, const string &erasure_code_profile, const unsigned pool_type, @@ -5535,10 +5608,10 @@ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, return -EINVAL; } int r; - r = prepare_pool_crush_ruleset(pool_type, erasure_code_profile, - crush_ruleset_name, &crush_ruleset, ss); + r = prepare_pool_crush_rule(pool_type, erasure_code_profile, + crush_rule_name, &crush_rule, ss); if (r) { - dout(10) << " prepare_pool_crush_ruleset returns " << r << dendl; + dout(10) << " prepare_pool_crush_rule returns " << r << dendl; return r; } CrushWrapper newcrush; @@ -5552,7 +5625,7 @@ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, r = tester.test_with_crushtool(g_conf->crushtool.c_str(), osdmap.get_max_osd(), g_conf->mon_lease, - crush_ruleset); + crush_rule); } if (r) { dout(10) << " tester.test_with_crushtool returns " << r @@ -5567,7 +5640,7 @@ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, return r; } - if (!osdmap.crush->check_crush_rule(crush_ruleset, pool_type, size, *ss)) { + if (!osdmap.crush->check_crush_rule(crush_rule, pool_type, size, *ss)) { return -EINVAL; } @@ -5627,7 +5700,7 @@ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, pi->size = size; pi->min_size = min_size; - pi->crush_ruleset = crush_ruleset; + pi->crush_rule = crush_rule; pi->expected_num_objects = expected_num_objects; pi->object_hash = CEPH_STR_HASH_RJENKINS; pi->set_pg_num(pg_num); @@ -5674,28 +5747,6 @@ bool OSDMonitor::prepare_unset_flag(MonOpRequestRef op, int flag) return true; } -int OSDMonitor::parse_osd_id(const char *s, stringstream *pss) -{ - // osd.NNN? - if (strncmp(s, "osd.", 4) == 0) { - s += 4; - } - - // NNN? - ostringstream ss; - long id = parse_pos_long(s, &ss); - if (id < 0) { - *pss << ss.str(); - return id; - } - if (id > 0xffff) { - *pss << "osd id " << id << " is too large"; - return -ERANGE; - } - return id; -} - - int OSDMonitor::prepare_command_pool_set(map &cmdmap, stringstream& ss) { @@ -5878,21 +5929,7 @@ int OSDMonitor::prepare_command_pool_set(map &cmdmap, if (!osdmap.crush->check_crush_rule(id, p.get_type(), p.get_size(), ss)) { return -EINVAL; } - p.crush_ruleset = id; - } else if (var == "crush_ruleset") { - if (interr.length()) { - ss << "error parsing integer value '" << val << "': " << interr; - return -EINVAL; - } - if (!osdmap.crush->ruleset_exists(n)) { - ss << "crush ruleset " << n << " does not exist"; - return -ENOENT; - } - - if (!osdmap.crush->check_crush_rule(n, p.get_type(), p.get_size(), ss)) { - return -EINVAL; - } - p.crush_ruleset = n; + p.crush_rule = id; } else if (var == "nodelete" || var == "nopgchange" || var == "nosizechange" || var == "write_fadvise_dontneed" || var == "noscrub" || var == "nodeep-scrub") { @@ -5994,7 +6031,8 @@ int OSDMonitor::prepare_command_pool_set(map &cmdmap, return -EINVAL; } stringstream err; - if (!is_pool_currently_all_bluestore(pool, p, &err)) { + if (!g_conf->mon_debug_no_require_bluestore_for_ec_overwrites && + !is_pool_currently_all_bluestore(pool, p, &err)) { ss << "pool must only be stored on bluestore for scrubbing to work: " << err.str(); return -EINVAL; } @@ -6182,6 +6220,482 @@ int OSDMonitor::prepare_command_pool_set(map &cmdmap, return 0; } +int OSDMonitor::_prepare_command_osd_crush_remove( + CrushWrapper &newcrush, + int32_t id, + int32_t ancestor, + bool has_ancestor, + bool unlink_only) +{ + int err = 0; + + if (has_ancestor) { + err = newcrush.remove_item_under(g_ceph_context, id, ancestor, + unlink_only); + } else { + err = newcrush.remove_item(g_ceph_context, id, unlink_only); + } + return err; +} + +void OSDMonitor::do_osd_crush_remove(CrushWrapper& newcrush) +{ + pending_inc.crush.clear(); + newcrush.encode(pending_inc.crush, mon->get_quorum_con_features()); +} + +int OSDMonitor::prepare_command_osd_crush_remove( + CrushWrapper &newcrush, + int32_t id, + int32_t ancestor, + bool has_ancestor, + bool unlink_only) +{ + int err = _prepare_command_osd_crush_remove( + newcrush, id, ancestor, + has_ancestor, unlink_only); + + if (err < 0) + return err; + + assert(err == 0); + do_osd_crush_remove(newcrush); + + return 0; +} + +int OSDMonitor::prepare_command_osd_remove(int32_t id) +{ + if (osdmap.is_up(id)) { + return -EBUSY; + } + + pending_inc.new_state[id] = osdmap.get_state(id); + pending_inc.new_uuid[id] = uuid_d(); + pending_metadata_rm.insert(id); + pending_metadata.erase(id); + + return 0; +} + +int32_t OSDMonitor::_allocate_osd_id(int32_t* existing_id) +{ + assert(existing_id); + *existing_id = -1; + + for (int32_t i = 0; i < osdmap.get_max_osd(); ++i) { + if (!osdmap.exists(i) && + pending_inc.new_up_client.count(i) == 0 && + (pending_inc.new_state.count(i) == 0 || + (pending_inc.new_state[i] & CEPH_OSD_EXISTS) == 0)) { + *existing_id = i; + return -1; + } + } + + if (pending_inc.new_max_osd < 0) { + return osdmap.get_max_osd(); + } + return pending_inc.new_max_osd; +} + +void OSDMonitor::do_osd_create( + const int32_t id, + const uuid_d& uuid, + int32_t* new_id) +{ + dout(10) << __func__ << " uuid " << uuid << dendl; + assert(new_id); + + // We presume validation has been performed prior to calling this + // function. We assert with prejudice. + + int32_t allocated_id = -1; // declare here so we can jump + int32_t existing_id = -1; + if (!uuid.is_zero()) { + existing_id = osdmap.identify_osd(uuid); + if (existing_id >= 0) { + assert(id < 0 || id == existing_id); + *new_id = existing_id; + goto out; + } else if (id >= 0) { + // uuid does not exist, and id has been provided, so just create + // the new osd.id + *new_id = id; + goto out; + } + } + + // allocate a new id + allocated_id = _allocate_osd_id(&existing_id); + dout(10) << __func__ << " allocated id " << allocated_id + << " existing id " << existing_id << dendl; + if (existing_id >= 0) { + assert(existing_id < osdmap.get_max_osd()); + assert(allocated_id < 0); + pending_inc.new_weight[existing_id] = CEPH_OSD_OUT; + *new_id = existing_id; + + } else if (allocated_id >= 0) { + assert(existing_id < 0); + // raise max_osd + if (pending_inc.new_max_osd < 0) { + pending_inc.new_max_osd = osdmap.get_max_osd() + 1; + } else { + ++pending_inc.new_max_osd; + } + *new_id = pending_inc.new_max_osd - 1; + assert(*new_id == allocated_id); + } else { + assert(0 == "unexpected condition"); + } + +out: + dout(10) << __func__ << " using id " << *new_id << dendl; + if (osdmap.get_max_osd() <= *new_id && pending_inc.new_max_osd <= *new_id) { + pending_inc.new_max_osd = *new_id + 1; + } + + pending_inc.new_state[*new_id] |= CEPH_OSD_EXISTS | CEPH_OSD_NEW; + if (!uuid.is_zero()) + pending_inc.new_uuid[*new_id] = uuid; +} + +int OSDMonitor::validate_osd_create( + const int32_t id, + const uuid_d& uuid, + const bool check_osd_exists, + int32_t* existing_id, + stringstream& ss) +{ + + dout(10) << __func__ << " id " << id << " uuid " << uuid + << " check_osd_exists " << check_osd_exists << dendl; + + assert(existing_id); + + if (id < 0 && uuid.is_zero()) { + // we have nothing to validate + *existing_id = -1; + return 0; + } else if (uuid.is_zero()) { + // we have an id but we will ignore it - because that's what + // `osd create` does. + return 0; + } + + /* + * This function will be used to validate whether we are able to + * create a new osd when the `uuid` is specified. + * + * It will be used by both `osd create` and `osd new`, as the checks + * are basically the same when it pertains to osd id and uuid validation. + * However, `osd create` presumes an `uuid` is optional, for legacy + * reasons, while `osd new` requires the `uuid` to be provided. This + * means that `osd create` will not be idempotent if an `uuid` is not + * provided, but we will always guarantee the idempotency of `osd new`. + */ + + assert(!uuid.is_zero()); + if (pending_inc.identify_osd(uuid) >= 0) { + // osd is about to exist + return -EAGAIN; + } + + int32_t i = osdmap.identify_osd(uuid); + if (i >= 0) { + // osd already exists + if (id >= 0 && i != id) { + ss << "uuid " << uuid << " already in use for different id " << i; + return -EEXIST; + } + // return a positive errno to distinguish between a blocking error + // and an error we consider to not be a problem (i.e., this would be + // an idempotent operation). + *existing_id = i; + return EEXIST; + } + // i < 0 + if (id >= 0) { + if (pending_inc.new_state.count(id)) { + // osd is about to exist + return -EAGAIN; + } + // we may not care if an osd exists if we are recreating a previously + // destroyed osd. + if (check_osd_exists && osdmap.exists(id)) { + ss << "id " << id << " already in use and does not match uuid " + << uuid; + return -EINVAL; + } + } + return 0; +} + +int OSDMonitor::prepare_command_osd_create( + const int32_t id, + const uuid_d& uuid, + int32_t* existing_id, + stringstream& ss) +{ + dout(10) << __func__ << " id " << id << " uuid " << uuid << dendl; + assert(existing_id); + + if (uuid.is_zero()) { + dout(10) << __func__ << " no uuid; assuming legacy `osd create`" << dendl; + } + + return validate_osd_create(id, uuid, true, existing_id, ss); +} + +int OSDMonitor::prepare_command_osd_new( + MonOpRequestRef op, + const map& cmdmap, + const map& secrets, + stringstream &ss, + Formatter *f) +{ + uuid_d uuid; + string uuidstr; + int64_t id = -1; + + assert(paxos->is_plugged()); + + dout(10) << __func__ << " " << op << dendl; + + /* validate command. abort now if something's wrong. */ + + /* `osd new` will expect a `uuid` to be supplied; `id` is optional. + * + * If `id` is not specified, we will identify any existing osd based + * on `uuid`. Operation will be idempotent iff secrets match. + * + * If `id` is specified, we will identify any existing osd based on + * `uuid` and match against `id`. If they match, operation will be + * idempotent iff secrets match. + * + * `-i secrets.json` will be optional. If supplied, will be used + * to check for idempotency when `id` and `uuid` match. + * + * If `id` is not specified, and `uuid` does not exist, an id will + * be found or allocated for the osd. + * + * If `id` is specified, and the osd has been previously marked + * as destroyed, then the `id` will be reused. + */ + if (!cmd_getval(g_ceph_context, cmdmap, "uuid", uuidstr)) { + ss << "requires the OSD's UUID to be specified."; + return -EINVAL; + } else if (!uuid.parse(uuidstr.c_str())) { + ss << "invalid UUID value '" << uuidstr << "'."; + return -EINVAL; + } + + if (cmd_getval(g_ceph_context, cmdmap, "id", id) && + (id < 0)) { + ss << "invalid OSD id; must be greater or equal than zero."; + return -EINVAL; + } + + // are we running an `osd create`-like command, or recreating + // a previously destroyed osd? + + bool is_recreate_destroyed = (id >= 0 && osdmap.is_destroyed(id)); + + // we will care about `id` to assess whether osd is `destroyed`, or + // to create a new osd. + // we will need an `id` by the time we reach auth. + + int32_t existing_id = -1; + int err = validate_osd_create(id, uuid, !is_recreate_destroyed, + &existing_id, ss); + + bool may_be_idempotent = false; + if (err == EEXIST) { + // this is idempotent from the osdmon's point-of-view + may_be_idempotent = true; + assert(existing_id >= 0); + id = existing_id; + } else if (err < 0) { + return err; + } + + if (!may_be_idempotent) { + // idempotency is out of the window. We are either creating a new + // osd or recreating a destroyed osd. + // + // We now need to figure out if we have an `id` (and if it's valid), + // of find an `id` if we don't have one. + + // NOTE: we need to consider the case where the `id` is specified for + // `osd create`, and we must honor it. So this means checking if + // the `id` is destroyed, and if so assume the destroy; otherwise, + // check if it `exists` - in which case we complain about not being + // `destroyed`. In the end, if nothing fails, we must allow the + // creation, so that we are compatible with `create`. + if (id >= 0 && osdmap.exists(id) && !osdmap.is_destroyed(id)) { + dout(10) << __func__ << " osd." << id << " isn't destroyed" << dendl; + ss << "OSD " << id << " has not yet been destroyed"; + return -EINVAL; + } else if (id < 0) { + // find an `id` + id = _allocate_osd_id(&existing_id); + if (id < 0) { + assert(existing_id >= 0); + id = existing_id; + } + dout(10) << __func__ << " found id " << id << " to use" << dendl; + } else if (id >= 0 && osdmap.is_destroyed(id)) { + dout(10) << __func__ << " recreating osd." << id << dendl; + } else { + dout(10) << __func__ << " creating new osd." << id << dendl; + } + } else { + assert(id >= 0); + assert(osdmap.exists(id)); + } + + // we are now able to either create a brand new osd or reuse an existing + // osd that has been previously destroyed. + + dout(10) << __func__ << " id " << id << " uuid " << uuid << dendl; + + if (may_be_idempotent && secrets.empty()) { + // nothing to do, really. + dout(10) << __func__ << " idempotent and no secrets -- no op." << dendl; + assert(id >= 0); + if (f) { + f->open_object_section("created_osd"); + f->dump_int("osdid", id); + f->close_section(); + } else { + ss << id; + } + return EEXIST; + } + + string cephx_secret, lockbox_secret, dmcrypt_key; + bool has_lockbox = false; + bool has_secrets = (!secrets.empty()); + + ConfigKeyService *svc = nullptr; + AuthMonitor::auth_entity_t cephx_entity, lockbox_entity; + + if (has_secrets) { + if (secrets.count("cephx_secret") == 0) { + ss << "requires a cephx secret."; + return -EINVAL; + } + cephx_secret = secrets.at("cephx_secret"); + + bool has_lockbox_secret = (secrets.count("cephx_lockbox_secret") > 0); + bool has_dmcrypt_key = (secrets.count("dmcrypt_key") > 0); + + dout(10) << __func__ << " has lockbox " << has_lockbox_secret + << " dmcrypt " << has_dmcrypt_key << dendl; + + if (has_lockbox_secret && has_dmcrypt_key) { + has_lockbox = true; + lockbox_secret = secrets.at("cephx_lockbox_secret"); + dmcrypt_key = secrets.at("dmcrypt_key"); + } else if (!has_lockbox_secret != !has_dmcrypt_key) { + ss << "requires both a cephx lockbox secret and a dm-crypt key."; + return -EINVAL; + } + + dout(10) << __func__ << " validate secrets using osd id " << id << dendl; + + err = mon->authmon()->validate_osd_new(id, uuid, + cephx_secret, + lockbox_secret, + cephx_entity, + lockbox_entity, + ss); + if (err < 0) { + return err; + } else if (may_be_idempotent && err != EEXIST) { + // for this to be idempotent, `id` should already be >= 0; no need + // to use validate_id. + assert(id >= 0); + ss << "osd." << id << " exists but secrets do not match"; + return -EEXIST; + } + + if (has_lockbox) { + svc = (ConfigKeyService*)mon->config_key_service; + err = svc->validate_osd_new(uuid, dmcrypt_key, ss); + if (err < 0) { + return err; + } else if (may_be_idempotent && err != EEXIST) { + assert(id >= 0); + ss << "osd." << id << " exists but dm-crypt key does not match."; + return -EEXIST; + } + } + } + assert(!has_secrets || !cephx_secret.empty()); + assert(!has_lockbox || !lockbox_secret.empty()); + + if (may_be_idempotent) { + // we have nothing to do for either the osdmon or the authmon, + // and we have no lockbox - so the config key service will not be + // touched. This is therefore an idempotent operation, and we can + // just return right away. + dout(10) << __func__ << " idempotent -- no op." << dendl; + assert(id >= 0); + if (f) { + f->open_object_section("created_osd"); + f->dump_int("osdid", id); + f->close_section(); + } else { + ss << id; + } + return EEXIST; + } + assert(!may_be_idempotent); + + // perform updates. + if (has_secrets) { + assert(!cephx_secret.empty()); + assert((lockbox_secret.empty() && dmcrypt_key.empty()) || + (!lockbox_secret.empty() && !dmcrypt_key.empty())); + + err = mon->authmon()->do_osd_new(cephx_entity, + lockbox_entity, + has_lockbox); + assert(0 == err); + + if (has_lockbox) { + assert(nullptr != svc); + svc->do_osd_new(uuid, dmcrypt_key); + } + } + + if (is_recreate_destroyed) { + assert(id >= 0); + assert(osdmap.is_destroyed(id)); + pending_inc.new_weight[id] = CEPH_OSD_OUT; + pending_inc.new_state[id] |= CEPH_OSD_DESTROYED | CEPH_OSD_NEW; + pending_inc.new_uuid[id] = uuid; + } else { + assert(id >= 0); + int32_t new_id = -1; + do_osd_create(id, uuid, &new_id); + assert(new_id >= 0); + assert(id == new_id); + } + + if (f) { + f->open_object_section("created_osd"); + f->dump_int("osdid", id); + f->close_section(); + } else { + ss << id; + } + + return 0; +} + bool OSDMonitor::prepare_command(MonOpRequestRef op) { op->mark_osdmon_event(__func__); @@ -6239,6 +6753,148 @@ static int parse_reweights(CephContext *cct, return 0; } +int OSDMonitor::prepare_command_osd_destroy( + int32_t id, + stringstream& ss) +{ + assert(paxos->is_plugged()); + + // we check if the osd exists for the benefit of `osd purge`, which may + // have previously removed the osd. If the osd does not exist, return + // -ENOENT to convey this, and let the caller deal with it. + // + // we presume that all auth secrets and config keys were removed prior + // to this command being called. if they exist by now, we also assume + // they must have been created by some other command and do not pertain + // to this non-existent osd. + if (!osdmap.exists(id)) { + dout(10) << __func__ << " osd." << id << " does not exist." << dendl; + return -ENOENT; + } + + uuid_d uuid = osdmap.get_uuid(id); + dout(10) << __func__ << " destroying osd." << id + << " uuid " << uuid << dendl; + + // if it has been destroyed, we assume our work here is done. + if (osdmap.is_destroyed(id)) { + ss << "destroyed osd." << id; + return 0; + } + + EntityName cephx_entity, lockbox_entity; + bool idempotent_auth = false, idempotent_cks = false; + + int err = mon->authmon()->validate_osd_destroy(id, uuid, + cephx_entity, + lockbox_entity, + ss); + if (err < 0) { + if (err == -ENOENT) { + idempotent_auth = true; + err = 0; + } else { + return err; + } + } + + ConfigKeyService *svc = (ConfigKeyService*)mon->config_key_service; + err = svc->validate_osd_destroy(id, uuid); + if (err < 0) { + assert(err == -ENOENT); + err = 0; + idempotent_cks = true; + } + + if (!idempotent_auth) { + err = mon->authmon()->do_osd_destroy(cephx_entity, lockbox_entity); + assert(0 == err); + } + + if (!idempotent_cks) { + svc->do_osd_destroy(id, uuid); + } + + pending_inc.new_state[id] = CEPH_OSD_DESTROYED; + pending_inc.new_uuid[id] = uuid_d(); + + // we can only propose_pending() once per service, otherwise we'll be + // defying PaxosService and all laws of nature. Therefore, as we may + // be used during 'osd purge', let's keep the caller responsible for + // proposing. + assert(err == 0); + return 0; +} + +int OSDMonitor::prepare_command_osd_purge( + int32_t id, + stringstream& ss) +{ + assert(paxos->is_plugged()); + dout(10) << __func__ << " purging osd." << id << dendl; + + assert(!osdmap.is_up(id)); + + /* + * This may look a bit weird, but this is what's going to happen: + * + * 1. we make sure that removing from crush works + * 2. we call `prepare_command_osd_destroy()`. If it returns an + * error, then we abort the whole operation, as no updates + * have been made. However, we this function will have + * side-effects, thus we need to make sure that all operations + * performed henceforth will *always* succeed. + * 3. we call `prepare_command_osd_remove()`. Although this + * function can return an error, it currently only checks if the + * osd is up - and we have made sure that it is not so, so there + * is no conflict, and it is effectively an update. + * 4. finally, we call `do_osd_crush_remove()`, which will perform + * the crush update we delayed from before. + */ + + CrushWrapper newcrush; + _get_pending_crush(newcrush); + + bool may_be_idempotent = false; + + int err = _prepare_command_osd_crush_remove(newcrush, id, 0, false, false); + if (err == -ENOENT) { + err = 0; + may_be_idempotent = true; + } else if (err < 0) { + ss << "error removing osd." << id << " from crush"; + return err; + } + + // no point destroying the osd again if it has already been marked destroyed + if (!osdmap.is_destroyed(id)) { + err = prepare_command_osd_destroy(id, ss); + if (err < 0) { + if (err == -ENOENT) { + err = 0; + } else { + return err; + } + } else { + may_be_idempotent = false; + } + } + assert(0 == err); + + if (may_be_idempotent && !osdmap.exists(id)) { + dout(10) << __func__ << " osd." << id << " does not exist and " + << "we are idempotent." << dendl; + return -ENOENT; + } + + err = prepare_command_osd_remove(id); + // we should not be busy, as we should have made sure this id is not up. + assert(0 == err); + + do_osd_crush_remove(newcrush); + return 0; +} + bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, map &cmdmap) { @@ -6298,6 +6954,11 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, if (prefix == "osd setcrushmap" || (prefix == "osd crush set" && !osdid_present)) { + if (pending_inc.crush.length()) { + dout(10) << __func__ << " waiting for pending crush update " << dendl; + wait_for_finished_proposal(op, new C_RetryMessage(this, op)); + return true; + } dout(10) << "prepare_command setting new crush map" << dendl; bufferlist data(m->get_data()); CrushWrapper crush; @@ -6310,17 +6971,48 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, ss << "Failed to parse crushmap: " << e.what(); goto reply; } + + int64_t prior_version = 0; + if (cmd_getval(g_ceph_context, cmdmap, "prior_version", prior_version)) { + if (prior_version == osdmap.get_crush_version() - 1) { + // see if we are a resend of the last update. this is imperfect + // (multiple racing updaters may not both get reliable success) + // but we expect crush updaters (via this interface) to be rare-ish. + bufferlist current, proposed; + osdmap.crush->encode(current, mon->get_quorum_con_features()); + crush.encode(proposed, mon->get_quorum_con_features()); + if (current.contents_equal(proposed)) { + dout(10) << __func__ + << " proposed matches current and version equals previous" + << dendl; + err = 0; + ss << osdmap.get_crush_version(); + goto reply; + } + } + if (prior_version != osdmap.get_crush_version()) { + err = -EPERM; + ss << "prior_version " << prior_version << " != crush version " + << osdmap.get_crush_version(); + goto reply; + } + } + if (crush.has_legacy_rulesets()) { + err = -EINVAL; + ss << "crush maps with ruleset != ruleid are no longer allowed"; + goto reply; + } if (!validate_crush_against_features(&crush, ss)) { err = -EINVAL; goto reply; } - + const auto& osdmap_pools = osdmap.get_pools(); for (auto pit = osdmap_pools.begin(); pit != osdmap_pools.end(); ++pit) { const int64_t pool_id = pit->first; const pg_pool_t &pool = pit->second; - int ruleno = pool.get_crush_ruleset(); + int ruleno = pool.get_crush_rule(); if (!crush.rule_exists(ruleno)) { ss << " the crush rule no "<< ruleno << " for pool id " << pool_id << " is in use"; err = -EINVAL; @@ -6349,7 +7041,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, dout(10) << " result " << ess.str() << dendl; pending_inc.crush = data; - ss << "set crush map"; + ss << osdmap.get_crush_version() + 1; goto update; } else if (prefix == "osd crush set-device-class") { @@ -6685,8 +7377,53 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, err = 0; } } while (false); - - } else if (prefix == "osd crush link") { + } else if (prefix == "osd crush swap-bucket") { + string source, dest, force; + cmd_getval(g_ceph_context, cmdmap, "source", source); + cmd_getval(g_ceph_context, cmdmap, "dest", dest); + cmd_getval(g_ceph_context, cmdmap, "force", force); + CrushWrapper newcrush; + _get_pending_crush(newcrush); + if (!newcrush.name_exists(source)) { + ss << "source item " << source << " does not exist"; + err = -ENOENT; + goto reply; + } + if (!newcrush.name_exists(dest)) { + ss << "dest item " << dest << " does not exist"; + err = -ENOENT; + goto reply; + } + int sid = newcrush.get_item_id(source); + int did = newcrush.get_item_id(dest); + int sparent; + if (newcrush.get_immediate_parent_id(sid, &sparent) == 0 && + force != "--yes-i-really-mean-it") { + ss << "source item " << source << " is not an orphan bucket; pass --yes-i-really-mean-it to proceed anyway"; + err = -EPERM; + goto reply; + } + if (newcrush.get_bucket_alg(sid) != newcrush.get_bucket_alg(did) && + force != "--yes-i-really-mean-it") { + ss << "source bucket alg " << crush_alg_name(newcrush.get_bucket_alg(sid)) << " != " + << "dest bucket alg " << crush_alg_name(newcrush.get_bucket_alg(did)) + << "; pass --yes-i-really-mean-it to proceed anyway"; + err = -EPERM; + goto reply; + } + int r = newcrush.swap_bucket(g_ceph_context, sid, did); + if (r < 0) { + ss << "failed to swap bucket contents: " << cpp_strerror(r); + goto reply; + } + ss << "swapped bucket of " << source << " to " << dest; + pending_inc.crush.clear(); + newcrush.encode(pending_inc.crush, mon->get_quorum_con_features()); + wait_for_finished_proposal(op, + new Monitor::C_Command(mon, op, err, ss.str(), + get_last_committed() + 1)); + return true; + } else if (prefix == "osd crush link") { // osd crush link [ ...] string name; cmd_getval(g_ceph_context, cmdmap, "name", name); @@ -6768,6 +7505,8 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, return true; } int id = newcrush.get_item_id(name); + int ancestor = 0; + bool unlink_only = prefix == "osd crush unlink"; string ancestor_str; if (cmd_getval(g_ceph_context, cmdmap, "ancestor", ancestor_str)) { @@ -6777,20 +7516,20 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, << "' does not appear in the crush map"; break; } - int ancestor = newcrush.get_item_id(ancestor_str); - err = newcrush.remove_item_under(g_ceph_context, id, ancestor, - unlink_only); - } else { - err = newcrush.remove_item(g_ceph_context, id, unlink_only); + ancestor = newcrush.get_item_id(ancestor_str); } + + err = prepare_command_osd_crush_remove( + newcrush, + id, ancestor, + (ancestor < 0), unlink_only); + if (err == -ENOENT) { ss << "item " << id << " does not appear in that position"; err = 0; break; } if (err == 0) { - pending_inc.crush.clear(); - newcrush.encode(pending_inc.crush, mon->get_quorum_con_features()); ss << "removed item id " << id << " name '" << name << "' from crush map"; getline(ss, rs); wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, @@ -6978,9 +7717,9 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, mode = "firstn"; if (osdmap.crush->rule_exists(name)) { - // The name is uniquely associated to a ruleid and the ruleset it contains - // From the user point of view, the ruleset is more meaningfull. - ss << "ruleset " << name << " already exists"; + // The name is uniquely associated to a ruleid and the rule it contains + // From the user point of view, the rule is more meaningfull. + ss << "rule " << name << " already exists"; err = 0; goto reply; } @@ -6989,12 +7728,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, _get_pending_crush(newcrush); if (newcrush.rule_exists(name)) { - // The name is uniquely associated to a ruleid and the ruleset it contains - // From the user point of view, the ruleset is more meaningfull. - ss << "ruleset " << name << " already exists"; + // The name is uniquely associated to a ruleid and the rule it contains + // From the user point of view, the rule is more meaningfull. + ss << "rule " << name << " already exists"; err = 0; } else { - int ruleno = newcrush.add_simple_ruleset(name, root, type, mode, + int ruleno = newcrush.add_simple_rule(name, root, type, mode, pg_pool_t::TYPE_REPLICATED, &ss); if (ruleno < 0) { err = ruleno; @@ -7152,8 +7891,8 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } } - int ruleset; - err = crush_ruleset_create_erasure(name, profile, &ruleset, &ss); + int rule; + err = crush_rule_create_erasure(name, profile, &rule, &ss); if (err < 0) { switch(err) { case -EEXIST: // return immediately @@ -7170,7 +7909,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, break; } } else { - ss << "created ruleset " << name << " at " << ruleset; + ss << "created rule " << name << " at " << rule; } getline(ss, rs); @@ -7264,9 +8003,9 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } else if (prefix == "osd set-full-ratio" || prefix == "osd set-backfillfull-ratio" || prefix == "osd set-nearfull-ratio") { - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - ss << "you must complete the upgrade and set require_luminous_osds before" - << " using the new interface"; + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + ss << "you must complete the upgrade and set require_osd_release =" + << "luminous before using the new interface"; err = -EPERM; goto reply; } @@ -7289,17 +8028,16 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, get_last_committed() + 1)); return true; } else if (prefix == "osd set-require-min-compat-client") { - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - ss << "you must complete the upgrade and set require_luminous_osds before" - << " using the new interface"; + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + ss << "you must complete the upgrade and set require_osd_release =" + << "luminous before using the new interface"; err = -EPERM; goto reply; } string v; cmd_getval(g_ceph_context, cmdmap, "version", v); - if (v != "luminous" && v != "kraken" && v != "jewel" && v != "infernalis" && - v != "hammer" && v != "giant" && v != "firefly" && v != "emperor" && - v != "dumpling" && v != "cuttlefish" && v != "bobtail" && v != "argonaut") { + int vno = ceph_release_from_name(v.c_str()); + if (vno <= 0) { ss << "version " << v << " is not recognized"; err = -EINVAL; goto reply; @@ -7307,16 +8045,57 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, OSDMap newmap; newmap.deepish_copy_from(osdmap); newmap.apply_incremental(pending_inc); - newmap.require_min_compat_client = v; - auto mv = newmap.get_min_compat_client(); - if (v < mv.first) { - ss << "osdmap current utilizes features that require " << mv - << "; cannot set require_min_compat_client below that to " << v; + newmap.require_min_compat_client = vno; + auto mvno = newmap.get_min_compat_client(); + if (vno < mvno) { + ss << "osdmap current utilizes features that require " + << ceph_release_name(mvno) + << "; cannot set require_min_compat_client below that to " + << ceph_release_name(vno); err = -EPERM; goto reply; } - ss << "set require_min_compat_client to " << v; - pending_inc.new_require_min_compat_client = v; + string sure; + cmd_getval(g_ceph_context, cmdmap, "sure", sure); + if (sure != "--yes-i-really-mean-it") { + FeatureMap m; + mon->get_combined_feature_map(&m); + uint64_t features = ceph_release_features(vno); + bool first = true; + bool ok = true; + for (int type : { + CEPH_ENTITY_TYPE_CLIENT, + CEPH_ENTITY_TYPE_MDS, + CEPH_ENTITY_TYPE_MGR }) { + auto p = m.m.find(type); + if (p == m.m.end()) { + continue; + } + for (auto& q : p->second) { + uint64_t missing = ~q.first & features; + if (missing) { + if (first) { + ss << "cannot set require_min_compat_client to " << v << ": "; + } else { + ss << "; "; + } + first = false; + ss << q.second << " connected " << ceph_entity_type_name(type) + << "(s) look like " << ceph_release_name( + ceph_release_from_features(q.first)) + << " (missing 0x" << std::hex << missing << std::dec << ")"; + ok = false; + } + } + } + if (!ok) { + ss << "; add --yes-i-really-mean-it to do it anyway"; + err = -EPERM; + goto reply; + } + } + ss << "set require_min_compat_client to " << ceph_release_name(vno); + pending_inc.new_require_min_compat_client = vno; getline(ss, rs); wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); @@ -7360,11 +8139,17 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } else { ss << "not all up OSDs have OSD_BITWISE_HOBJ_SORT feature"; err = -EPERM; + goto reply; } } else if (key == "require_jewel_osds") { if (!osdmap.test_flag(CEPH_OSDMAP_SORTBITWISE)) { ss << "the sortbitwise flag must be set before require_jewel_osds"; err = -EPERM; + goto reply; + } else if (osdmap.require_osd_release >= CEPH_RELEASE_JEWEL) { + ss << "require_osd_release is already >= jewel"; + err = 0; + goto reply; } else if (HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_JEWEL)) { return prepare_set_flag(op, CEPH_OSDMAP_REQUIRE_JEWEL); } else { @@ -7375,6 +8160,11 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, if (!osdmap.test_flag(CEPH_OSDMAP_SORTBITWISE)) { ss << "the sortbitwise flag must be set before require_kraken_osds"; err = -EPERM; + goto reply; + } else if (osdmap.require_osd_release >= CEPH_RELEASE_KRAKEN) { + ss << "require_osd_release is already >= kraken"; + err = 0; + goto reply; } else if (HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_KRAKEN)) { bool r = prepare_set_flag(op, CEPH_OSDMAP_REQUIRE_KRAKEN); // ensure JEWEL is also set @@ -7384,20 +8174,6 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, ss << "not all up OSDs have CEPH_FEATURE_SERVER_KRAKEN feature"; err = -EPERM; } - } else if (key == "require_luminous_osds") { - if (!osdmap.test_flag(CEPH_OSDMAP_SORTBITWISE)) { - ss << "the sortbitwise flag must be set before require_luminous_osds"; - err = -EPERM; - } else if (HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_LUMINOUS)) { - bool r = prepare_set_flag(op, CEPH_OSDMAP_REQUIRE_LUMINOUS); - // ensure JEWEL and KRAKEN are also set - pending_inc.new_flags |= CEPH_OSDMAP_REQUIRE_JEWEL; - pending_inc.new_flags |= CEPH_OSDMAP_REQUIRE_KRAKEN; - return r; - } else { - ss << "not all up OSDs have CEPH_FEATURE_SERVER_LUMINOUS feature"; - err = -EPERM; - } } else { ss << "unrecognized flag '" << key << "'"; err = -EINVAL; @@ -7438,6 +8214,43 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, err = -EINVAL; } + } else if (prefix == "osd require-osd-release") { + string release; + cmd_getval(g_ceph_context, cmdmap, "release", release); + if (!osdmap.test_flag(CEPH_OSDMAP_SORTBITWISE)) { + ss << "the sortbitwise flag must be set first"; + err = -EPERM; + goto reply; + } + int rel = ceph_release_from_name(release.c_str()); + if (rel <= 0) { + ss << "unrecognized release " << release; + err = -EINVAL; + goto reply; + } + if (rel < CEPH_RELEASE_LUMINOUS) { + ss << "use this command only for luminous and later"; + err = -EINVAL; + goto reply; + } + if (rel == CEPH_RELEASE_LUMINOUS) { + if (!HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_LUMINOUS)) { + ss << "not all up OSDs have CEPH_FEATURE_SERVER_LUMINOUS feature"; + err = -EPERM; + goto reply; + } + } else { + ss << "not supported for this release yet"; + err = -EPERM; + goto reply; + } + if (rel < osdmap.require_osd_release) { + ss << "require_osd_release cannot be lowered once it has been set"; + err = -EPERM; + goto reply; + } + pending_inc.new_require_osd_release = rel; + goto update; } else if (prefix == "osd cluster_snap") { // ** DISABLE THIS FOR NOW ** ss << "cluster snapshot currently disabled (broken implementation)"; @@ -7449,80 +8262,406 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, prefix == "osd rm") { bool any = false; + bool stop = false; + bool verbose = true; vector idvec; cmd_getval(g_ceph_context, cmdmap, "ids", idvec); - for (unsigned j = 0; j < idvec.size(); j++) { - long osd = parse_osd_id(idvec[j].c_str(), &ss); - if (osd < 0) { - ss << "invalid osd id" << osd; - err = -EINVAL; - continue; - } else if (!osdmap.exists(osd)) { - ss << "osd." << osd << " does not exist. "; - continue; + for (unsigned j = 0; j < idvec.size() && !stop; j++) { + set osds; + + // wildcard? + if (j == 0 && + (idvec[0] == "any" || idvec[0] == "all" || idvec[0] == "*")) { + if (prefix == "osd in") { + // touch out osds only + osdmap.get_out_osds(osds); + } else { + osdmap.get_all_osds(osds); + } + stop = true; + verbose = false; // so the output is less noisy. + } else { + long osd = parse_osd_id(idvec[j].c_str(), &ss); + if (osd < 0) { + ss << "invalid osd id" << osd; + err = -EINVAL; + continue; + } else if (!osdmap.exists(osd)) { + ss << "osd." << osd << " does not exist. "; + continue; + } + + osds.insert(osd); } - if (prefix == "osd down") { - if (osdmap.is_down(osd)) { - ss << "osd." << osd << " is already down. "; - } else { - pending_inc.new_state[osd] = CEPH_OSD_UP; - ss << "marked down osd." << osd << ". "; - any = true; - } - } else if (prefix == "osd out") { - if (osdmap.is_out(osd)) { - ss << "osd." << osd << " is already out. "; - } else { - pending_inc.new_weight[osd] = CEPH_OSD_OUT; - if (osdmap.osd_weight[osd]) { - if (pending_inc.new_xinfo.count(osd) == 0) { - pending_inc.new_xinfo[osd] = osdmap.osd_xinfo[osd]; + + for (auto &osd : osds) { + if (prefix == "osd down") { + if (osdmap.is_down(osd)) { + if (verbose) + ss << "osd." << osd << " is already down. "; + } else { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_UP); + ss << "marked down osd." << osd << ". "; + any = true; + } + } else if (prefix == "osd out") { + if (osdmap.is_out(osd)) { + if (verbose) + ss << "osd." << osd << " is already out. "; + } else { + pending_inc.new_weight[osd] = CEPH_OSD_OUT; + if (osdmap.osd_weight[osd]) { + if (pending_inc.new_xinfo.count(osd) == 0) { + pending_inc.new_xinfo[osd] = osdmap.osd_xinfo[osd]; + } + pending_inc.new_xinfo[osd].old_weight = osdmap.osd_weight[osd]; } - pending_inc.new_xinfo[osd].old_weight = osdmap.osd_weight[osd]; + ss << "marked out osd." << osd << ". "; + any = true; } - ss << "marked out osd." << osd << ". "; - any = true; - } - } else if (prefix == "osd in") { - if (osdmap.is_in(osd)) { - ss << "osd." << osd << " is already in. "; - } else { - if (osdmap.osd_xinfo[osd].old_weight > 0) { - pending_inc.new_weight[osd] = osdmap.osd_xinfo[osd].old_weight; - if (pending_inc.new_xinfo.count(osd) == 0) { - pending_inc.new_xinfo[osd] = osdmap.osd_xinfo[osd]; + } else if (prefix == "osd in") { + if (osdmap.is_in(osd)) { + if (verbose) + ss << "osd." << osd << " is already in. "; + } else { + if (osdmap.osd_xinfo[osd].old_weight > 0) { + pending_inc.new_weight[osd] = osdmap.osd_xinfo[osd].old_weight; + if (pending_inc.new_xinfo.count(osd) == 0) { + pending_inc.new_xinfo[osd] = osdmap.osd_xinfo[osd]; + } + pending_inc.new_xinfo[osd].old_weight = 0; + } else { + pending_inc.new_weight[osd] = CEPH_OSD_IN; } - pending_inc.new_xinfo[osd].old_weight = 0; + ss << "marked in osd." << osd << ". "; + any = true; + } + } else if (prefix == "osd rm") { + err = prepare_command_osd_remove(osd); + + if (err == -EBUSY) { + if (any) + ss << ", "; + ss << "osd." << osd << " is still up; must be down before removal. "; } else { - pending_inc.new_weight[osd] = CEPH_OSD_IN; + assert(err == 0); + if (any) { + ss << ", osd." << osd; + } else { + ss << "removed osd." << osd; + } + any = true; } - ss << "marked in osd." << osd << ". "; - any = true; - } - } else if (prefix == "osd rm") { - if (osdmap.is_up(osd)) { - if (any) - ss << ", "; - ss << "osd." << osd << " is still up; must be down before removal. "; - err = -EBUSY; - } else { - pending_inc.new_state[osd] = osdmap.get_state(osd); - pending_inc.new_uuid[osd] = uuid_d(); - pending_metadata_rm.insert(osd); - if (any) { - ss << ", osd." << osd; + } + } + } + if (any) { + getline(ss, rs); + wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, err, rs, + get_last_committed() + 1)); + return true; + } + } else if (prefix == "osd add-noup" || + prefix == "osd add-nodown" || + prefix == "osd add-noin" || + prefix == "osd add-noout") { + + enum { + OP_NOUP, + OP_NODOWN, + OP_NOIN, + OP_NOOUT, + } option; + + if (prefix == "osd add-noup") { + option = OP_NOUP; + } else if (prefix == "osd add-nodown") { + option = OP_NODOWN; + } else if (prefix == "osd add-noin") { + option = OP_NOIN; + } else { + option = OP_NOOUT; + } + + bool any = false; + bool stop = false; + + vector idvec; + cmd_getval(g_ceph_context, cmdmap, "ids", idvec); + for (unsigned j = 0; j < idvec.size() && !stop; j++) { + + set osds; + + // wildcard? + if (j == 0 && + (idvec[0] == "any" || idvec[0] == "all" || idvec[0] == "*")) { + osdmap.get_all_osds(osds); + stop = true; + } else { + // try traditional single osd way + + long osd = parse_osd_id(idvec[j].c_str(), &ss); + if (osd < 0) { + // ss has reason for failure + ss << ", unable to parse osd id:\"" << idvec[j] << "\". "; + err = -EINVAL; + continue; + } + + osds.insert(osd); + } + + for (auto &osd : osds) { + + if (!osdmap.exists(osd)) { + ss << "osd." << osd << " does not exist. "; + continue; + } + + switch (option) { + case OP_NOUP: + if (osdmap.is_up(osd)) { + ss << "osd." << osd << " is already up. "; + continue; + } + + if (osdmap.is_noup(osd)) { + if (pending_inc.pending_osd_state_clear(osd, CEPH_OSD_NOUP)) + any = true; } else { - ss << "removed osd." << osd; + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NOUP); + any = true; } - any = true; - } + + break; + + case OP_NODOWN: + if (osdmap.is_down(osd)) { + ss << "osd." << osd << " is already down. "; + continue; + } + + if (osdmap.is_nodown(osd)) { + if (pending_inc.pending_osd_state_clear(osd, CEPH_OSD_NODOWN)) + any = true; + } else { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NODOWN); + any = true; + } + + break; + + case OP_NOIN: + if (osdmap.is_in(osd)) { + ss << "osd." << osd << " is already in. "; + continue; + } + + if (osdmap.is_noin(osd)) { + if (pending_inc.pending_osd_state_clear(osd, CEPH_OSD_NOIN)) + any = true; + } else { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NOIN); + any = true; + } + + break; + + case OP_NOOUT: + if (osdmap.is_out(osd)) { + ss << "osd." << osd << " is already out. "; + continue; + } + + if (osdmap.is_noout(osd)) { + if (pending_inc.pending_osd_state_clear(osd, CEPH_OSD_NOOUT)) + any = true; + } else { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NOOUT); + any = true; + } + + break; + + default: + assert(0 == "invalid option"); + } } } + if (any) { getline(ss, rs); wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, err, rs, - get_last_committed() + 1)); + get_last_committed() + 1)); + return true; + } + } else if (prefix == "osd rm-noup" || + prefix == "osd rm-nodown" || + prefix == "osd rm-noin" || + prefix == "osd rm-noout") { + + enum { + OP_NOUP, + OP_NODOWN, + OP_NOIN, + OP_NOOUT, + } option; + + if (prefix == "osd rm-noup") { + option = OP_NOUP; + } else if (prefix == "osd rm-nodown") { + option = OP_NODOWN; + } else if (prefix == "osd rm-noin") { + option = OP_NOIN; + } else { + option = OP_NOOUT; + } + + bool any = false; + bool stop = false; + + vector idvec; + cmd_getval(g_ceph_context, cmdmap, "ids", idvec); + + for (unsigned j = 0; j < idvec.size() && !stop; j++) { + + vector osds; + + // wildcard? + if (j == 0 && + (idvec[0] == "any" || idvec[0] == "all" || idvec[0] == "*")) { + + // touch previous noup/nodown/noin/noout osds only + switch (option) { + case OP_NOUP: + osdmap.get_noup_osds(&osds); + break; + case OP_NODOWN: + osdmap.get_nodown_osds(&osds); + break; + case OP_NOIN: + osdmap.get_noin_osds(&osds); + break; + case OP_NOOUT: + osdmap.get_noout_osds(&osds); + break; + default: + assert(0 == "invalid option"); + } + + // cancel any pending noup/nodown/noin/noout requests too + vector pending_state_osds; + (void) pending_inc.get_pending_state_osds(&pending_state_osds); + for (auto &p : pending_state_osds) { + + switch (option) { + case OP_NOUP: + if (!osdmap.is_noup(p) && + pending_inc.pending_osd_state_clear(p, CEPH_OSD_NOUP)) { + any = true; + } + break; + + case OP_NODOWN: + if (!osdmap.is_nodown(p) && + pending_inc.pending_osd_state_clear(p, CEPH_OSD_NODOWN)) { + any = true; + } + break; + + case OP_NOIN: + if (!osdmap.is_noin(p) && + pending_inc.pending_osd_state_clear(p, CEPH_OSD_NOIN)) { + any = true; + } + break; + + case OP_NOOUT: + if (!osdmap.is_noout(p) && + pending_inc.pending_osd_state_clear(p, CEPH_OSD_NOOUT)) { + any = true; + } + break; + + default: + assert(0 == "invalid option"); + } + } + + stop = true; + } else { + // try traditional single osd way + + long osd = parse_osd_id(idvec[j].c_str(), &ss); + if (osd < 0) { + // ss has reason for failure + ss << ", unable to parse osd id:\"" << idvec[j] << "\". "; + err = -EINVAL; + continue; + } + + osds.push_back(osd); + } + + for (auto &osd : osds) { + + if (!osdmap.exists(osd)) { + ss << "osd." << osd << " does not exist. "; + continue; + } + + switch (option) { + case OP_NOUP: + if (osdmap.is_noup(osd)) { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NOUP); + any = true; + } else if (pending_inc.pending_osd_state_clear( + osd, CEPH_OSD_NOUP)) { + any = true; + } + break; + + case OP_NODOWN: + if (osdmap.is_nodown(osd)) { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NODOWN); + any = true; + } else if (pending_inc.pending_osd_state_clear( + osd, CEPH_OSD_NODOWN)) { + any = true; + } + break; + + case OP_NOIN: + if (osdmap.is_noin(osd)) { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NOIN); + any = true; + } else if (pending_inc.pending_osd_state_clear( + osd, CEPH_OSD_NOIN)) { + any = true; + } + break; + + case OP_NOOUT: + if (osdmap.is_noout(osd)) { + pending_inc.pending_osd_state_set(osd, CEPH_OSD_NOOUT); + any = true; + } else if (pending_inc.pending_osd_state_clear( + osd, CEPH_OSD_NOOUT)) { + any = true; + } + break; + + default: + assert(0 == "invalid option"); + } + } + } + + if (any) { + getline(ss, rs); + wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, err, rs, + get_last_committed() + 1)); return true; } } else if (prefix == "osd pg-temp") { @@ -7604,9 +8743,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, goto reply; } - if (osdmap.require_min_compat_client.length() && - osdmap.require_min_compat_client < "firefly") { - ss << "require_min_compat_client " << osdmap.require_min_compat_client + if (osdmap.require_min_compat_client > 0 && + osdmap.require_min_compat_client < CEPH_RELEASE_FIREFLY) { + ss << "require_min_compat_client " + << ceph_release_name(osdmap.require_min_compat_client) << " < firefly, which is required for primary-temp"; err = -EPERM; goto reply; @@ -7620,13 +8760,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, ss << "set " << pgid << " primary_temp mapping to " << osd; goto update; } else if (prefix == "osd pg-upmap") { - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - ss << "you must set the require_luminous_osds flag to use this feature"; + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + ss << "you must complete the upgrade and set require_osd_release =" + << "luminous before using the new interface"; err = -EPERM; goto reply; } - if (osdmap.require_min_compat_client < "luminous") { - ss << "min_compat_client " << osdmap.require_min_compat_client + if (osdmap.require_min_compat_client < CEPH_RELEASE_LUMINOUS) { + ss << "min_compat_client " + << ceph_release_name(osdmap.require_min_compat_client) << " < luminous, which is required for pg-upmap"; err = -EPERM; goto reply; @@ -7682,13 +8824,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, ss << "set " << pgid << " pg_upmap mapping to " << new_pg_upmap; goto update; } else if (prefix == "osd rm-pg-upmap") { - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - ss << "you must set the require_luminous_osds flag to use this feature"; + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + ss << "you must complete the upgrade and set require_osd_release =" + << "luminous before using the new interface"; err = -EPERM; goto reply; } - if (osdmap.require_min_compat_client < "luminous") { - ss << "require_min_compat_client " << osdmap.require_min_compat_client + if (osdmap.require_min_compat_client < CEPH_RELEASE_LUMINOUS) { + ss << "require_min_compat_client " + << ceph_release_name(osdmap.require_min_compat_client) << " < luminous, which is required for pg-upmap"; err = -EPERM; goto reply; @@ -7711,11 +8855,6 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, err = -EINVAL; goto reply; } - if (!osdmap.pg_exists(pgid)) { - ss << "pg " << pgid << " does not exist"; - err = -ENOENT; - goto reply; - } if (pending_inc.new_pg_upmap.count(pgid) || pending_inc.old_pg_upmap.count(pgid)) { dout(10) << __func__ << " waiting for pending update on " << pgid << dendl; @@ -7727,13 +8866,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, ss << "clear " << pgid << " pg_upmap mapping"; goto update; } else if (prefix == "osd pg-upmap-items") { - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - ss << "you must set the require_luminous_osds flag to use this feature"; + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + ss << "you must complete the upgrade and set require_osd_release =" + << "luminous before using the new interface"; err = -EPERM; goto reply; } - if (osdmap.require_min_compat_client < "luminous") { - ss << "require_min_compat_client " << osdmap.require_min_compat_client + if (osdmap.require_min_compat_client < CEPH_RELEASE_LUMINOUS) { + ss << "require_min_compat_client " + << ceph_release_name(osdmap.require_min_compat_client) << " < luminous, which is required for pg-upmap"; err = -EPERM; goto reply; @@ -7802,13 +8943,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, ss << "set " << pgid << " pg_upmap_items mapping to " << new_pg_upmap_items; goto update; } else if (prefix == "osd rm-pg-upmap-items") { - if (!osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { - ss << "you must set the require_luminous_osds flag to use this feature"; + if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { + ss << "you must complete the upgrade and set require_osd_release =" + << "luminous before using the new interface"; err = -EPERM; goto reply; } - if (osdmap.require_min_compat_client < "luminous") { - ss << "require_min_compat_client " << osdmap.require_min_compat_client + if (osdmap.require_min_compat_client < CEPH_RELEASE_LUMINOUS) { + ss << "require_min_compat_client " + << ceph_release_name(osdmap.require_min_compat_client) << " < luminous, which is required for pg-upmap"; err = -EPERM; goto reply; @@ -7831,11 +8974,6 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, err = -EINVAL; goto reply; } - if (!osdmap.pg_exists(pgid)) { - ss << "pg " << pgid << " does not exist"; - err = -ENOENT; - goto reply; - } if (pending_inc.new_pg_upmap_items.count(pgid) || pending_inc.old_pg_upmap_items.count(pgid)) { dout(10) << __func__ << " waiting for pending update on " << pgid << dendl; @@ -7867,9 +9005,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, err = -EINVAL; goto reply; } - if (osdmap.require_min_compat_client.length() && - osdmap.require_min_compat_client < "firefly") { - ss << "require_min_compat_client " << osdmap.require_min_compat_client + if (osdmap.require_min_compat_client > 0 && + osdmap.require_min_compat_client < CEPH_RELEASE_FIREFLY) { + ss << "require_min_compat_client " + << ceph_release_name(osdmap.require_min_compat_client) << " < firefly, which is required for primary-affinity"; err = -EPERM; goto reply; @@ -7973,112 +9112,208 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, return true; } + } else if (prefix == "osd destroy" || prefix == "osd purge") { + /* Destroying an OSD means that we don't expect to further make use of + * the OSDs data (which may even become unreadable after this operation), + * and that we are okay with scrubbing all its cephx keys and config-key + * data (which may include lockbox keys, thus rendering the osd's data + * unreadable). + * + * The OSD will not be removed. Instead, we will mark it as destroyed, + * such that a subsequent call to `create` will not reuse the osd id. + * This will play into being able to recreate the OSD, at the same + * crush location, with minimal data movement. + */ + + // make sure authmon is writeable. + if (!mon->authmon()->is_writeable()) { + dout(10) << __func__ << " waiting for auth mon to be writeable for " + << "osd destroy" << dendl; + mon->authmon()->wait_for_writeable(op, new C_RetryMessage(this, op)); + return false; + } + + int64_t id; + if (!cmd_getval(g_ceph_context, cmdmap, "id", id)) { + ss << "unable to parse osd id value '" + << cmd_vartype_stringify(cmdmap["id"]) << ""; + err = -EINVAL; + goto reply; + } + + bool is_destroy = (prefix == "osd destroy"); + if (!is_destroy) { + assert("osd purge" == prefix); + } + + string sure; + if (!cmd_getval(g_ceph_context, cmdmap, "sure", sure) || + sure != "--yes-i-really-mean-it") { + ss << "Are you SURE? This will mean real, permanent data loss, as well " + << "as cephx and lockbox keys. Pass --yes-i-really-mean-it if you " + << "really do."; + err = -EPERM; + goto reply; + } else if (is_destroy && !osdmap.exists(id)) { + ss << "osd." << id << " does not exist"; + err = -ENOENT; + goto reply; + } else if (osdmap.is_up(id)) { + ss << "osd." << id << " is not `down`."; + err = -EBUSY; + goto reply; + } else if (is_destroy && osdmap.is_destroyed(id)) { + ss << "destroyed osd." << id; + err = 0; + goto reply; + } + + bool goto_reply = false; + + paxos->plug(); + if (is_destroy) { + err = prepare_command_osd_destroy(id, ss); + // we checked above that it should exist. + assert(err != -ENOENT); + } else { + err = prepare_command_osd_purge(id, ss); + if (err == -ENOENT) { + err = 0; + ss << "osd." << id << " does not exist."; + goto_reply = true; + } + } + paxos->unplug(); + + if (err < 0 || goto_reply) { + goto reply; + } + + if (is_destroy) { + ss << "destroyed osd." << id; + } else { + ss << "purged osd." << id; + } + + getline(ss, rs); + wait_for_finished_proposal(op, + new Monitor::C_Command(mon, op, 0, rs, get_last_committed() + 1)); + force_immediate_propose(); + return true; + + } else if (prefix == "osd new") { + + // make sure authmon is writeable. + if (!mon->authmon()->is_writeable()) { + dout(10) << __func__ << " waiting for auth mon to be writeable for " + << "osd destroy" << dendl; + mon->authmon()->wait_for_writeable(op, new C_RetryMessage(this, op)); + return false; + } + + map secrets_map; + + bufferlist bl = m->get_data(); + string secrets_json = bl.to_str(); + dout(20) << __func__ << " osd new json = " << secrets_json << dendl; + + err = get_json_str_map(secrets_json, ss, &secrets_map); + if (err < 0) + goto reply; + + dout(20) << __func__ << " osd new secrets " << secrets_map << dendl; + + paxos->plug(); + err = prepare_command_osd_new(op, cmdmap, secrets_map, ss, f.get()); + paxos->unplug(); + + if (err < 0) { + goto reply; + } + + if (f) { + f->flush(rdata); + } else { + rdata.append(ss); + } + + if (err == EEXIST) { + // idempotent operation + err = 0; + goto reply; + } + + wait_for_finished_proposal(op, + new Monitor::C_Command(mon, op, 0, rs, rdata, + get_last_committed() + 1)); + force_immediate_propose(); + return true; + } else if (prefix == "osd create") { - int i = -1; // optional id provided? - int64_t id = -1; - if (cmd_getval(g_ceph_context, cmdmap, "id", id)) { - if (id < 0) { - ss << "invalid osd id value '" << id << "'"; + int64_t id = -1, cmd_id = -1; + if (cmd_getval(g_ceph_context, cmdmap, "id", cmd_id)) { + if (cmd_id < 0) { + ss << "invalid osd id value '" << cmd_id << "'"; err = -EINVAL; goto reply; } - dout(10) << " osd create got id " << id << dendl; + dout(10) << " osd create got id " << cmd_id << dendl; } - // optional uuid provided? uuid_d uuid; string uuidstr; if (cmd_getval(g_ceph_context, cmdmap, "uuid", uuidstr)) { if (!uuid.parse(uuidstr.c_str())) { - ss << "invalid uuid value '" << uuidstr << "'"; - err = -EINVAL; - goto reply; - } - dout(10) << " osd create got uuid " << uuid << dendl; - i = osdmap.identify_osd(uuid); - if (i >= 0) { - // osd already exists - if (id >= 0 && i != id) { - ss << "uuid " << uuidstr << " already in use for different id " << i; - err = -EINVAL; - goto reply; - } - err = 0; - if (f) { - f->open_object_section("created_osd"); - f->dump_int("osdid", i); - f->close_section(); - f->flush(rdata); - } else { - ss << i; - rdata.append(ss); - } - goto reply; - } - // i < 0 - if (id >= 0) { - if (osdmap.exists(id)) { - ss << "id " << id << " already in use and does not match uuid " - << uuid; - err = -EINVAL; - goto reply; - } - if (pending_inc.new_state.count(id)) { - // osd is about to exist - wait_for_finished_proposal(op, new C_RetryMessage(this, op)); - return true; - } - i = id; - } - if (pending_inc.identify_osd(uuid) >= 0) { - // osd is about to exist - wait_for_finished_proposal(op, new C_RetryMessage(this, op)); - return true; - } - if (i >= 0) { - // raise max_osd - if (osdmap.get_max_osd() <= i && pending_inc.new_max_osd <= i) - pending_inc.new_max_osd = i + 1; - goto done; + ss << "invalid uuid value '" << uuidstr << "'"; + err = -EINVAL; + goto reply; } + // we only care about the id if we also have the uuid, to + // ensure the operation's idempotency. + id = cmd_id; } - // allocate a new id - for (i=0; i < osdmap.get_max_osd(); i++) { - if (!osdmap.exists(i) && - pending_inc.new_up_client.count(i) == 0 && - (pending_inc.new_state.count(i) == 0 || - (pending_inc.new_state[i] & CEPH_OSD_EXISTS) == 0)) { - pending_inc.new_weight[i] = CEPH_OSD_OUT; - goto done; + int32_t new_id = -1; + err = prepare_command_osd_create(id, uuid, &new_id, ss); + if (err < 0) { + if (err == -EAGAIN) { + wait_for_finished_proposal(op, new C_RetryMessage(this, op)); + return true; } + // a check has failed; reply to the user. + goto reply; + + } else if (err == EEXIST) { + // this is an idempotent operation; we can go ahead and reply. + if (f) { + f->open_object_section("created_osd"); + f->dump_int("osdid", new_id); + f->close_section(); + f->flush(rdata); + } else { + ss << new_id; + rdata.append(ss); + } + err = 0; + goto reply; } - // raise max_osd - if (pending_inc.new_max_osd < 0) - pending_inc.new_max_osd = osdmap.get_max_osd() + 1; - else - pending_inc.new_max_osd++; - i = pending_inc.new_max_osd - 1; - -done: - dout(10) << " creating osd." << i << dendl; - pending_inc.new_state[i] |= CEPH_OSD_EXISTS | CEPH_OSD_NEW; - if (!uuid.is_zero()) - pending_inc.new_uuid[i] = uuid; + do_osd_create(id, uuid, &new_id); + if (f) { f->open_object_section("created_osd"); - f->dump_int("osdid", i); + f->dump_int("osdid", new_id); f->close_section(); f->flush(rdata); } else { - ss << i; + ss << new_id; rdata.append(ss); } - wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, rdata, - get_last_committed() + 1)); + wait_for_finished_proposal(op, + new Monitor::C_Command(mon, op, 0, rs, rdata, + get_last_committed() + 1)); return true; } else if (prefix == "osd blacklist clear") { @@ -8263,9 +9498,9 @@ done: goto reply; } - bool implicit_ruleset_creation = false; - string ruleset_name; - cmd_getval(g_ceph_context, cmdmap, "ruleset", ruleset_name); + bool implicit_rule_creation = false; + string rule_name; + cmd_getval(g_ceph_context, cmdmap, "rule", rule_name); string erasure_code_profile; cmd_getval(g_ceph_context, cmdmap, "erasure_code_profile", erasure_code_profile); @@ -8291,24 +9526,24 @@ done: goto wait; } } - if (ruleset_name == "") { - implicit_ruleset_creation = true; + if (rule_name == "") { + implicit_rule_creation = true; if (erasure_code_profile == "default") { - ruleset_name = "erasure-code"; + rule_name = "erasure-code"; } else { - dout(1) << "implicitly use ruleset named after the pool: " + dout(1) << "implicitly use rule named after the pool: " << poolstr << dendl; - ruleset_name = poolstr; + rule_name = poolstr; } } } else { - //NOTE:for replicated pool,cmd_map will put ruleset_name to erasure_code_profile field - ruleset_name = erasure_code_profile; + //NOTE:for replicated pool,cmd_map will put rule_name to erasure_code_profile field + rule_name = erasure_code_profile; } - if (!implicit_ruleset_creation && ruleset_name != "") { - int ruleset; - err = get_crush_ruleset(ruleset_name, &ruleset, &ss); + if (!implicit_rule_creation && rule_name != "") { + int rule; + err = get_crush_rule(rule_name, &rule, &ss); if (err == -EAGAIN) { wait_for_finished_proposal(op, new C_RetryMessage(this, op)); return true; @@ -8335,7 +9570,7 @@ done: err = prepare_new_pool(poolstr, 0, // auid=0 for admin created pool -1, // default crush rule - ruleset_name, + rule_name, pg_num, pgp_num, erasure_code_profile, pool_type, (uint64_t)expected_num_objects, @@ -8481,9 +9716,8 @@ done: // make sure new tier is empty string force_nonempty; cmd_getval(g_ceph_context, cmdmap, "force_nonempty", force_nonempty); - const pool_stat_t& tier_stats = - mon->pgmon()->pg_map.get_pg_pool_sum_stat(tierpool_id); - if (tier_stats.stats.sum.num_objects != 0 && + const pool_stat_t *pstats = mon->pgservice->get_pool_stat(tierpool_id); + if (pstats && pstats->stats.sum.num_objects != 0 && force_nonempty != "--force-nonempty") { ss << "tier pool '" << tierpoolstr << "' is not empty; --force-nonempty to force"; err = -ENOTEMPTY; @@ -8795,10 +10029,10 @@ done: mode != pg_pool_t::CACHEMODE_PROXY && mode != pg_pool_t::CACHEMODE_READPROXY))) { - const pool_stat_t& tier_stats = - mon->pgmon()->pg_map.get_pg_pool_sum_stat(pool_id); + const pool_stat_t* pstats = + mon->pgservice->get_pool_stat(pool_id); - if (tier_stats.stats.sum.num_objects_dirty > 0) { + if (pstats && pstats->stats.sum.num_objects_dirty > 0) { ss << "unable to set cache-mode '" << pg_pool_t::get_cache_mode_name(mode) << "' on pool '" << poolstr << "': dirty objects found"; @@ -8863,9 +10097,9 @@ done: goto reply; } // make sure new tier is empty - const pool_stat_t& tier_stats = - mon->pgmon()->pg_map.get_pg_pool_sum_stat(tierpool_id); - if (tier_stats.stats.sum.num_objects != 0) { + const pool_stat_t *pstats = + mon->pgservice->get_pool_stat(tierpool_id); + if (pstats && pstats->stats.sum.num_objects != 0) { ss << "tier pool '" << tierpoolstr << "' is not empty"; err = -ENOTEMPTY; goto reply; @@ -9003,16 +10237,15 @@ done: cmd_getval(g_ceph_context, cmdmap, "no_increasing", no_increasing); string out_str; mempool::osdmap::map new_weights; - err = reweight::by_utilization(osdmap, - mon->pgmon()->pg_map, - oload, - max_change, - max_osds, - by_pg, - pools.empty() ? NULL : &pools, - no_increasing == "--no-increasing", - &new_weights, - &ss, &out_str, f.get()); + err = mon->pgservice->reweight_by_utilization(osdmap, + oload, + max_change, + max_osds, + by_pg, + pools.empty() ? NULL : &pools, + no_increasing == "--no-increasing", + &new_weights, + &ss, &out_str, f.get()); if (err >= 0) { dout(10) << "reweight::by_utilization: finished with " << out_str << dendl; } diff --git a/ceph/src/mon/OSDMonitor.h b/ceph/src/mon/OSDMonitor.h index 44f013f27..3f258815a 100644 --- a/ceph/src/mon/OSDMonitor.h +++ b/ceph/src/mon/OSDMonitor.h @@ -147,7 +147,7 @@ public: bool check_failures(utime_t now); bool check_failure(utime_t now, int target_osd, failure_info_t& fi); - void force_failure(utime_t now, int target_osd); + void force_failure(utime_t now, int target_osd, int by); // the time of last msg(MSG_ALIVE and MSG_PGTEMP) proposed without delay utime_t last_attempted_minwait_time; @@ -316,20 +316,20 @@ private: ErasureCodeProfile &profile, bool force, ostream *ss); - int crush_ruleset_create_erasure(const string &name, - const string &profile, - int *ruleset, - ostream *ss); - int get_crush_ruleset(const string &ruleset_name, - int *crush_ruleset, + int crush_rule_create_erasure(const string &name, + const string &profile, + int *rule, + ostream *ss); + int get_crush_rule(const string &rule_name, + int *crush_rule, ostream *ss); int get_erasure_code(const string &erasure_code_profile, ErasureCodeInterfaceRef *erasure_code, ostream *ss) const; - int prepare_pool_crush_ruleset(const unsigned pool_type, + int prepare_pool_crush_rule(const unsigned pool_type, const string &erasure_code_profile, - const string &ruleset_name, - int *crush_ruleset, + const string &rule_name, + int *crush_rule, ostream *ss); bool erasure_code_profile_in_use( const mempool::osdmap::map &pools, @@ -347,8 +347,8 @@ private: unsigned *stripe_width, ostream *ss); int prepare_new_pool(string& name, uint64_t auid, - int crush_ruleset, - const string &crush_ruleset_name, + int crush_rule, + const string &crush_rule_name, unsigned pg_num, unsigned pgp_num, const string &erasure_code_profile, const unsigned pool_type, @@ -429,6 +429,7 @@ private: OpTracker op_tracker; int load_metadata(int osd, map& m, ostream *err); + void count_metadata(const string& field, Formatter *f); int get_osd_objectstore_type(int osd, std::string *type); bool is_pool_currently_all_bluestore(int64_t pool_id, const pg_pool_t &pool, ostream *err); @@ -452,8 +453,9 @@ private: std::mutex creating_pgs_lock; creating_pgs_t update_pending_pgs(const OSDMap::Incremental& inc); - void trim_creating_pgs(creating_pgs_t *creating_pgs, const PGMap& pgm); - void scan_for_creating_pgs( + void trim_creating_pgs(creating_pgs_t *creating_pgs, + const ceph::unordered_map& pgm); + unsigned scan_for_creating_pgs( const mempool::osdmap::map& pools, const mempool::osdmap::set& removed_pools, utime_t modified, @@ -463,13 +465,13 @@ private: void check_pg_creates_subs(); epoch_t send_pg_creates(int osd, Connection *con, epoch_t next); + int32_t _allocate_osd_id(int32_t* existing_id); + public: OSDMonitor(CephContext *cct, Monitor *mn, Paxos *p, const string& service_name); void tick() override; // check state, take actions - int parse_osd_id(const char *s, stringstream *pss); - void get_health(list >& summary, list > *detail, CephContext *cct) const override; @@ -477,6 +479,41 @@ public: bool prepare_command(MonOpRequestRef op); bool prepare_command_impl(MonOpRequestRef op, map& cmdmap); + int validate_osd_create( + const int32_t id, + const uuid_d& uuid, + const bool check_osd_exists, + int32_t* existing_id, + stringstream& ss); + int prepare_command_osd_create( + const int32_t id, + const uuid_d& uuid, + int32_t* existing_id, + stringstream& ss); + void do_osd_create(const int32_t id, const uuid_d& uuid, int32_t* new_id); + int prepare_command_osd_purge(int32_t id, stringstream& ss); + int prepare_command_osd_destroy(int32_t id, stringstream& ss); + int _prepare_command_osd_crush_remove( + CrushWrapper &newcrush, + int32_t id, + int32_t ancestor, + bool has_ancestor, + bool unlink_only); + void do_osd_crush_remove(CrushWrapper& newcrush); + int prepare_command_osd_crush_remove( + CrushWrapper &newcrush, + int32_t id, + int32_t ancestor, + bool has_ancestor, + bool unlink_only); + int prepare_command_osd_remove(int32_t id); + int prepare_command_osd_new( + MonOpRequestRef op, + const map& cmdmap, + const map& secrets, + stringstream &ss, + Formatter *f); + int prepare_command_pool_set(map &cmdmap, stringstream& ss); diff --git a/ceph/src/mon/PGMap.cc b/ceph/src/mon/PGMap.cc index ac7ba802b..c0277b7a5 100644 --- a/ceph/src/mon/PGMap.cc +++ b/ceph/src/mon/PGMap.cc @@ -14,1504 +14,2141 @@ #define dout_context g_ceph_context -// -- - -void PGMap::Incremental::encode(bufferlist &bl, uint64_t features) const -{ - if ((features & CEPH_FEATURE_MONENC) == 0) { - __u8 v = 4; - ::encode(v, bl); - ::encode(version, bl); - ::encode(pg_stat_updates, bl); - ::encode(osd_stat_updates, bl); - ::encode(osd_stat_rm, bl); - ::encode(osdmap_epoch, bl); - ::encode(pg_scan, bl); - ::encode(full_ratio, bl); - ::encode(nearfull_ratio, bl); - ::encode(pg_remove, bl); - return; - } - - ENCODE_START(7, 5, bl); - ::encode(version, bl); - ::encode(pg_stat_updates, bl); - ::encode(osd_stat_updates, bl); - ::encode(osd_stat_rm, bl); - ::encode(osdmap_epoch, bl); - ::encode(pg_scan, bl); - ::encode(full_ratio, bl); - ::encode(nearfull_ratio, bl); - ::encode(pg_remove, bl); - ::encode(stamp, bl); - ::encode(osd_epochs, bl); +MEMPOOL_DEFINE_OBJECT_FACTORY(PGMapDigest, pgmap_digest, pgmap); +MEMPOOL_DEFINE_OBJECT_FACTORY(PGMap, pgmap, pgmap); +MEMPOOL_DEFINE_OBJECT_FACTORY(PGMap::Incremental, pgmap_inc, pgmap); + + +// --------------------- +// PGMapDigest + +void PGMapDigest::encode(bufferlist& bl, uint64_t features) const +{ + // NOTE: see PGMap::encode_digest + ENCODE_START(1, 1, bl); + ::encode(num_pg, bl); + ::encode(num_pg_active, bl); + ::encode(num_pg_unknown, bl); + ::encode(num_osd, bl); + ::encode(pg_pool_sum, bl, features); + ::encode(pg_sum, bl, features); + ::encode(osd_sum, bl); + ::encode(num_pg_by_state, bl); + ::encode(num_pg_by_osd, bl); + ::encode(num_pg_by_pool, bl); + ::encode(osd_last_seq, bl); + ::encode(per_pool_sum_delta, bl, features); + ::encode(per_pool_sum_deltas_stamps, bl); + ::encode(pg_sum_delta, bl, features); + ::encode(stamp_delta, bl); + ::encode(avail_space_by_rule, bl); ENCODE_FINISH(bl); } -void PGMap::Incremental::decode(bufferlist::iterator &bl) -{ - DECODE_START_LEGACY_COMPAT_LEN(7, 5, 5, bl); - ::decode(version, bl); - if (struct_v < 3) { - pg_stat_updates.clear(); - __u32 n; - ::decode(n, bl); - while (n--) { - old_pg_t opgid; - ::decode(opgid, bl); - pg_t pgid = opgid; - ::decode(pg_stat_updates[pgid], bl); - } - } else { - ::decode(pg_stat_updates, bl); - } - ::decode(osd_stat_updates, bl); - ::decode(osd_stat_rm, bl); - ::decode(osdmap_epoch, bl); - ::decode(pg_scan, bl); - if (struct_v >= 2) { - ::decode(full_ratio, bl); - ::decode(nearfull_ratio, bl); - } - if (struct_v < 3) { - pg_remove.clear(); - __u32 n; - ::decode(n, bl); - while (n--) { - old_pg_t opgid; - ::decode(opgid, bl); - pg_remove.insert(pg_t(opgid)); - } - } else { - ::decode(pg_remove, bl); - } - if (struct_v < 4 && full_ratio == 0) { - full_ratio = -1; - } - if (struct_v < 4 && nearfull_ratio == 0) { - nearfull_ratio = -1; - } - if (struct_v >= 6) - ::decode(stamp, bl); - if (struct_v >= 7) { - ::decode(osd_epochs, bl); - } else { - for (map::iterator i = osd_stat_updates.begin(); - i != osd_stat_updates.end(); - ++i) { - // This isn't accurate, but will cause trimming to behave like - // previously. - osd_epochs.insert(make_pair(i->first, osdmap_epoch)); - } - } - DECODE_FINISH(bl); -} - -void PGMap::Incremental::dump(Formatter *f) const -{ - f->dump_unsigned("version", version); - f->dump_stream("stamp") << stamp; - f->dump_unsigned("osdmap_epoch", osdmap_epoch); - f->dump_unsigned("pg_scan_epoch", pg_scan); - f->dump_float("full_ratio", full_ratio); - f->dump_float("nearfull_ratio", nearfull_ratio); - - f->open_array_section("pg_stat_updates"); - for (map::const_iterator p = pg_stat_updates.begin(); p != pg_stat_updates.end(); ++p) { - f->open_object_section("pg_stat"); - f->dump_stream("pgid") << p->first; - p->second.dump(f); +void PGMapDigest::decode(bufferlist::iterator& p) +{ + DECODE_START(1, p); + ::decode(num_pg, p); + ::decode(num_pg_active, p); + ::decode(num_pg_unknown, p); + ::decode(num_osd, p); + ::decode(pg_pool_sum, p); + ::decode(pg_sum, p); + ::decode(osd_sum, p); + ::decode(num_pg_by_state, p); + ::decode(num_pg_by_osd, p); + ::decode(num_pg_by_pool, p); + ::decode(osd_last_seq, p); + ::decode(per_pool_sum_delta, p); + ::decode(per_pool_sum_deltas_stamps, p); + ::decode(pg_sum_delta, p); + ::decode(stamp_delta, p); + ::decode(avail_space_by_rule, p); + DECODE_FINISH(p); +} + +void PGMapDigest::dump(Formatter *f) const +{ + f->dump_unsigned("num_pg", num_pg); + f->dump_unsigned("num_pg_active", num_pg_active); + f->dump_unsigned("num_pg_unknown", num_pg_unknown); + f->dump_unsigned("num_osd", num_osd); + f->dump_object("pool_sum", pg_sum); + f->dump_object("osd_sum", osd_sum); + f->open_array_section("pool_stats"); + for (auto& p : pg_pool_sum) { + f->open_object_section("pool_stat"); + f->dump_int("poolid", p.first); + auto q = num_pg_by_pool.find(p.first); + if (q != num_pg_by_pool.end()) + f->dump_unsigned("num_pg", q->second); + p.second.dump(f); f->close_section(); } f->close_section(); - - f->open_array_section("osd_stat_updates"); - for (map::const_iterator p = osd_stat_updates.begin(); p != osd_stat_updates.end(); ++p) { + f->open_array_section("osd_stats"); + int i = 0; + // TODO: this isn't really correct since we can dump non-existent OSDs + // I dunno what osd_last_seq is set to in that case... + for (auto& p : osd_last_seq) { f->open_object_section("osd_stat"); - f->dump_int("osd", p->first); - p->second.dump(f); + f->dump_int("osd", i); + f->dump_unsigned("seq", p); f->close_section(); + ++i; } f->close_section(); - - f->open_array_section("osd_stat_removals"); - for (set::const_iterator p = osd_stat_rm.begin(); p != osd_stat_rm.end(); ++p) - f->dump_int("osd", *p); + f->open_array_section("num_pg_by_state"); + for (auto& p : num_pg_by_state) { + f->open_object_section("count"); + f->dump_string("state", pg_state_string(p.first)); + f->dump_unsigned("num", p.second); + f->close_section(); + } f->close_section(); - - f->open_array_section("pg_removals"); - for (set::const_iterator p = pg_remove.begin(); p != pg_remove.end(); ++p) - f->dump_stream("pgid") << *p; + f->open_array_section("num_pg_by_osd"); + for (auto& p : num_pg_by_osd) { + f->open_object_section("count"); + f->dump_unsigned("osd", p.first); + f->dump_unsigned("num_primary_pg", p.second.primary); + f->dump_unsigned("num_acting_pg", p.second.acting); + f->dump_unsigned("num_up_pg", p.second.up); + f->close_section(); + } f->close_section(); } -void PGMap::Incremental::generate_test_instances(list& o) +void PGMapDigest::generate_test_instances(list& ls) { - o.push_back(new Incremental); - o.push_back(new Incremental); - o.back()->version = 1; - o.back()->stamp = utime_t(123,345); - o.push_back(new Incremental); - o.back()->version = 2; - o.back()->pg_stat_updates[pg_t(1,2,3)] = pg_stat_t(); - o.back()->osd_stat_updates[5] = osd_stat_t(); - o.back()->osd_epochs[5] = 12; - o.push_back(new Incremental); - o.back()->version = 3; - o.back()->osdmap_epoch = 1; - o.back()->pg_scan = 2; - o.back()->full_ratio = .2; - o.back()->nearfull_ratio = .3; - o.back()->pg_stat_updates[pg_t(4,5,6)] = pg_stat_t(); - o.back()->osd_stat_updates[6] = osd_stat_t(); - o.back()->osd_epochs[6] = 12; - o.back()->pg_remove.insert(pg_t(1,2,3)); - o.back()->osd_stat_rm.insert(5); + ls.push_back(new PGMapDigest); } +inline std::string percentify(const float& a) { + std::stringstream ss; + if (a < 0.01) + ss << "0"; + else + ss << std::fixed << std::setprecision(2) << a; + return ss.str(); +} -// -- - -void PGMap::apply_incremental(CephContext *cct, const Incremental& inc) +void PGMapDigest::print_summary(Formatter *f, ostream *out) const { - assert(inc.version == version+1); - version++; - - utime_t delta_t; - delta_t = inc.stamp; - delta_t -= stamp; - stamp = inc.stamp; - - pool_stat_t pg_sum_old = pg_sum; - ceph::unordered_map pg_pool_sum_old; + if (f) + f->open_array_section("pgs_by_state"); - bool ratios_changed = false; - if (inc.full_ratio != full_ratio && inc.full_ratio != -1) { - full_ratio = inc.full_ratio; - ratios_changed = true; + // list is descending numeric order (by count) + multimap state_by_count; // count -> state + for (auto p = num_pg_by_state.begin(); + p != num_pg_by_state.end(); + ++p) { + state_by_count.insert(make_pair(p->second, p->first)); } - if (inc.nearfull_ratio != nearfull_ratio && inc.nearfull_ratio != -1) { - nearfull_ratio = inc.nearfull_ratio; - ratios_changed = true; + if (f) { + for (auto p = state_by_count.rbegin(); + p != state_by_count.rend(); + ++p) + { + f->open_object_section("pgs_by_state_element"); + f->dump_string("state_name", pg_state_string(p->second)); + f->dump_unsigned("count", p->first); + f->close_section(); + } } - if (ratios_changed) - redo_full_sets(); + if (f) + f->close_section(); - for (map::const_iterator p = inc.pg_stat_updates.begin(); - p != inc.pg_stat_updates.end(); - ++p) { - const pg_t &update_pg(p->first); - const pg_stat_t &update_stat(p->second); + if (f) { + f->dump_unsigned("num_pgs", num_pg); + f->dump_unsigned("num_pools", pg_pool_sum.size()); + f->dump_unsigned("num_objects", pg_sum.stats.sum.num_objects); + f->dump_unsigned("data_bytes", pg_sum.stats.sum.num_bytes); + f->dump_unsigned("bytes_used", osd_sum.kb_used * 1024ull); + f->dump_unsigned("bytes_avail", osd_sum.kb_avail * 1024ull); + f->dump_unsigned("bytes_total", osd_sum.kb * 1024ull); + } else { + *out << " pools: " << pg_pool_sum.size() << " pools, " + << num_pg << " pgs\n"; + *out << " objects: " << si_t(pg_sum.stats.sum.num_objects) << " objects, " + << prettybyte_t(pg_sum.stats.sum.num_bytes) << "\n"; + *out << " usage: " + << kb_t(osd_sum.kb_used) << " used, " + << kb_t(osd_sum.kb_avail) << " / " + << kb_t(osd_sum.kb) << " avail\n"; + *out << " pgs: "; + } - if (pg_pool_sum_old.count(update_pg.pool()) == 0) - pg_pool_sum_old[update_pg.pool()] = pg_pool_sum[update_pg.pool()]; + bool pad = false; - ceph::unordered_map::iterator t = pg_stat.find(update_pg); - if (t == pg_stat.end()) { - ceph::unordered_map::value_type v(update_pg, update_stat); - pg_stat.insert(v); + if (num_pg_unknown > 0) { + float p = (float)num_pg_unknown / (float)num_pg; + if (f) { + f->dump_float("unknown_pgs_ratio", p); } else { - stat_pg_sub(update_pg, t->second); - t->second = update_stat; + char b[20]; + snprintf(b, sizeof(b), "%.3lf", p * 100.0); + *out << b << "% pgs unknown\n"; + pad = true; } - stat_pg_add(update_pg, update_stat); } - assert(osd_stat.size() == osd_epochs.size()); - for (map::const_iterator p = - inc.get_osd_stat_updates().begin(); - p != inc.get_osd_stat_updates().end(); - ++p) { - int osd = p->first; - const osd_stat_t &new_stats(p->second); - ceph::unordered_map::iterator t = osd_stat.find(osd); - if (t == osd_stat.end()) { - ceph::unordered_map::value_type v(osd, new_stats); - osd_stat.insert(v); + int num_pg_inactive = num_pg - num_pg_active - num_pg_unknown; + if (num_pg_inactive > 0) { + float p = (float)num_pg_inactive / (float)num_pg; + if (f) { + f->dump_float("inactive_pgs_ratio", p); } else { - stat_osd_sub(t->second); - t->second = new_stats; + if (pad) { + *out << " "; + } + char b[20]; + snprintf(b, sizeof(b), "%.3f", p * 100.0); + *out << b << "% pgs not active\n"; + pad = true; } - ceph::unordered_map::iterator i = osd_epochs.find(osd); - map::const_iterator j = inc.get_osd_epochs().find(osd); - assert(j != inc.get_osd_epochs().end()); - - if (i == osd_epochs.end()) - osd_epochs.insert(*j); - else - i->second = j->second; - - stat_osd_add(new_stats); - - // adjust [near]full status - register_nearfull_status(osd, new_stats); } - set deleted_pools; - for (set::const_iterator p = inc.pg_remove.begin(); - p != inc.pg_remove.end(); - ++p) { - const pg_t &removed_pg(*p); - ceph::unordered_map::iterator s = pg_stat.find(removed_pg); - if (s != pg_stat.end()) { - stat_pg_sub(removed_pg, s->second); - pg_stat.erase(s); + + list sl; + overall_recovery_summary(f, &sl); + if (!f && !sl.empty()) { + for (auto p = sl.begin(); p != sl.end(); ++p) { + if (pad) { + *out << " "; + } + *out << *p << "\n"; + pad = true; } - if (removed_pg.ps() == 0) - deleted_pools.insert(removed_pg.pool()); - } - for (set::iterator p = deleted_pools.begin(); - p != deleted_pools.end(); - ++p) { - dout(20) << " deleted pool " << *p << dendl; - deleted_pool(*p); } + sl.clear(); - for (set::iterator p = inc.get_osd_stat_rm().begin(); - p != inc.get_osd_stat_rm().end(); - ++p) { - ceph::unordered_map::iterator t = osd_stat.find(*p); - if (t != osd_stat.end()) { - stat_osd_sub(t->second); - osd_stat.erase(t); + if (!f) { + unsigned max_width = 1; + for (multimap::reverse_iterator p = state_by_count.rbegin(); + p != state_by_count.rend(); + ++p) + { + std::stringstream ss; + ss << p->first; + max_width = MAX(ss.str().size(), max_width); } - // remove these old osds from full/nearfull set(s), too - nearfull_osds.erase(*p); - full_osds.erase(*p); + for (multimap::reverse_iterator p = state_by_count.rbegin(); + p != state_by_count.rend(); + ++p) + { + if (pad) { + *out << " "; + } + pad = true; + out->setf(std::ios::left); + *out << std::setw(max_width) << p->first + << " " << pg_state_string(p->second) << "\n"; + out->unsetf(std::ios::left); + } } - // calculate a delta, and average over the last 2 deltas. - pool_stat_t d = pg_sum; - d.stats.sub(pg_sum_old.stats); - pg_sum_deltas.push_back(make_pair(d, delta_t)); - stamp_delta += delta_t; + ostringstream ss_rec_io; + overall_recovery_rate_summary(f, &ss_rec_io); + ostringstream ss_client_io; + overall_client_io_rate_summary(f, &ss_client_io); + ostringstream ss_cache_io; + overall_cache_io_rate_summary(f, &ss_cache_io); - pg_sum_delta.stats.add(d.stats); - if (pg_sum_deltas.size() > (std::list< pair >::size_type)MAX(1, cct ? cct->_conf->mon_stat_smooth_intervals : 1)) { - pg_sum_delta.stats.sub(pg_sum_deltas.front().first.stats); - stamp_delta -= pg_sum_deltas.front().second; - pg_sum_deltas.pop_front(); + if (!f && (ss_client_io.str().length() || ss_rec_io.str().length() + || ss_cache_io.str().length())) { + *out << "\n \n"; + *out << " io:\n"; } - update_pool_deltas(cct, inc.stamp, pg_pool_sum_old); - - if (inc.osdmap_epoch) - last_osdmap_epoch = inc.osdmap_epoch; - if (inc.pg_scan) - last_pg_scan = inc.pg_scan; - - min_last_epoch_clean = 0; // invalidate + if (!f && ss_client_io.str().length()) + *out << " client: " << ss_client_io.str() << "\n"; + if (!f && ss_rec_io.str().length()) + *out << " recovery: " << ss_rec_io.str() << "\n"; + if (!f && ss_cache_io.str().length()) + *out << " cache: " << ss_cache_io.str() << "\n"; } -void PGMap::redo_full_sets() +void PGMapDigest::print_oneline_summary(Formatter *f, ostream *out) const { - full_osds.clear(); - nearfull_osds.clear(); - for (ceph::unordered_map::iterator i = osd_stat.begin(); - i != osd_stat.end(); - ++i) { - register_nearfull_status(i->first, i->second); + std::stringstream ss; + + if (f) + f->open_array_section("num_pg_by_state"); + for (auto p = num_pg_by_state.begin(); + p != num_pg_by_state.end(); + ++p) { + if (f) { + f->open_object_section("state"); + f->dump_string("name", pg_state_string(p->first)); + f->dump_unsigned("num", p->second); + f->close_section(); + } + if (p != num_pg_by_state.begin()) + ss << ", "; + ss << p->second << " " << pg_state_string(p->first); } -} + if (f) + f->close_section(); -void PGMap::register_nearfull_status(int osd, const osd_stat_t& s) -{ - float ratio = ((float)s.kb_used) / ((float)s.kb); + string states = ss.str(); + if (out) + *out << num_pg << " pgs: " + << states << "; " + << prettybyte_t(pg_sum.stats.sum.num_bytes) << " data, " + << kb_t(osd_sum.kb_used) << " used, " + << kb_t(osd_sum.kb_avail) << " / " + << kb_t(osd_sum.kb) << " avail"; + if (f) { + f->dump_unsigned("num_pgs", num_pg); + f->dump_unsigned("num_bytes", pg_sum.stats.sum.num_bytes); + f->dump_unsigned("raw_bytes_used", osd_sum.kb_used << 10); + f->dump_unsigned("raw_bytes_avail", osd_sum.kb_avail << 10); + f->dump_unsigned("raw_bytes", osd_sum.kb << 10); + } - if (full_ratio > 0 && ratio > full_ratio) { - // full - full_osds.insert(osd); - nearfull_osds.erase(osd); - } else if (nearfull_ratio > 0 && ratio > nearfull_ratio) { - // nearfull - full_osds.erase(osd); - nearfull_osds.insert(osd); - } else { - // ok - full_osds.erase(osd); - nearfull_osds.erase(osd); + // make non-negative; we can get negative values if osds send + // uncommitted stats and then "go backward" or if they are just + // buggy/wrong. + pool_stat_t pos_delta = pg_sum_delta; + pos_delta.floor(0); + if (pos_delta.stats.sum.num_rd || + pos_delta.stats.sum.num_wr) { + if (out) + *out << "; "; + if (pos_delta.stats.sum.num_rd) { + int64_t rd = (pos_delta.stats.sum.num_rd_kb << 10) / (double)stamp_delta; + if (out) + *out << pretty_si_t(rd) << "B/s rd, "; + if (f) + f->dump_unsigned("read_bytes_sec", rd); + } + if (pos_delta.stats.sum.num_wr) { + int64_t wr = (pos_delta.stats.sum.num_wr_kb << 10) / (double)stamp_delta; + if (out) + *out << pretty_si_t(wr) << "B/s wr, "; + if (f) + f->dump_unsigned("write_bytes_sec", wr); + } + int64_t iops = (pos_delta.stats.sum.num_rd + pos_delta.stats.sum.num_wr) / (double)stamp_delta; + if (out) + *out << pretty_si_t(iops) << "op/s"; + if (f) + f->dump_unsigned("io_sec", iops); } + + list sl; + overall_recovery_summary(f, &sl); + if (out) + for (auto p = sl.begin(); p != sl.end(); ++p) + *out << "; " << *p; + std::stringstream ssr; + overall_recovery_rate_summary(f, &ssr); + if (out && ssr.str().length()) + *out << "; " << ssr.str() << " recovering"; } -void PGMap::calc_stats() +void PGMapDigest::recovery_summary(Formatter *f, list *psl, + const pool_stat_t& delta_sum) const { - num_pg_by_state.clear(); - num_pg = 0; - num_pg_active = 0; - num_osd = 0; - pg_pool_sum.clear(); - pg_sum = pool_stat_t(); - osd_sum = osd_stat_t(); - pg_by_osd.clear(); - num_primary_pg_by_osd.clear(); - - for (ceph::unordered_map::iterator p = pg_stat.begin(); - p != pg_stat.end(); - ++p) { - stat_pg_add(p->first, p->second); + if (delta_sum.stats.sum.num_objects_degraded && delta_sum.stats.sum.num_object_copies > 0) { + double pc = (double)delta_sum.stats.sum.num_objects_degraded / + (double)delta_sum.stats.sum.num_object_copies * (double)100.0; + char b[20]; + snprintf(b, sizeof(b), "%.3lf", pc); + if (f) { + f->dump_unsigned("degraded_objects", delta_sum.stats.sum.num_objects_degraded); + f->dump_unsigned("degraded_total", delta_sum.stats.sum.num_object_copies); + f->dump_float("degraded_ratio", pc / 100.0); + } else { + ostringstream ss; + ss << delta_sum.stats.sum.num_objects_degraded + << "/" << delta_sum.stats.sum.num_object_copies << " objects degraded (" << b << "%)"; + psl->push_back(ss.str()); + } + } + if (delta_sum.stats.sum.num_objects_misplaced && delta_sum.stats.sum.num_object_copies > 0) { + double pc = (double)delta_sum.stats.sum.num_objects_misplaced / + (double)delta_sum.stats.sum.num_object_copies * (double)100.0; + char b[20]; + snprintf(b, sizeof(b), "%.3lf", pc); + if (f) { + f->dump_unsigned("misplaced_objects", delta_sum.stats.sum.num_objects_misplaced); + f->dump_unsigned("misplaced_total", delta_sum.stats.sum.num_object_copies); + f->dump_float("misplaced_ratio", pc / 100.0); + } else { + ostringstream ss; + ss << delta_sum.stats.sum.num_objects_misplaced + << "/" << delta_sum.stats.sum.num_object_copies << " objects misplaced (" << b << "%)"; + psl->push_back(ss.str()); + } + } + if (delta_sum.stats.sum.num_objects_unfound && delta_sum.stats.sum.num_objects) { + double pc = (double)delta_sum.stats.sum.num_objects_unfound / + (double)delta_sum.stats.sum.num_objects * (double)100.0; + char b[20]; + snprintf(b, sizeof(b), "%.3lf", pc); + if (f) { + f->dump_unsigned("unfound_objects", delta_sum.stats.sum.num_objects_unfound); + f->dump_unsigned("unfound_total", delta_sum.stats.sum.num_objects); + f->dump_float("unfound_ratio", pc / 100.0); + } else { + ostringstream ss; + ss << delta_sum.stats.sum.num_objects_unfound + << "/" << delta_sum.stats.sum.num_objects << " unfound (" << b << "%)"; + psl->push_back(ss.str()); + } } - for (ceph::unordered_map::iterator p = osd_stat.begin(); - p != osd_stat.end(); - ++p) - stat_osd_add(p->second); - - redo_full_sets(); - - min_last_epoch_clean = calc_min_last_epoch_clean(); } -void PGMap::update_pg(pg_t pgid, bufferlist& bl) +void PGMapDigest::recovery_rate_summary(Formatter *f, ostream *out, + const pool_stat_t& delta_sum, + utime_t delta_stamp) const { - bufferlist::iterator p = bl.begin(); - ceph::unordered_map::iterator s = pg_stat.find(pgid); - epoch_t old_lec = 0, lec; - if (s != pg_stat.end()) { - old_lec = s->second.get_effective_last_epoch_clean(); - stat_pg_update(pgid, s->second, p); - lec = s->second.get_effective_last_epoch_clean(); - } else { - pg_stat_t& r = pg_stat[pgid]; - ::decode(r, p); - stat_pg_add(pgid, r); - lec = r.get_effective_last_epoch_clean(); + // make non-negative; we can get negative values if osds send + // uncommitted stats and then "go backward" or if they are just + // buggy/wrong. + pool_stat_t pos_delta = delta_sum; + pos_delta.floor(0); + if (pos_delta.stats.sum.num_objects_recovered || + pos_delta.stats.sum.num_bytes_recovered || + pos_delta.stats.sum.num_keys_recovered) { + int64_t objps = pos_delta.stats.sum.num_objects_recovered / (double)delta_stamp; + int64_t bps = pos_delta.stats.sum.num_bytes_recovered / (double)delta_stamp; + int64_t kps = pos_delta.stats.sum.num_keys_recovered / (double)delta_stamp; + if (f) { + f->dump_int("recovering_objects_per_sec", objps); + f->dump_int("recovering_bytes_per_sec", bps); + f->dump_int("recovering_keys_per_sec", kps); + f->dump_int("num_objects_recovered", pos_delta.stats.sum.num_objects_recovered); + f->dump_int("num_bytes_recovered", pos_delta.stats.sum.num_bytes_recovered); + f->dump_int("num_keys_recovered", pos_delta.stats.sum.num_keys_recovered); + } else { + *out << pretty_si_t(bps) << "B/s"; + if (pos_delta.stats.sum.num_keys_recovered) + *out << ", " << pretty_si_t(kps) << "keys/s"; + *out << ", " << pretty_si_t(objps) << "objects/s"; + } } +} - if (min_last_epoch_clean && - (lec < min_last_epoch_clean || // we did - (lec > min_last_epoch_clean && // we might - old_lec == min_last_epoch_clean) - )) - min_last_epoch_clean = 0; +void PGMapDigest::overall_recovery_rate_summary(Formatter *f, ostream *out) const +{ + recovery_rate_summary(f, out, pg_sum_delta, stamp_delta); } -void PGMap::remove_pg(pg_t pgid) +void PGMapDigest::overall_recovery_summary(Formatter *f, list *psl) const { - ceph::unordered_map::iterator s = pg_stat.find(pgid); - if (s != pg_stat.end()) { - if (min_last_epoch_clean && - s->second.get_effective_last_epoch_clean() == min_last_epoch_clean) - min_last_epoch_clean = 0; - stat_pg_sub(pgid, s->second); - pg_stat.erase(s); - } + recovery_summary(f, psl, pg_sum); } -void PGMap::update_osd(int osd, bufferlist& bl) +void PGMapDigest::pool_recovery_rate_summary(Formatter *f, ostream *out, + uint64_t poolid) const { - bufferlist::iterator p = bl.begin(); - ceph::unordered_map::iterator o = osd_stat.find(osd); - epoch_t old_lec = 0; - if (o != osd_stat.end()) { - ceph::unordered_map::iterator i = osd_epochs.find(osd); - if (i != osd_epochs.end()) - old_lec = i->second; - stat_osd_sub(o->second); - } - osd_stat_t& r = osd_stat[osd]; - ::decode(r, p); - stat_osd_add(r); + auto p = per_pool_sum_delta.find(poolid); + if (p == per_pool_sum_delta.end()) + return; - // adjust [near]full status - register_nearfull_status(osd, r); + auto ts = per_pool_sum_deltas_stamps.find(p->first); + assert(ts != per_pool_sum_deltas_stamps.end()); + recovery_rate_summary(f, out, p->second.first, ts->second); +} - // epoch? - if (!p.end()) { - epoch_t e; - ::decode(e, p); +void PGMapDigest::pool_recovery_summary(Formatter *f, list *psl, + uint64_t poolid) const +{ + auto p = per_pool_sum_delta.find(poolid); + if (p == per_pool_sum_delta.end()) + return; - if (e < min_last_epoch_clean || - (e > min_last_epoch_clean && - old_lec == min_last_epoch_clean)) - min_last_epoch_clean = 0; - } else { - // WARNING: we are not refreshing min_last_epoch_clean! must be old store - // or old mon running. - } + recovery_summary(f, psl, p->second.first); } -void PGMap::remove_osd(int osd) +void PGMapDigest::client_io_rate_summary(Formatter *f, ostream *out, + const pool_stat_t& delta_sum, + utime_t delta_stamp) const { - ceph::unordered_map::iterator o = osd_stat.find(osd); - if (o != osd_stat.end()) { - stat_osd_sub(o->second); - osd_stat.erase(o); - - // remove these old osds from full/nearfull set(s), too - nearfull_osds.erase(osd); - full_osds.erase(osd); + pool_stat_t pos_delta = delta_sum; + pos_delta.floor(0); + if (pos_delta.stats.sum.num_rd || + pos_delta.stats.sum.num_wr) { + if (pos_delta.stats.sum.num_rd) { + int64_t rd = (pos_delta.stats.sum.num_rd_kb << 10) / (double)delta_stamp; + if (f) { + f->dump_int("read_bytes_sec", rd); + } else { + *out << pretty_si_t(rd) << "B/s rd, "; + } + } + if (pos_delta.stats.sum.num_wr) { + int64_t wr = (pos_delta.stats.sum.num_wr_kb << 10) / (double)delta_stamp; + if (f) { + f->dump_int("write_bytes_sec", wr); + } else { + *out << pretty_si_t(wr) << "B/s wr, "; + } + } + int64_t iops_rd = pos_delta.stats.sum.num_rd / (double)delta_stamp; + int64_t iops_wr = pos_delta.stats.sum.num_wr / (double)delta_stamp; + if (f) { + f->dump_int("read_op_per_sec", iops_rd); + f->dump_int("write_op_per_sec", iops_wr); + } else { + *out << pretty_si_t(iops_rd) << "op/s rd, " << pretty_si_t(iops_wr) << "op/s wr"; + } } } -void PGMap::stat_pg_add(const pg_t &pgid, const pg_stat_t &s, - bool sameosds) +void PGMapDigest::overall_client_io_rate_summary(Formatter *f, ostream *out) const { - pg_pool_sum[pgid.pool()].add(s); - pg_sum.add(s); - - num_pg++; - num_pg_by_state[s.state]++; - - if ((s.state & PG_STATE_CREATING) && - s.parent_split_bits == 0) { - creating_pgs.insert(pgid); - if (s.acting_primary >= 0) { - creating_pgs_by_osd_epoch[s.acting_primary][s.mapping_epoch].insert(pgid); - } - } - - if (s.state & PG_STATE_ACTIVE) { - ++num_pg_active; - } + client_io_rate_summary(f, out, pg_sum_delta, stamp_delta); +} - if (sameosds) +void PGMapDigest::pool_client_io_rate_summary(Formatter *f, ostream *out, + uint64_t poolid) const +{ + auto p = per_pool_sum_delta.find(poolid); + if (p == per_pool_sum_delta.end()) return; - for (vector::const_iterator p = s.blocked_by.begin(); - p != s.blocked_by.end(); - ++p) { - ++blocked_by_sum[*p]; - } - - for (vector::const_iterator p = s.acting.begin(); p != s.acting.end(); ++p) - pg_by_osd[*p].insert(pgid); - for (vector::const_iterator p = s.up.begin(); p != s.up.end(); ++p) - pg_by_osd[*p].insert(pgid); - - if (s.up_primary >= 0) - num_primary_pg_by_osd[s.up_primary]++; + auto ts = per_pool_sum_deltas_stamps.find(p->first); + assert(ts != per_pool_sum_deltas_stamps.end()); + client_io_rate_summary(f, out, p->second.first, ts->second); } -void PGMap::stat_pg_sub(const pg_t &pgid, const pg_stat_t &s, - bool sameosds) +void PGMapDigest::cache_io_rate_summary(Formatter *f, ostream *out, + const pool_stat_t& delta_sum, + utime_t delta_stamp) const { - pool_stat_t& ps = pg_pool_sum[pgid.pool()]; - ps.sub(s); - if (ps.is_zero()) - pg_pool_sum.erase(pgid.pool()); - pg_sum.sub(s); - - num_pg--; - int end = --num_pg_by_state[s.state]; - assert(end >= 0); - if (end == 0) - num_pg_by_state.erase(s.state); + pool_stat_t pos_delta = delta_sum; + pos_delta.floor(0); + bool have_output = false; - if ((s.state & PG_STATE_CREATING) && - s.parent_split_bits == 0) { - creating_pgs.erase(pgid); - if (s.acting_primary >= 0) { - map >& r = creating_pgs_by_osd_epoch[s.acting_primary]; - r[s.mapping_epoch].erase(pgid); - if (r[s.mapping_epoch].empty()) - r.erase(s.mapping_epoch); - if (r.empty()) - creating_pgs_by_osd_epoch.erase(s.acting_primary); + if (pos_delta.stats.sum.num_flush) { + int64_t flush = (pos_delta.stats.sum.num_flush_kb << 10) / (double)delta_stamp; + if (f) { + f->dump_int("flush_bytes_sec", flush); + } else { + *out << pretty_si_t(flush) << "B/s flush"; + have_output = true; } } - - if (s.state & PG_STATE_ACTIVE) { - --num_pg_active; + if (pos_delta.stats.sum.num_evict) { + int64_t evict = (pos_delta.stats.sum.num_evict_kb << 10) / (double)delta_stamp; + if (f) { + f->dump_int("evict_bytes_sec", evict); + } else { + if (have_output) + *out << ", "; + *out << pretty_si_t(evict) << "B/s evict"; + have_output = true; + } } - - if (sameosds) - return; - - for (vector::const_iterator p = s.blocked_by.begin(); - p != s.blocked_by.end(); - ++p) { - ceph::unordered_map::iterator q = blocked_by_sum.find(*p); - assert(q != blocked_by_sum.end()); - --q->second; - if (q->second == 0) - blocked_by_sum.erase(q); + if (pos_delta.stats.sum.num_promote) { + int64_t promote = pos_delta.stats.sum.num_promote / (double)delta_stamp; + if (f) { + f->dump_int("promote_op_per_sec", promote); + } else { + if (have_output) + *out << ", "; + *out << pretty_si_t(promote) << "op/s promote"; + have_output = true; + } } - - for (vector::const_iterator p = s.acting.begin(); p != s.acting.end(); ++p) { - set& oset = pg_by_osd[*p]; - oset.erase(pgid); - if (oset.empty()) - pg_by_osd.erase(*p); + if (pos_delta.stats.sum.num_flush_mode_low) { + if (f) { + f->dump_int("num_flush_mode_low", pos_delta.stats.sum.num_flush_mode_low); + } else { + if (have_output) + *out << ", "; + *out << pretty_si_t(pos_delta.stats.sum.num_flush_mode_low) << "PG(s) flushing"; + have_output = true; + } } - for (vector::const_iterator p = s.up.begin(); p != s.up.end(); ++p) { - set& oset = pg_by_osd[*p]; - oset.erase(pgid); - if (oset.empty()) - pg_by_osd.erase(*p); + if (pos_delta.stats.sum.num_flush_mode_high) { + if (f) { + f->dump_int("num_flush_mode_high", pos_delta.stats.sum.num_flush_mode_high); + } else { + if (have_output) + *out << ", "; + *out << pretty_si_t(pos_delta.stats.sum.num_flush_mode_high) << "PG(s) flushing (high)"; + have_output = true; + } } - - if (s.up_primary >= 0) { - auto it = num_primary_pg_by_osd.find(s.up_primary); - if (it != num_primary_pg_by_osd.end() && it->second > 0) - it->second--; + if (pos_delta.stats.sum.num_evict_mode_some) { + if (f) { + f->dump_int("num_evict_mode_some", pos_delta.stats.sum.num_evict_mode_some); + } else { + if (have_output) + *out << ", "; + *out << pretty_si_t(pos_delta.stats.sum.num_evict_mode_some) << "PG(s) evicting"; + have_output = true; + } + } + if (pos_delta.stats.sum.num_evict_mode_full) { + if (f) { + f->dump_int("num_evict_mode_full", pos_delta.stats.sum.num_evict_mode_full); + } else { + if (have_output) + *out << ", "; + *out << pretty_si_t(pos_delta.stats.sum.num_evict_mode_full) << "PG(s) evicting (full)"; + } } } -void PGMap::stat_pg_update(const pg_t pgid, pg_stat_t& s, - bufferlist::iterator& blp) +void PGMapDigest::overall_cache_io_rate_summary(Formatter *f, ostream *out) const { - pg_stat_t n; - ::decode(n, blp); - - bool sameosds = - s.acting == n.acting && - s.up == n.up && - s.blocked_by == n.blocked_by; - - stat_pg_sub(pgid, s, sameosds); - - // if acting_primary has shift to an just restored osd, and pg yet to finish - // peering, many attributes in current stats remain stale. others seem don't - // mater much while faulty last_active will make "pg stuck in" check unhappy. - if (!(n.state & (PG_STATE_ACTIVE | PG_STATE_PEERED)) && - n.last_active < s.last_active) - n.last_active = s.last_active; - s = n; - stat_pg_add(pgid, n, sameosds); + cache_io_rate_summary(f, out, pg_sum_delta, stamp_delta); } -void PGMap::stat_osd_add(const osd_stat_t &s) +void PGMapDigest::pool_cache_io_rate_summary(Formatter *f, ostream *out, + uint64_t poolid) const { - num_osd++; - osd_sum.add(s); -} + auto p = per_pool_sum_delta.find(poolid); + if (p == per_pool_sum_delta.end()) + return; -void PGMap::stat_osd_sub(const osd_stat_t &s) -{ - num_osd--; - osd_sum.sub(s); + auto ts = per_pool_sum_deltas_stamps.find(p->first); + assert(ts != per_pool_sum_deltas_stamps.end()); + cache_io_rate_summary(f, out, p->second.first, ts->second); } -epoch_t PGMap::calc_min_last_epoch_clean() const +void PGMapDigest::dump_pool_stats_full( + const OSDMap &osd_map, + stringstream *ss, + Formatter *f, + bool verbose) const { - if (pg_stat.empty()) - return 0; + TextTable tbl; - ceph::unordered_map::const_iterator p = pg_stat.begin(); - epoch_t min = p->second.get_effective_last_epoch_clean(); - for (++p; p != pg_stat.end(); ++p) { - epoch_t lec = p->second.get_effective_last_epoch_clean(); - if (lec < min) - min = lec; - } - // also scan osd epochs - // don't trim past the oldest reported osd epoch - for (ceph::unordered_map::const_iterator i = osd_epochs.begin(); - i != osd_epochs.end(); - ++i) { - if (i->second < min) - min = i->second; - } - return min; -} + if (f) { + f->open_array_section("pools"); + } else { + tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT); + tbl.define_column("ID", TextTable::LEFT, TextTable::LEFT); + if (verbose) { + tbl.define_column("QUOTA OBJECTS", TextTable::LEFT, TextTable::LEFT); + tbl.define_column("QUOTA BYTES", TextTable::LEFT, TextTable::LEFT); + } -void PGMap::encode(bufferlist &bl, uint64_t features) const -{ - if ((features & CEPH_FEATURE_MONENC) == 0) { - __u8 v = 3; + tbl.define_column("USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("%USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("MAX AVAIL", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + if (verbose) { + tbl.define_column("DIRTY", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("READ", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("WRITE", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); + } + } + + map avail_by_rule; + for (auto p = osd_map.get_pools().begin(); + p != osd_map.get_pools().end(); ++p) { + int64_t pool_id = p->first; + if ((pool_id < 0) || (pg_pool_sum.count(pool_id) == 0)) + continue; + const string& pool_name = osd_map.get_pool_name(pool_id); + const pool_stat_t &stat = pg_pool_sum.at(pool_id); + + const pg_pool_t *pool = osd_map.get_pg_pool(pool_id); + int ruleno = osd_map.crush->find_rule(pool->get_crush_rule(), + pool->get_type(), + pool->get_size()); + int64_t avail; + float raw_used_rate; + if (avail_by_rule.count(ruleno) == 0) { + // FIXME: we don't guarantee avail_space_by_rule is up-to-date before this function is invoked + avail = get_rule_avail(ruleno); + if (avail < 0) + avail = 0; + avail_by_rule[ruleno] = avail; + } else { + avail = avail_by_rule[ruleno]; + } + switch (pool->get_type()) { + case pg_pool_t::TYPE_REPLICATED: + avail /= pool->get_size(); + raw_used_rate = pool->get_size(); + break; + case pg_pool_t::TYPE_ERASURE: + { + auto& ecp = + osd_map.get_erasure_code_profile(pool->erasure_code_profile); + auto pm = ecp.find("m"); + auto pk = ecp.find("k"); + if (pm != ecp.end() && pk != ecp.end()) { + int k = atoi(pk->second.c_str()); + int m = atoi(pm->second.c_str()); + int mk = m + k; + assert(mk != 0); + avail = avail * k / mk; + raw_used_rate = (float)mk / k; + } else { + raw_used_rate = 0.0; + } + } + break; + default: + assert(0 == "unrecognized pool type"); + } + + if (f) { + f->open_object_section("pool"); + f->dump_string("name", pool_name); + f->dump_int("id", pool_id); + f->open_object_section("stats"); + } else { + tbl << pool_name + << pool_id; + if (verbose) { + if (pool->quota_max_objects == 0) + tbl << "N/A"; + else + tbl << si_t(pool->quota_max_objects); + + if (pool->quota_max_bytes == 0) + tbl << "N/A"; + else + tbl << si_t(pool->quota_max_bytes); + } + + } + dump_object_stat_sum(tbl, f, stat.stats.sum, avail, raw_used_rate, verbose, pool); + if (f) + f->close_section(); // stats + else + tbl << TextTable::endrow; + + if (f) + f->close_section(); // pool + } + if (f) + f->close_section(); + else { + assert(ss != nullptr); + *ss << "POOLS:\n"; + tbl.set_indent(4); + *ss << tbl; + } +} + +void PGMapDigest::dump_fs_stats(stringstream *ss, Formatter *f, bool verbose) const +{ + if (f) { + f->open_object_section("stats"); + f->dump_int("total_bytes", osd_sum.kb * 1024ull); + f->dump_int("total_used_bytes", osd_sum.kb_used * 1024ull); + f->dump_int("total_avail_bytes", osd_sum.kb_avail * 1024ull); + if (verbose) { + f->dump_int("total_objects", pg_sum.stats.sum.num_objects); + } + f->close_section(); + } else { + assert(ss != nullptr); + TextTable tbl; + tbl.define_column("SIZE", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("%RAW USED", TextTable::LEFT, TextTable::RIGHT); + if (verbose) { + tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + } + tbl << stringify(si_t(osd_sum.kb*1024)) + << stringify(si_t(osd_sum.kb_avail*1024)) + << stringify(si_t(osd_sum.kb_used*1024)); + float used = 0.0; + if (osd_sum.kb > 0) { + used = ((float)osd_sum.kb_used / osd_sum.kb); + } + tbl << percentify(used*100); + if (verbose) { + tbl << stringify(si_t(pg_sum.stats.sum.num_objects)); + } + tbl << TextTable::endrow; + + *ss << "GLOBAL:\n"; + tbl.set_indent(4); + *ss << tbl; + } +} + +void PGMapDigest::dump_object_stat_sum( + TextTable &tbl, Formatter *f, + const object_stat_sum_t &sum, uint64_t avail, + float raw_used_rate, bool verbose, + const pg_pool_t *pool) +{ + float curr_object_copies_rate = 0.0; + if (sum.num_object_copies > 0) + curr_object_copies_rate = (float)(sum.num_object_copies - sum.num_objects_degraded) / sum.num_object_copies; + + float used = 0.0; + if (avail) { + used = sum.num_bytes * curr_object_copies_rate; + used /= used + avail; + } else if (sum.num_bytes) { + used = 1.0; + } + + if (f) { + f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10)); + f->dump_int("bytes_used", sum.num_bytes); + f->dump_format_unquoted("percent_used", "%.2f", (used*100)); + f->dump_unsigned("max_avail", avail); + f->dump_int("objects", sum.num_objects); + if (verbose) { + f->dump_int("quota_objects", pool->quota_max_objects); + f->dump_int("quota_bytes", pool->quota_max_bytes); + f->dump_int("dirty", sum.num_objects_dirty); + f->dump_int("rd", sum.num_rd); + f->dump_int("rd_bytes", sum.num_rd_kb * 1024ull); + f->dump_int("wr", sum.num_wr); + f->dump_int("wr_bytes", sum.num_wr_kb * 1024ull); + f->dump_int("raw_bytes_used", sum.num_bytes * raw_used_rate * curr_object_copies_rate); + } + } else { + tbl << stringify(si_t(sum.num_bytes)); + tbl << percentify(used*100); + tbl << si_t(avail); + tbl << sum.num_objects; + if (verbose) { + tbl << stringify(si_t(sum.num_objects_dirty)) + << stringify(si_t(sum.num_rd)) + << stringify(si_t(sum.num_wr)) + << stringify(si_t(sum.num_bytes * raw_used_rate * curr_object_copies_rate)); + } + } +} + +int64_t PGMap::get_rule_avail(const OSDMap& osdmap, int ruleno) const +{ + map wm; + int r = osdmap.crush->get_rule_weight_osd_map(ruleno, &wm); + if (r < 0) { + return r; + } + if (wm.empty()) { + return 0; + } + + float fratio; + if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS && + osdmap.get_full_ratio() > 0) { + fratio = osdmap.get_full_ratio(); + } else { + fratio = get_fallback_full_ratio(); + } + + int64_t min = -1; + for (auto p = wm.begin(); p != wm.end(); ++p) { + auto osd_info = osd_stat.find(p->first); + if (osd_info != osd_stat.end()) { + if (osd_info->second.kb == 0 || p->second == 0) { + // osd must be out, hence its stats have been zeroed + // (unless we somehow managed to have a disk with size 0...) + // + // (p->second == 0), if osd weight is 0, no need to + // calculate proj below. + continue; + } + double unusable = (double)osd_info->second.kb * + (1.0 - fratio); + double avail = MAX(0.0, (double)osd_info->second.kb_avail - unusable); + avail *= 1024.0; + int64_t proj = (int64_t)(avail / (double)p->second); + if (min < 0 || proj < min) { + min = proj; + } + } else { + dout(0) << "Cannot get stat of OSD " << p->first << dendl; + } + } + return min; +} + +void PGMap::get_rules_avail(const OSDMap& osdmap, + std::map *avail_map) const +{ + avail_map->clear(); + for (auto p : osdmap.get_pools()) { + int64_t pool_id = p.first; + if ((pool_id < 0) || (pg_pool_sum.count(pool_id) == 0)) + continue; + const pg_pool_t *pool = osdmap.get_pg_pool(pool_id); + int ruleno = osdmap.crush->find_rule(pool->get_crush_rule(), + pool->get_type(), + pool->get_size()); + if (avail_map->count(ruleno) == 0) + (*avail_map)[ruleno] = get_rule_avail(osdmap, ruleno); + } +} + +// --------------------- +// PGMap + +void PGMap::Incremental::encode(bufferlist &bl, uint64_t features) const +{ + if ((features & CEPH_FEATURE_MONENC) == 0) { + __u8 v = 4; ::encode(v, bl); ::encode(version, bl); - ::encode(pg_stat, bl); - ::encode(osd_stat, bl); - ::encode(last_osdmap_epoch, bl); - ::encode(last_pg_scan, bl); + ::encode(pg_stat_updates, bl); + ::encode(osd_stat_updates, bl); + ::encode(osd_stat_rm, bl); + ::encode(osdmap_epoch, bl); + ::encode(pg_scan, bl); ::encode(full_ratio, bl); ::encode(nearfull_ratio, bl); + ::encode(pg_remove, bl); return; } - ENCODE_START(6, 4, bl); + ENCODE_START(7, 5, bl); ::encode(version, bl); - ::encode(pg_stat, bl); - ::encode(osd_stat, bl); - ::encode(last_osdmap_epoch, bl); - ::encode(last_pg_scan, bl); + ::encode(pg_stat_updates, bl); + ::encode(osd_stat_updates, bl); + ::encode(osd_stat_rm, bl); + ::encode(osdmap_epoch, bl); + ::encode(pg_scan, bl); ::encode(full_ratio, bl); ::encode(nearfull_ratio, bl); + ::encode(pg_remove, bl); ::encode(stamp, bl); ::encode(osd_epochs, bl); ENCODE_FINISH(bl); } -void PGMap::decode(bufferlist::iterator &bl) +void PGMap::Incremental::decode(bufferlist::iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(6, 4, 4, bl); + DECODE_START_LEGACY_COMPAT_LEN(7, 5, 5, bl); ::decode(version, bl); if (struct_v < 3) { - pg_stat.clear(); + pg_stat_updates.clear(); __u32 n; ::decode(n, bl); while (n--) { old_pg_t opgid; ::decode(opgid, bl); pg_t pgid = opgid; - ::decode(pg_stat[pgid], bl); + ::decode(pg_stat_updates[pgid], bl); } } else { - ::decode(pg_stat, bl); + ::decode(pg_stat_updates, bl); } - ::decode(osd_stat, bl); - ::decode(last_osdmap_epoch, bl); - ::decode(last_pg_scan, bl); + ::decode(osd_stat_updates, bl); + ::decode(osd_stat_rm, bl); + ::decode(osdmap_epoch, bl); + ::decode(pg_scan, bl); if (struct_v >= 2) { ::decode(full_ratio, bl); ::decode(nearfull_ratio, bl); } - if (struct_v >= 5) + if (struct_v < 3) { + pg_remove.clear(); + __u32 n; + ::decode(n, bl); + while (n--) { + old_pg_t opgid; + ::decode(opgid, bl); + pg_remove.insert(pg_t(opgid)); + } + } else { + ::decode(pg_remove, bl); + } + if (struct_v < 4 && full_ratio == 0) { + full_ratio = -1; + } + if (struct_v < 4 && nearfull_ratio == 0) { + nearfull_ratio = -1; + } + if (struct_v >= 6) ::decode(stamp, bl); - if (struct_v >= 6) { + if (struct_v >= 7) { ::decode(osd_epochs, bl); } else { - for (ceph::unordered_map::iterator i = osd_stat.begin(); - i != osd_stat.end(); + for (auto i = osd_stat_updates.begin(); + i != osd_stat_updates.end(); ++i) { // This isn't accurate, but will cause trimming to behave like // previously. - osd_epochs.insert(make_pair(i->first, last_osdmap_epoch)); + osd_epochs.insert(make_pair(i->first, osdmap_epoch)); } } DECODE_FINISH(bl); - - calc_stats(); -} - -void PGMap::dirty_all(Incremental& inc) -{ - inc.osdmap_epoch = last_osdmap_epoch; - inc.pg_scan = last_pg_scan; - inc.full_ratio = full_ratio; - inc.nearfull_ratio = nearfull_ratio; - - for (ceph::unordered_map::const_iterator p = pg_stat.begin(); p != pg_stat.end(); ++p) { - inc.pg_stat_updates[p->first] = p->second; - } - for (ceph::unordered_map::const_iterator p = osd_stat.begin(); p != osd_stat.end(); ++p) { - assert(osd_epochs.count(p->first)); - inc.update_stat(p->first, - inc.get_osd_epochs().find(p->first)->second, - p->second); - } -} - -void PGMap::dump(Formatter *f) const -{ - dump_basic(f); - dump_pg_stats(f, false); - dump_pool_stats(f); - dump_osd_stats(f); } -void PGMap::dump_basic(Formatter *f) const +void PGMap::Incremental::dump(Formatter *f) const { f->dump_unsigned("version", version); f->dump_stream("stamp") << stamp; - f->dump_unsigned("last_osdmap_epoch", last_osdmap_epoch); - f->dump_unsigned("last_pg_scan", last_pg_scan); - f->dump_unsigned("min_last_epoch_clean", min_last_epoch_clean); + f->dump_unsigned("osdmap_epoch", osdmap_epoch); + f->dump_unsigned("pg_scan_epoch", pg_scan); f->dump_float("full_ratio", full_ratio); - f->dump_float("near_full_ratio", nearfull_ratio); - - f->open_object_section("pg_stats_sum"); - pg_sum.dump(f); - f->close_section(); + f->dump_float("nearfull_ratio", nearfull_ratio); - f->open_object_section("osd_stats_sum"); - osd_sum.dump(f); + f->open_array_section("pg_stat_updates"); + for (auto p = pg_stat_updates.begin(); p != pg_stat_updates.end(); ++p) { + f->open_object_section("pg_stat"); + f->dump_stream("pgid") << p->first; + p->second.dump(f); + f->close_section(); + } f->close_section(); - f->open_array_section("osd_epochs"); - for (ceph::unordered_map::const_iterator p = - osd_epochs.begin(); p != osd_epochs.end(); ++p) { - f->open_object_section("osd"); - f->dump_unsigned("osd", p->first); - f->dump_unsigned("epoch", p->second); + f->open_array_section("osd_stat_updates"); + for (auto p = osd_stat_updates.begin(); p != osd_stat_updates.end(); ++p) { + f->open_object_section("osd_stat"); + f->dump_int("osd", p->first); + p->second.dump(f); f->close_section(); } f->close_section(); - dump_delta(f); -} - -void PGMap::dump_delta(Formatter *f) const -{ - f->open_object_section("pg_stats_delta"); - pg_sum_delta.dump(f); + f->open_array_section("osd_stat_removals"); + for (auto p = osd_stat_rm.begin(); p != osd_stat_rm.end(); ++p) + f->dump_int("osd", *p); f->close_section(); -} -void PGMap::dump_pg_stats(Formatter *f, bool brief) const -{ - f->open_array_section("pg_stats"); - for (ceph::unordered_map::const_iterator i = pg_stat.begin(); - i != pg_stat.end(); - ++i) { - f->open_object_section("pg_stat"); - f->dump_stream("pgid") << i->first; - if (brief) - i->second.dump_brief(f); - else - i->second.dump(f); - f->close_section(); - } + f->open_array_section("pg_removals"); + for (auto p = pg_remove.begin(); p != pg_remove.end(); ++p) + f->dump_stream("pgid") << *p; f->close_section(); } -void PGMap::dump_pool_stats(Formatter *f) const +void PGMap::Incremental::generate_test_instances(list& o) { - f->open_array_section("pool_stats"); - for (ceph::unordered_map::const_iterator p = pg_pool_sum.begin(); - p != pg_pool_sum.end(); - ++p) { - f->open_object_section("pool_stat"); - f->dump_int("poolid", p->first); - p->second.dump(f); - f->close_section(); - } - f->close_section(); + o.push_back(new Incremental); + o.push_back(new Incremental); + o.back()->version = 1; + o.back()->stamp = utime_t(123,345); + o.push_back(new Incremental); + o.back()->version = 2; + o.back()->pg_stat_updates[pg_t(1,2,3)] = pg_stat_t(); + o.back()->osd_stat_updates[5] = osd_stat_t(); + o.back()->osd_epochs[5] = 12; + o.push_back(new Incremental); + o.back()->version = 3; + o.back()->osdmap_epoch = 1; + o.back()->pg_scan = 2; + o.back()->full_ratio = .2; + o.back()->nearfull_ratio = .3; + o.back()->pg_stat_updates[pg_t(4,5,6)] = pg_stat_t(); + o.back()->osd_stat_updates[6] = osd_stat_t(); + o.back()->osd_epochs[6] = 12; + o.back()->pg_remove.insert(pg_t(1,2,3)); + o.back()->osd_stat_rm.insert(5); } -void PGMap::dump_osd_stats(Formatter *f) const -{ - f->open_array_section("osd_stats"); - for (ceph::unordered_map::const_iterator q = osd_stat.begin(); - q != osd_stat.end(); - ++q) { - f->open_object_section("osd_stat"); - f->dump_int("osd", q->first); - q->second.dump(f); - f->close_section(); - } - f->close_section(); -} -void PGMap::dump_pg_stats_plain(ostream& ss, - const ceph::unordered_map& pg_stats, - bool brief) const +// -- + +void PGMap::apply_incremental(CephContext *cct, const Incremental& inc) { - TextTable tab; + assert(inc.version == version+1); + version++; - if (brief){ - tab.define_column("PG_STAT", TextTable::LEFT, TextTable::LEFT); - tab.define_column("STATE", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UP", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UP_PRIMARY", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("ACTING", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("ACTING_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + utime_t delta_t; + delta_t = inc.stamp; + delta_t -= stamp; + stamp = inc.stamp; + + pool_stat_t pg_sum_old = pg_sum; + mempool::pgmap::unordered_map pg_pool_sum_old; + + bool ratios_changed = false; + if (inc.full_ratio != full_ratio && inc.full_ratio != -1) { + full_ratio = inc.full_ratio; + ratios_changed = true; } - else { - tab.define_column("PG_STAT", TextTable::LEFT, TextTable::LEFT); - tab.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("MISSING_ON_PRIMARY", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DEGRADED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("MISPLACED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UNFOUND", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("BYTES", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("LOG", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DISK_LOG", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("STATE", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("STATE_STAMP", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("VERSION", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("REPORTED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UP", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UP_PRIMARY", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("ACTING", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("ACTING_PRIMARY", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("LAST_SCRUB", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("SCRUB_STAMP", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("LAST_DEEP_SCRUB", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DEEP_SCRUB_STAMP", TextTable::LEFT, TextTable::RIGHT); + if (inc.nearfull_ratio != nearfull_ratio && inc.nearfull_ratio != -1) { + nearfull_ratio = inc.nearfull_ratio; + ratios_changed = true; } + if (ratios_changed) + redo_full_sets(); - for (ceph::unordered_map::const_iterator i = pg_stats.begin(); - i != pg_stats.end(); ++i) { - const pg_stat_t &st(i->second); - if (brief) { - tab << i->first - << pg_state_string(st.state) - << st.up - << st.up_primary - << st.acting - << st.acting_primary - << TextTable::endrow; - } else { - ostringstream reported; - reported << st.reported_epoch << ":" << st.reported_seq; + for (auto p = inc.pg_stat_updates.begin(); + p != inc.pg_stat_updates.end(); + ++p) { + const pg_t &update_pg(p->first); + const pg_stat_t &update_stat(p->second); - tab << i->first - << st.stats.sum.num_objects - << st.stats.sum.num_objects_missing_on_primary - << st.stats.sum.num_objects_degraded - << st.stats.sum.num_objects_misplaced - << st.stats.sum.num_objects_unfound - << st.stats.sum.num_bytes - << st.log_size - << st.ondisk_log_size - << pg_state_string(st.state) - << st.last_change - << st.version - << reported.str() - << pg_vector_string(st.up) - << st.up_primary - << pg_vector_string(st.acting) - << st.acting_primary - << st.last_scrub - << st.last_scrub_stamp - << st.last_deep_scrub - << st.last_deep_scrub_stamp - << TextTable::endrow; + if (pg_pool_sum_old.count(update_pg.pool()) == 0) + pg_pool_sum_old[update_pg.pool()] = pg_pool_sum[update_pg.pool()]; + + auto t = pg_stat.find(update_pg); + if (t == pg_stat.end()) { + pg_stat.insert(make_pair(update_pg, update_stat)); + } else { + stat_pg_sub(update_pg, t->second); + t->second = update_stat; } + stat_pg_add(update_pg, update_stat); } + assert(osd_stat.size() == osd_epochs.size()); + for (auto p = inc.get_osd_stat_updates().begin(); + p != inc.get_osd_stat_updates().end(); + ++p) { + int osd = p->first; + const osd_stat_t &new_stats(p->second); - ss << tab; -} - -void PGMap::dump(ostream& ss) const -{ - dump_basic(ss); - dump_pg_stats(ss, false); - dump_pool_stats(ss, false); - dump_pg_sum_stats(ss, false); - dump_osd_stats(ss); -} - -void PGMap::dump_basic(ostream& ss) const -{ - ss << "version " << version << std::endl; - ss << "stamp " << stamp << std::endl; - ss << "last_osdmap_epoch " << last_osdmap_epoch << std::endl; - ss << "last_pg_scan " << last_pg_scan << std::endl; - ss << "full_ratio " << full_ratio << std::endl; - ss << "nearfull_ratio " << nearfull_ratio << std::endl; -} + auto t = osd_stat.find(osd); + if (t == osd_stat.end()) { + osd_stat.insert(make_pair(osd, new_stats)); + } else { + stat_osd_sub(t->first, t->second); + t->second = new_stats; + } + auto i = osd_epochs.find(osd); + auto j = inc.get_osd_epochs().find(osd); + assert(j != inc.get_osd_epochs().end()); -void PGMap::dump_pg_stats(ostream& ss, bool brief) const -{ - dump_pg_stats_plain(ss, pg_stat, brief); -} + if (i == osd_epochs.end()) + osd_epochs.insert(*j); + else + i->second = j->second; -void PGMap::dump_pool_stats(ostream& ss, bool header) const -{ - TextTable tab; + stat_osd_add(osd, new_stats); - if (header) { - tab.define_column("POOLID", TextTable::LEFT, TextTable::LEFT); - tab.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("MISSING_ON_PRIMARY", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DEGRADED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("MISPLACED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UNFOUND", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("BYTES", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("LOG", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DISK_LOG", TextTable::LEFT, TextTable::RIGHT); - } else { - tab.define_column("", TextTable::LEFT, TextTable::LEFT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + // adjust [near]full status + register_nearfull_status(osd, new_stats); + } + set deleted_pools; + for (auto p = inc.pg_remove.begin(); + p != inc.pg_remove.end(); + ++p) { + const pg_t &removed_pg(*p); + auto s = pg_stat.find(removed_pg); + if (s != pg_stat.end()) { + stat_pg_sub(removed_pg, s->second); + pg_stat.erase(s); + } + deleted_pools.insert(removed_pg.pool()); } - for (ceph::unordered_map::const_iterator p = pg_pool_sum.begin(); - p != pg_pool_sum.end(); + for (auto p = inc.get_osd_stat_rm().begin(); + p != inc.get_osd_stat_rm().end(); ++p) { - tab << p->first - << p->second.stats.sum.num_objects - << p->second.stats.sum.num_objects_missing_on_primary - << p->second.stats.sum.num_objects_degraded - << p->second.stats.sum.num_objects_misplaced - << p->second.stats.sum.num_objects_unfound - << p->second.stats.sum.num_bytes - << p->second.log_size - << p->second.ondisk_log_size - << TextTable::endrow; + auto t = osd_stat.find(*p); + if (t != osd_stat.end()) { + stat_osd_sub(t->first, t->second); + osd_stat.erase(t); + osd_epochs.erase(*p); + } + + // remove these old osds from full/nearfull set(s), too + nearfull_osds.erase(*p); + full_osds.erase(*p); } - ss << tab; -} + // calculate a delta, and average over the last 2 deltas. + pool_stat_t d = pg_sum; + d.stats.sub(pg_sum_old.stats); + pg_sum_deltas.push_back(make_pair(d, delta_t)); + stamp_delta += delta_t; -void PGMap::dump_pg_sum_stats(ostream& ss, bool header) const -{ - TextTable tab; + pg_sum_delta.stats.add(d.stats); + if (pg_sum_deltas.size() > (unsigned)MAX(1, cct ? cct->_conf->mon_stat_smooth_intervals : 1)) { + pg_sum_delta.stats.sub(pg_sum_deltas.front().first.stats); + stamp_delta -= pg_sum_deltas.front().second; + pg_sum_deltas.pop_front(); + } - if (header) { - tab.define_column("PG_STAT", TextTable::LEFT, TextTable::LEFT); - tab.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("MISSING_ON_PRIMARY", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DEGRADED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("MISPLACED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("UNFOUND", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("BYTES", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("LOG", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("DISK_LOG", TextTable::LEFT, TextTable::RIGHT); - } else { - tab.define_column("", TextTable::LEFT, TextTable::LEFT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("", TextTable::LEFT, TextTable::RIGHT); - }; + update_pool_deltas(cct, inc.stamp, pg_pool_sum_old); - tab << "sum" - << pg_sum.stats.sum.num_objects - << pg_sum.stats.sum.num_objects_missing_on_primary - << pg_sum.stats.sum.num_objects_degraded - << pg_sum.stats.sum.num_objects_misplaced - << pg_sum.stats.sum.num_objects_unfound - << pg_sum.stats.sum.num_bytes - << pg_sum.log_size - << pg_sum.ondisk_log_size - << TextTable::endrow; + for (auto p : deleted_pools) { + if (cct) + dout(20) << " deleted pool " << p << dendl; + deleted_pool(p); + } - ss << tab; + if (inc.osdmap_epoch) + last_osdmap_epoch = inc.osdmap_epoch; + if (inc.pg_scan) + last_pg_scan = inc.pg_scan; + + min_last_epoch_clean = 0; // invalidate } -void PGMap::dump_osd_stats(ostream& ss) const +void PGMap::redo_full_sets() { - TextTable tab; - - tab.define_column("OSD_STAT", TextTable::LEFT, TextTable::LEFT); - tab.define_column("USED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("TOTAL", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("HB_PEERS", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("PG_SUM", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("PRIMARY_PG_SUM", TextTable::LEFT, TextTable::RIGHT); - - for (ceph::unordered_map::const_iterator p = osd_stat.begin(); - p != osd_stat.end(); - ++p) { - tab << p->first - << si_t(p->second.kb_used << 10) - << si_t(p->second.kb_avail << 10) - << si_t(p->second.kb << 10) - << p->second.hb_peers - << get_num_pg_by_osd(p->first) - << get_num_primary_pg_by_osd(p->first) - << TextTable::endrow; + full_osds.clear(); + nearfull_osds.clear(); + for (auto i = osd_stat.begin(); + i != osd_stat.end(); + ++i) { + register_nearfull_status(i->first, i->second); } +} - tab << "sum" - << si_t(osd_sum.kb_used << 10) - << si_t(osd_sum.kb_avail << 10) - << si_t(osd_sum.kb << 10) - << TextTable::endrow; +void PGMap::register_nearfull_status(int osd, const osd_stat_t& s) +{ + float ratio = ((float)s.kb_used) / ((float)s.kb); - ss << tab; + if (full_ratio > 0 && ratio > full_ratio) { + // full + full_osds.insert(osd); + nearfull_osds.erase(osd); + } else if (nearfull_ratio > 0 && ratio > nearfull_ratio) { + // nearfull + full_osds.erase(osd); + nearfull_osds.insert(osd); + } else { + // ok + full_osds.erase(osd); + nearfull_osds.erase(osd); + } } -void PGMap::dump_osd_sum_stats(ostream& ss) const +void PGMap::calc_stats() { - TextTable tab; + num_pg = 0; + num_pg_active = 0; + num_pg_unknown = 0; + num_osd = 0; + pg_pool_sum.clear(); + num_pg_by_pool.clear(); + pg_by_osd.clear(); + pg_sum = pool_stat_t(); + osd_sum = osd_stat_t(); + num_pg_by_state.clear(); + num_pg_by_osd.clear(); - tab.define_column("OSD_STAT", TextTable::LEFT, TextTable::LEFT); - tab.define_column("USED", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("TOTAL", TextTable::LEFT, TextTable::RIGHT); + for (auto p = pg_stat.begin(); + p != pg_stat.end(); + ++p) { + stat_pg_add(p->first, p->second); + } + for (auto p = osd_stat.begin(); + p != osd_stat.end(); + ++p) + stat_osd_add(p->first, p->second); - tab << "sum" - << si_t(osd_sum.kb_used << 10) - << si_t(osd_sum.kb_avail << 10) - << si_t(osd_sum.kb << 10) - << TextTable::endrow; + redo_full_sets(); - ss << tab; + min_last_epoch_clean = calc_min_last_epoch_clean(); } -void PGMap::get_stuck_stats(int types, const utime_t cutoff, - ceph::unordered_map& stuck_pgs) const +void PGMap::update_pg(pg_t pgid, bufferlist& bl) { - assert(types != 0); - for (ceph::unordered_map::const_iterator i = pg_stat.begin(); - i != pg_stat.end(); - ++i) { - utime_t val = cutoff; // don't care about >= cutoff so that is infinity - - if ((types & STUCK_INACTIVE) && !(i->second.state & PG_STATE_ACTIVE)) { - if (i->second.last_active < val) - val = i->second.last_active; - } + bufferlist::iterator p = bl.begin(); + auto s = pg_stat.find(pgid); + epoch_t old_lec = 0, lec; + if (s != pg_stat.end()) { + old_lec = s->second.get_effective_last_epoch_clean(); + stat_pg_update(pgid, s->second, p); + lec = s->second.get_effective_last_epoch_clean(); + } else { + pg_stat_t& r = pg_stat[pgid]; + ::decode(r, p); + stat_pg_add(pgid, r); + lec = r.get_effective_last_epoch_clean(); + } - if ((types & STUCK_UNCLEAN) && !(i->second.state & PG_STATE_CLEAN)) { - if (i->second.last_clean < val) - val = i->second.last_clean; - } + if (min_last_epoch_clean && + (lec < min_last_epoch_clean || // we did + (lec > min_last_epoch_clean && // we might + old_lec == min_last_epoch_clean) + )) + min_last_epoch_clean = 0; +} - if ((types & STUCK_DEGRADED) && (i->second.state & PG_STATE_DEGRADED)) { - if (i->second.last_undegraded < val) - val = i->second.last_undegraded; - } - - if ((types & STUCK_UNDERSIZED) && (i->second.state & PG_STATE_UNDERSIZED)) { - if (i->second.last_fullsized < val) - val = i->second.last_fullsized; - } - - if ((types & STUCK_STALE) && (i->second.state & PG_STATE_STALE)) { - if (i->second.last_unstale < val) - val = i->second.last_unstale; - } - - // val is now the earliest any of the requested stuck states began - if (val < cutoff) { - stuck_pgs[i->first] = i->second; - } +void PGMap::remove_pg(pg_t pgid) +{ + auto s = pg_stat.find(pgid); + if (s != pg_stat.end()) { + if (min_last_epoch_clean && + s->second.get_effective_last_epoch_clean() == min_last_epoch_clean) + min_last_epoch_clean = 0; + stat_pg_sub(pgid, s->second); + pg_stat.erase(s); } } -bool PGMap::get_stuck_counts(const utime_t cutoff, map& note) const +void PGMap::update_osd(int osd, bufferlist& bl) { - int inactive = 0; - int unclean = 0; - int degraded = 0; - int undersized = 0; - int stale = 0; + bufferlist::iterator p = bl.begin(); + auto o = osd_stat.find(osd); + epoch_t old_lec = 0; + if (o != osd_stat.end()) { + auto i = osd_epochs.find(osd); + if (i != osd_epochs.end()) + old_lec = i->second; + stat_osd_sub(osd, o->second); + } + osd_stat_t& r = osd_stat[osd]; + ::decode(r, p); + stat_osd_add(osd, r); - for (ceph::unordered_map::const_iterator i = pg_stat.begin(); - i != pg_stat.end(); - ++i) { - if (! (i->second.state & PG_STATE_ACTIVE)) { - if (i->second.last_active < cutoff) - ++inactive; - } - if (! (i->second.state & PG_STATE_CLEAN)) { - if (i->second.last_clean < cutoff) - ++unclean; - } - if (i->second.state & PG_STATE_DEGRADED) { - if (i->second.last_undegraded < cutoff) - ++degraded; - } - if (i->second.state & PG_STATE_UNDERSIZED) { - if (i->second.last_fullsized < cutoff) - ++undersized; - } - if (i->second.state & PG_STATE_STALE) { - if (i->second.last_unstale < cutoff) - ++stale; - } + // adjust [near]full status + register_nearfull_status(osd, r); + + // epoch? + if (!p.end()) { + epoch_t e; + ::decode(e, p); + + if (e < min_last_epoch_clean || + (e > min_last_epoch_clean && + old_lec == min_last_epoch_clean)) + min_last_epoch_clean = 0; + } else { + // WARNING: we are not refreshing min_last_epoch_clean! must be old store + // or old mon running. } - - if (inactive) - note["stuck inactive"] = inactive; - - if (unclean) - note["stuck unclean"] = unclean; - - if (undersized) - note["stuck undersized"] = undersized; - - if (degraded) - note["stuck degraded"] = degraded; - - if (stale) - note["stuck stale"] = stale; - - return inactive || unclean || undersized || degraded || stale; } -void PGMap::dump_stuck(Formatter *f, int types, utime_t cutoff) const +void PGMap::remove_osd(int osd) { - ceph::unordered_map stuck_pg_stats; - get_stuck_stats(types, cutoff, stuck_pg_stats); - f->open_array_section("stuck_pg_stats"); - for (ceph::unordered_map::const_iterator i = stuck_pg_stats.begin(); - i != stuck_pg_stats.end(); - ++i) { - f->open_object_section("pg_stat"); - f->dump_stream("pgid") << i->first; - i->second.dump(f); - f->close_section(); + auto o = osd_stat.find(osd); + if (o != osd_stat.end()) { + stat_osd_sub(osd, o->second); + osd_stat.erase(o); + + // remove these old osds from full/nearfull set(s), too + nearfull_osds.erase(osd); + full_osds.erase(osd); } - f->close_section(); } -void PGMap::dump_stuck_plain(ostream& ss, int types, utime_t cutoff) const +void PGMap::stat_pg_add(const pg_t &pgid, const pg_stat_t &s, + bool sameosds) { - ceph::unordered_map stuck_pg_stats; - get_stuck_stats(types, cutoff, stuck_pg_stats); - if (!stuck_pg_stats.empty()) - dump_pg_stats_plain(ss, stuck_pg_stats, true); -} + pg_pool_sum[pgid.pool()].add(s); + pg_sum.add(s); -int PGMap::dump_stuck_pg_stats( - stringstream &ds, - Formatter *f, - int threshold, - vector& args) const -{ - int stuck_types = 0; + num_pg++; + num_pg_by_state[s.state]++; + num_pg_by_pool[pgid.pool()]++; - for (vector::iterator i = args.begin(); i != args.end(); ++i) { - if (*i == "inactive") - stuck_types |= PGMap::STUCK_INACTIVE; - else if (*i == "unclean") - stuck_types |= PGMap::STUCK_UNCLEAN; - else if (*i == "undersized") - stuck_types |= PGMap::STUCK_UNDERSIZED; - else if (*i == "degraded") - stuck_types |= PGMap::STUCK_DEGRADED; - else if (*i == "stale") - stuck_types |= PGMap::STUCK_STALE; - else { - ds << "Unknown type: " << *i << std::endl; - return -EINVAL; + if ((s.state & PG_STATE_CREATING) && + s.parent_split_bits == 0) { + creating_pgs.insert(pgid); + if (s.acting_primary >= 0) { + creating_pgs_by_osd_epoch[s.acting_primary][s.mapping_epoch].insert(pgid); } } - utime_t now(ceph_clock_now()); - utime_t cutoff = now - utime_t(threshold, 0); - - if (!f) { - dump_stuck_plain(ds, stuck_types, cutoff); - } else { - dump_stuck(f, stuck_types, cutoff); - f->flush(ds); + if (s.state & PG_STATE_ACTIVE) { + ++num_pg_active; + } + if (s.state == 0) { + ++num_pg_unknown; } - return 0; -} + if (sameosds) + return; -void PGMap::dump_osd_perf_stats(Formatter *f) const -{ - f->open_array_section("osd_perf_infos"); - for (ceph::unordered_map::const_iterator i = osd_stat.begin(); - i != osd_stat.end(); - ++i) { - f->open_object_section("osd"); - f->dump_int("id", i->first); - { - f->open_object_section("perf_stats"); - i->second.os_perf_stat.dump(f); - f->close_section(); - } - f->close_section(); + for (auto p = s.blocked_by.begin(); + p != s.blocked_by.end(); + ++p) { + ++blocked_by_sum[*p]; } - f->close_section(); -} -void PGMap::print_osd_perf_stats(std::ostream *ss) const -{ - TextTable tab; - tab.define_column("osd", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("commit_latency(ms)", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("apply_latency(ms)", TextTable::LEFT, TextTable::RIGHT); - for (ceph::unordered_map::const_iterator i = osd_stat.begin(); - i != osd_stat.end(); - ++i) { - tab << i->first; - tab << i->second.os_perf_stat.os_commit_latency; - tab << i->second.os_perf_stat.os_apply_latency; - tab << TextTable::endrow; + + for (auto p = s.acting.begin(); p != s.acting.end(); ++p) { + pg_by_osd[*p].insert(pgid); + num_pg_by_osd[*p].acting++; + } + for (auto p = s.up.begin(); p != s.up.end(); ++p) { + pg_by_osd[*p].insert(pgid); + num_pg_by_osd[*p].up++; } - (*ss) << tab; -} -void PGMap::dump_osd_blocked_by_stats(Formatter *f) const -{ - f->open_array_section("osd_blocked_by_infos"); - for (ceph::unordered_map::const_iterator i = blocked_by_sum.begin(); - i != blocked_by_sum.end(); - ++i) { - f->open_object_section("osd"); - f->dump_int("id", i->first); - f->dump_int("num_blocked", i->second); - f->close_section(); + if (s.up_primary >= 0) { + num_pg_by_osd[s.up_primary].primary++; } - f->close_section(); } -void PGMap::print_osd_blocked_by_stats(std::ostream *ss) const + +void PGMap::stat_pg_sub(const pg_t &pgid, const pg_stat_t &s, + bool sameosds) { - TextTable tab; - tab.define_column("osd", TextTable::LEFT, TextTable::RIGHT); - tab.define_column("num_blocked", TextTable::LEFT, TextTable::RIGHT); - for (ceph::unordered_map::const_iterator i = blocked_by_sum.begin(); - i != blocked_by_sum.end(); - ++i) { - tab << i->first; - tab << i->second; - tab << TextTable::endrow; + pool_stat_t& ps = pg_pool_sum[pgid.pool()]; + ps.sub(s); + pg_sum.sub(s); + + num_pg--; + int end = --num_pg_by_state[s.state]; + assert(end >= 0); + if (end == 0) + num_pg_by_state.erase(s.state); + end = --num_pg_by_pool[pgid.pool()]; + if (end == 0) { + num_pg_by_pool.erase(pgid.pool()); + pg_pool_sum.erase(pgid.pool()); } - (*ss) << tab; -} -void PGMap::recovery_summary(Formatter *f, list *psl, - const pool_stat_t& delta_sum) const -{ - if (delta_sum.stats.sum.num_objects_degraded && delta_sum.stats.sum.num_object_copies > 0) { - double pc = (double)delta_sum.stats.sum.num_objects_degraded / - (double)delta_sum.stats.sum.num_object_copies * (double)100.0; - char b[20]; - snprintf(b, sizeof(b), "%.3lf", pc); - if (f) { - f->dump_unsigned("degraded_objects", delta_sum.stats.sum.num_objects_degraded); - f->dump_unsigned("degraded_total", delta_sum.stats.sum.num_object_copies); - f->dump_float("degraded_ratio", pc / 100.0); - } else { - ostringstream ss; - ss << delta_sum.stats.sum.num_objects_degraded - << "/" << delta_sum.stats.sum.num_object_copies << " objects degraded (" << b << "%)"; - psl->push_back(ss.str()); + if ((s.state & PG_STATE_CREATING) && + s.parent_split_bits == 0) { + creating_pgs.erase(pgid); + if (s.acting_primary >= 0) { + map >& r = creating_pgs_by_osd_epoch[s.acting_primary]; + r[s.mapping_epoch].erase(pgid); + if (r[s.mapping_epoch].empty()) + r.erase(s.mapping_epoch); + if (r.empty()) + creating_pgs_by_osd_epoch.erase(s.acting_primary); } } - if (delta_sum.stats.sum.num_objects_misplaced && delta_sum.stats.sum.num_object_copies > 0) { - double pc = (double)delta_sum.stats.sum.num_objects_misplaced / - (double)delta_sum.stats.sum.num_object_copies * (double)100.0; - char b[20]; - snprintf(b, sizeof(b), "%.3lf", pc); - if (f) { - f->dump_unsigned("misplaced_objects", delta_sum.stats.sum.num_objects_misplaced); - f->dump_unsigned("misplaced_total", delta_sum.stats.sum.num_object_copies); - f->dump_float("misplaced_ratio", pc / 100.0); - } else { - ostringstream ss; - ss << delta_sum.stats.sum.num_objects_misplaced - << "/" << delta_sum.stats.sum.num_object_copies << " objects misplaced (" << b << "%)"; - psl->push_back(ss.str()); + + if (s.state & PG_STATE_ACTIVE) { + --num_pg_active; + } + if (s.state == 0) { + --num_pg_unknown; + } + + if (sameosds) + return; + + for (auto p = s.blocked_by.begin(); + p != s.blocked_by.end(); + ++p) { + auto q = blocked_by_sum.find(*p); + assert(q != blocked_by_sum.end()); + --q->second; + if (q->second == 0) + blocked_by_sum.erase(q); + } + + for (auto p = s.acting.begin(); p != s.acting.end(); ++p) { + auto& oset = pg_by_osd[*p]; + oset.erase(pgid); + if (oset.empty()) + pg_by_osd.erase(*p); + auto it = num_pg_by_osd.find(*p); + if (it != num_pg_by_osd.end() && it->second.acting > 0) + it->second.acting--; + } + for (auto p = s.up.begin(); p != s.up.end(); ++p) { + auto& oset = pg_by_osd[*p]; + oset.erase(pgid); + if (oset.empty()) + pg_by_osd.erase(*p); + auto it = num_pg_by_osd.find(*p); + if (it != num_pg_by_osd.end() && it->second.up > 0) + it->second.up--; + } + + if (s.up_primary >= 0) { + auto it = num_pg_by_osd.find(s.up_primary); + if (it != num_pg_by_osd.end() && it->second.primary > 0) + it->second.primary--; + } +} + +void PGMap::stat_pg_update(const pg_t pgid, pg_stat_t& s, + bufferlist::iterator& blp) +{ + pg_stat_t n; + ::decode(n, blp); + + bool sameosds = + s.acting == n.acting && + s.up == n.up && + s.blocked_by == n.blocked_by; + + stat_pg_sub(pgid, s, sameosds); + + // if acting_primary has shift to an just restored osd, and pg yet to finish + // peering, many attributes in current stats remain stale. others seem don't + // mater much while faulty last_active will make "pg stuck in" check unhappy. + if (!(n.state & (PG_STATE_ACTIVE | PG_STATE_PEERED)) && + n.last_active < s.last_active) + n.last_active = s.last_active; + s = n; + stat_pg_add(pgid, n, sameosds); +} + +void PGMap::stat_osd_add(int osd, const osd_stat_t &s) +{ + num_osd++; + osd_sum.add(s); + if (osd >= (int)osd_last_seq.size()) { + osd_last_seq.resize(osd + 1); + } + osd_last_seq[osd] = s.seq; +} + +void PGMap::stat_osd_sub(int osd, const osd_stat_t &s) +{ + num_osd--; + osd_sum.sub(s); + assert(osd < (int)osd_last_seq.size()); + osd_last_seq[osd] = 0; +} + +epoch_t PGMap::calc_min_last_epoch_clean() const +{ + if (pg_stat.empty()) + return 0; + + auto p = pg_stat.begin(); + epoch_t min = p->second.get_effective_last_epoch_clean(); + for (++p; p != pg_stat.end(); ++p) { + epoch_t lec = p->second.get_effective_last_epoch_clean(); + if (lec < min) + min = lec; + } + // also scan osd epochs + // don't trim past the oldest reported osd epoch + for (auto i = osd_epochs.begin(); + i != osd_epochs.end(); + ++i) { + if (i->second < min) + min = i->second; + } + return min; +} + +void PGMap::encode_digest(const OSDMap& osdmap, + bufferlist& bl, uint64_t features) const +{ + get_rules_avail(osdmap, &avail_space_by_rule); + PGMapDigest::encode(bl, features); +} + +void PGMap::encode(bufferlist &bl, uint64_t features) const +{ + if ((features & CEPH_FEATURE_MONENC) == 0) { + __u8 v = 3; + ::encode(v, bl); + ::encode(version, bl); + ::encode(pg_stat, bl); + ::encode(osd_stat, bl); + ::encode(last_osdmap_epoch, bl); + ::encode(last_pg_scan, bl); + ::encode(full_ratio, bl); + ::encode(nearfull_ratio, bl); + return; + } + + ENCODE_START(6, 4, bl); + ::encode(version, bl); + ::encode(pg_stat, bl); + ::encode(osd_stat, bl); + ::encode(last_osdmap_epoch, bl); + ::encode(last_pg_scan, bl); + ::encode(full_ratio, bl); + ::encode(nearfull_ratio, bl); + ::encode(stamp, bl); + ::encode(osd_epochs, bl); + ENCODE_FINISH(bl); +} + +void PGMap::decode(bufferlist::iterator &bl) +{ + DECODE_START_LEGACY_COMPAT_LEN(6, 4, 4, bl); + ::decode(version, bl); + if (struct_v < 3) { + pg_stat.clear(); + __u32 n; + ::decode(n, bl); + while (n--) { + old_pg_t opgid; + ::decode(opgid, bl); + pg_t pgid = opgid; + ::decode(pg_stat[pgid], bl); } + } else { + ::decode(pg_stat, bl); } - if (delta_sum.stats.sum.num_objects_unfound && delta_sum.stats.sum.num_objects) { - double pc = (double)delta_sum.stats.sum.num_objects_unfound / - (double)delta_sum.stats.sum.num_objects * (double)100.0; - char b[20]; - snprintf(b, sizeof(b), "%.3lf", pc); - if (f) { - f->dump_unsigned("unfound_objects", delta_sum.stats.sum.num_objects_unfound); - f->dump_unsigned("unfound_total", delta_sum.stats.sum.num_objects); - f->dump_float("unfound_ratio", pc / 100.0); - } else { - ostringstream ss; - ss << delta_sum.stats.sum.num_objects_unfound - << "/" << delta_sum.stats.sum.num_objects << " unfound (" << b << "%)"; - psl->push_back(ss.str()); + ::decode(osd_stat, bl); + ::decode(last_osdmap_epoch, bl); + ::decode(last_pg_scan, bl); + if (struct_v >= 2) { + ::decode(full_ratio, bl); + ::decode(nearfull_ratio, bl); + } + if (struct_v >= 5) + ::decode(stamp, bl); + if (struct_v >= 6) { + ::decode(osd_epochs, bl); + } else { + for (auto i = osd_stat.begin(); + i != osd_stat.end(); + ++i) { + // This isn't accurate, but will cause trimming to behave like + // previously. + osd_epochs.insert(make_pair(i->first, last_osdmap_epoch)); } } + DECODE_FINISH(bl); + + calc_stats(); } -void PGMap::recovery_rate_summary(Formatter *f, ostream *out, - const pool_stat_t& delta_sum, - utime_t delta_stamp) const +void PGMap::dirty_all(Incremental& inc) { - // make non-negative; we can get negative values if osds send - // uncommitted stats and then "go backward" or if they are just - // buggy/wrong. - pool_stat_t pos_delta = delta_sum; - pos_delta.floor(0); - if (pos_delta.stats.sum.num_objects_recovered || - pos_delta.stats.sum.num_bytes_recovered || - pos_delta.stats.sum.num_keys_recovered) { - int64_t objps = pos_delta.stats.sum.num_objects_recovered / (double)delta_stamp; - int64_t bps = pos_delta.stats.sum.num_bytes_recovered / (double)delta_stamp; - int64_t kps = pos_delta.stats.sum.num_keys_recovered / (double)delta_stamp; - if (f) { - f->dump_int("recovering_objects_per_sec", objps); - f->dump_int("recovering_bytes_per_sec", bps); - f->dump_int("recovering_keys_per_sec", kps); - f->dump_int("num_objects_recovered", pos_delta.stats.sum.num_objects_recovered); - f->dump_int("num_bytes_recovered", pos_delta.stats.sum.num_bytes_recovered); - f->dump_int("num_keys_recovered", pos_delta.stats.sum.num_keys_recovered); + inc.osdmap_epoch = last_osdmap_epoch; + inc.pg_scan = last_pg_scan; + inc.full_ratio = full_ratio; + inc.nearfull_ratio = nearfull_ratio; + + for (auto p = pg_stat.begin(); p != pg_stat.end(); ++p) { + inc.pg_stat_updates[p->first] = p->second; + } + for (auto p = osd_stat.begin(); p != osd_stat.end(); ++p) { + assert(osd_epochs.count(p->first)); + inc.update_stat(p->first, + inc.get_osd_epochs().find(p->first)->second, + p->second); + } +} + +void PGMap::dump(Formatter *f) const +{ + dump_basic(f); + dump_pg_stats(f, false); + dump_pool_stats(f); + dump_osd_stats(f); +} + +void PGMap::dump_basic(Formatter *f) const +{ + f->dump_unsigned("version", version); + f->dump_stream("stamp") << stamp; + f->dump_unsigned("last_osdmap_epoch", last_osdmap_epoch); + f->dump_unsigned("last_pg_scan", last_pg_scan); + f->dump_unsigned("min_last_epoch_clean", min_last_epoch_clean); + f->dump_float("full_ratio", full_ratio); + f->dump_float("near_full_ratio", nearfull_ratio); + + f->open_object_section("pg_stats_sum"); + pg_sum.dump(f); + f->close_section(); + + f->open_object_section("osd_stats_sum"); + osd_sum.dump(f); + f->close_section(); + + f->open_array_section("osd_epochs"); + for (auto p = osd_epochs.begin(); p != osd_epochs.end(); ++p) { + f->open_object_section("osd"); + f->dump_unsigned("osd", p->first); + f->dump_unsigned("epoch", p->second); + f->close_section(); + } + f->close_section(); + + dump_delta(f); +} + +void PGMap::dump_delta(Formatter *f) const +{ + f->open_object_section("pg_stats_delta"); + pg_sum_delta.dump(f); + f->close_section(); +} + +void PGMap::dump_pg_stats(Formatter *f, bool brief) const +{ + f->open_array_section("pg_stats"); + for (auto i = pg_stat.begin(); + i != pg_stat.end(); + ++i) { + f->open_object_section("pg_stat"); + f->dump_stream("pgid") << i->first; + if (brief) + i->second.dump_brief(f); + else + i->second.dump(f); + f->close_section(); + } + f->close_section(); +} + +void PGMap::dump_pool_stats(Formatter *f) const +{ + f->open_array_section("pool_stats"); + for (auto p = pg_pool_sum.begin(); + p != pg_pool_sum.end(); + ++p) { + f->open_object_section("pool_stat"); + f->dump_int("poolid", p->first); + auto q = num_pg_by_pool.find(p->first); + if (q != num_pg_by_pool.end()) + f->dump_unsigned("num_pg", q->second); + p->second.dump(f); + f->close_section(); + } + f->close_section(); +} + +void PGMap::dump_osd_stats(Formatter *f) const +{ + f->open_array_section("osd_stats"); + for (auto q = osd_stat.begin(); + q != osd_stat.end(); + ++q) { + f->open_object_section("osd_stat"); + f->dump_int("osd", q->first); + q->second.dump(f); + f->close_section(); + } + f->close_section(); +} + +void PGMap::dump_pg_stats_plain( + ostream& ss, + const mempool::pgmap::unordered_map& pg_stats, + bool brief) const +{ + TextTable tab; + + if (brief){ + tab.define_column("PG_STAT", TextTable::LEFT, TextTable::LEFT); + tab.define_column("STATE", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UP", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UP_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("ACTING", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("ACTING_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + } + else { + tab.define_column("PG_STAT", TextTable::LEFT, TextTable::LEFT); + tab.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("MISSING_ON_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DEGRADED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("MISPLACED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UNFOUND", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("BYTES", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("LOG", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DISK_LOG", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("STATE", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("STATE_STAMP", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("VERSION", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("REPORTED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UP", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UP_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("ACTING", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("ACTING_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("LAST_SCRUB", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("SCRUB_STAMP", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("LAST_DEEP_SCRUB", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DEEP_SCRUB_STAMP", TextTable::LEFT, TextTable::RIGHT); + } + + for (auto i = pg_stats.begin(); + i != pg_stats.end(); ++i) { + const pg_stat_t &st(i->second); + if (brief) { + tab << i->first + << pg_state_string(st.state) + << st.up + << st.up_primary + << st.acting + << st.acting_primary + << TextTable::endrow; } else { - *out << pretty_si_t(bps) << "B/s"; - if (pos_delta.stats.sum.num_keys_recovered) - *out << ", " << pretty_si_t(kps) << "keys/s"; - *out << ", " << pretty_si_t(objps) << "objects/s"; + ostringstream reported; + reported << st.reported_epoch << ":" << st.reported_seq; + + tab << i->first + << st.stats.sum.num_objects + << st.stats.sum.num_objects_missing_on_primary + << st.stats.sum.num_objects_degraded + << st.stats.sum.num_objects_misplaced + << st.stats.sum.num_objects_unfound + << st.stats.sum.num_bytes + << st.log_size + << st.ondisk_log_size + << pg_state_string(st.state) + << st.last_change + << st.version + << reported.str() + << pg_vector_string(st.up) + << st.up_primary + << pg_vector_string(st.acting) + << st.acting_primary + << st.last_scrub + << st.last_scrub_stamp + << st.last_deep_scrub + << st.last_deep_scrub_stamp + << TextTable::endrow; } } -} -void PGMap::overall_recovery_rate_summary(Formatter *f, ostream *out) const -{ - recovery_rate_summary(f, out, pg_sum_delta, stamp_delta); -} + ss << tab; +} + +void PGMap::dump(ostream& ss) const +{ + dump_basic(ss); + dump_pg_stats(ss, false); + dump_pool_stats(ss, false); + dump_pg_sum_stats(ss, false); + dump_osd_stats(ss); +} + +void PGMap::dump_basic(ostream& ss) const +{ + ss << "version " << version << std::endl; + ss << "stamp " << stamp << std::endl; + ss << "last_osdmap_epoch " << last_osdmap_epoch << std::endl; + ss << "last_pg_scan " << last_pg_scan << std::endl; + ss << "full_ratio " << full_ratio << std::endl; + ss << "nearfull_ratio " << nearfull_ratio << std::endl; +} + +void PGMap::dump_pg_stats(ostream& ss, bool brief) const +{ + dump_pg_stats_plain(ss, pg_stat, brief); +} + +void PGMap::dump_pool_stats(ostream& ss, bool header) const +{ + TextTable tab; + + if (header) { + tab.define_column("POOLID", TextTable::LEFT, TextTable::LEFT); + tab.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("MISSING_ON_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DEGRADED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("MISPLACED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UNFOUND", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("BYTES", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("LOG", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DISK_LOG", TextTable::LEFT, TextTable::RIGHT); + } else { + tab.define_column("", TextTable::LEFT, TextTable::LEFT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + } + + for (auto p = pg_pool_sum.begin(); + p != pg_pool_sum.end(); + ++p) { + tab << p->first + << p->second.stats.sum.num_objects + << p->second.stats.sum.num_objects_missing_on_primary + << p->second.stats.sum.num_objects_degraded + << p->second.stats.sum.num_objects_misplaced + << p->second.stats.sum.num_objects_unfound + << p->second.stats.sum.num_bytes + << p->second.log_size + << p->second.ondisk_log_size + << TextTable::endrow; + } + + ss << tab; +} + +void PGMap::dump_pg_sum_stats(ostream& ss, bool header) const +{ + TextTable tab; + + if (header) { + tab.define_column("PG_STAT", TextTable::LEFT, TextTable::LEFT); + tab.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("MISSING_ON_PRIMARY", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DEGRADED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("MISPLACED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("UNFOUND", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("BYTES", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("LOG", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("DISK_LOG", TextTable::LEFT, TextTable::RIGHT); + } else { + tab.define_column("", TextTable::LEFT, TextTable::LEFT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("", TextTable::LEFT, TextTable::RIGHT); + }; + + tab << "sum" + << pg_sum.stats.sum.num_objects + << pg_sum.stats.sum.num_objects_missing_on_primary + << pg_sum.stats.sum.num_objects_degraded + << pg_sum.stats.sum.num_objects_misplaced + << pg_sum.stats.sum.num_objects_unfound + << pg_sum.stats.sum.num_bytes + << pg_sum.log_size + << pg_sum.ondisk_log_size + << TextTable::endrow; + + ss << tab; +} + +void PGMap::dump_osd_stats(ostream& ss) const +{ + TextTable tab; + + tab.define_column("OSD_STAT", TextTable::LEFT, TextTable::LEFT); + tab.define_column("USED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("TOTAL", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("HB_PEERS", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("PG_SUM", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("PRIMARY_PG_SUM", TextTable::LEFT, TextTable::RIGHT); + + for (auto p = osd_stat.begin(); + p != osd_stat.end(); + ++p) { + tab << p->first + << si_t(p->second.kb_used << 10) + << si_t(p->second.kb_avail << 10) + << si_t(p->second.kb << 10) + << p->second.hb_peers + << get_num_pg_by_osd(p->first) + << get_num_primary_pg_by_osd(p->first) + << TextTable::endrow; + } + + tab << "sum" + << si_t(osd_sum.kb_used << 10) + << si_t(osd_sum.kb_avail << 10) + << si_t(osd_sum.kb << 10) + << TextTable::endrow; -void PGMap::overall_recovery_summary(Formatter *f, list *psl) const -{ - recovery_summary(f, psl, pg_sum); + ss << tab; } -void PGMap::pool_recovery_rate_summary(Formatter *f, ostream *out, - uint64_t poolid) const +void PGMap::dump_osd_sum_stats(ostream& ss) const { - ceph::unordered_map >::const_iterator p = - per_pool_sum_delta.find(poolid); - if (p == per_pool_sum_delta.end()) - return; + TextTable tab; - ceph::unordered_map::const_iterator ts = - per_pool_sum_deltas_stamps.find(p->first); - assert(ts != per_pool_sum_deltas_stamps.end()); - recovery_rate_summary(f, out, p->second.first, ts->second); -} + tab.define_column("OSD_STAT", TextTable::LEFT, TextTable::LEFT); + tab.define_column("USED", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("TOTAL", TextTable::LEFT, TextTable::RIGHT); -void PGMap::pool_recovery_summary(Formatter *f, list *psl, - uint64_t poolid) const -{ - ceph::unordered_map >::const_iterator p = - per_pool_sum_delta.find(poolid); - if (p == per_pool_sum_delta.end()) - return; + tab << "sum" + << si_t(osd_sum.kb_used << 10) + << si_t(osd_sum.kb_avail << 10) + << si_t(osd_sum.kb << 10) + << TextTable::endrow; - recovery_summary(f, psl, p->second.first); + ss << tab; } -void PGMap::client_io_rate_summary(Formatter *f, ostream *out, - const pool_stat_t& delta_sum, - utime_t delta_stamp) const +void PGMap::get_stuck_stats( + int types, const utime_t cutoff, + mempool::pgmap::unordered_map& stuck_pgs) const { - pool_stat_t pos_delta = delta_sum; - pos_delta.floor(0); - if (pos_delta.stats.sum.num_rd || - pos_delta.stats.sum.num_wr) { - if (pos_delta.stats.sum.num_rd) { - int64_t rd = (pos_delta.stats.sum.num_rd_kb << 10) / (double)delta_stamp; - if (f) { - f->dump_int("read_bytes_sec", rd); - } else { - *out << pretty_si_t(rd) << "B/s rd, "; - } + assert(types != 0); + for (auto i = pg_stat.begin(); + i != pg_stat.end(); + ++i) { + utime_t val = cutoff; // don't care about >= cutoff so that is infinity + + if ((types & STUCK_INACTIVE) && !(i->second.state & PG_STATE_ACTIVE)) { + if (i->second.last_active < val) + val = i->second.last_active; } - if (pos_delta.stats.sum.num_wr) { - int64_t wr = (pos_delta.stats.sum.num_wr_kb << 10) / (double)delta_stamp; - if (f) { - f->dump_int("write_bytes_sec", wr); - } else { - *out << pretty_si_t(wr) << "B/s wr, "; - } + + if ((types & STUCK_UNCLEAN) && !(i->second.state & PG_STATE_CLEAN)) { + if (i->second.last_clean < val) + val = i->second.last_clean; } - int64_t iops_rd = pos_delta.stats.sum.num_rd / (double)delta_stamp; - int64_t iops_wr = pos_delta.stats.sum.num_wr / (double)delta_stamp; - if (f) { - f->dump_int("read_op_per_sec", iops_rd); - f->dump_int("write_op_per_sec", iops_wr); - } else { - *out << pretty_si_t(iops_rd) << "op/s rd, " << pretty_si_t(iops_wr) << "op/s wr"; + + if ((types & STUCK_DEGRADED) && (i->second.state & PG_STATE_DEGRADED)) { + if (i->second.last_undegraded < val) + val = i->second.last_undegraded; } - } -} -void PGMap::overall_client_io_rate_summary(Formatter *f, ostream *out) const -{ - client_io_rate_summary(f, out, pg_sum_delta, stamp_delta); -} + if ((types & STUCK_UNDERSIZED) && (i->second.state & PG_STATE_UNDERSIZED)) { + if (i->second.last_fullsized < val) + val = i->second.last_fullsized; + } -void PGMap::pool_client_io_rate_summary(Formatter *f, ostream *out, - uint64_t poolid) const -{ - ceph::unordered_map >::const_iterator p = - per_pool_sum_delta.find(poolid); - if (p == per_pool_sum_delta.end()) - return; + if ((types & STUCK_STALE) && (i->second.state & PG_STATE_STALE)) { + if (i->second.last_unstale < val) + val = i->second.last_unstale; + } - ceph::unordered_map::const_iterator ts = - per_pool_sum_deltas_stamps.find(p->first); - assert(ts != per_pool_sum_deltas_stamps.end()); - client_io_rate_summary(f, out, p->second.first, ts->second); + // val is now the earliest any of the requested stuck states began + if (val < cutoff) { + stuck_pgs[i->first] = i->second; + } + } } -void PGMap::cache_io_rate_summary(Formatter *f, ostream *out, - const pool_stat_t& delta_sum, - utime_t delta_stamp) const +bool PGMap::get_stuck_counts(const utime_t cutoff, map& note) const { - pool_stat_t pos_delta = delta_sum; - pos_delta.floor(0); - bool have_output = false; + int inactive = 0; + int unclean = 0; + int degraded = 0; + int undersized = 0; + int stale = 0; - if (pos_delta.stats.sum.num_flush) { - int64_t flush = (pos_delta.stats.sum.num_flush_kb << 10) / (double)delta_stamp; - if (f) { - f->dump_int("flush_bytes_sec", flush); - } else { - *out << pretty_si_t(flush) << "B/s flush"; - have_output = true; + for (auto i = pg_stat.begin(); + i != pg_stat.end(); + ++i) { + if (! (i->second.state & PG_STATE_ACTIVE)) { + if (i->second.last_active < cutoff) + ++inactive; } - } - if (pos_delta.stats.sum.num_evict) { - int64_t evict = (pos_delta.stats.sum.num_evict_kb << 10) / (double)delta_stamp; - if (f) { - f->dump_int("evict_bytes_sec", evict); - } else { - if (have_output) - *out << ", "; - *out << pretty_si_t(evict) << "B/s evict"; - have_output = true; + if (! (i->second.state & PG_STATE_CLEAN)) { + if (i->second.last_clean < cutoff) + ++unclean; } - } - if (pos_delta.stats.sum.num_promote) { - int64_t promote = pos_delta.stats.sum.num_promote / (double)delta_stamp; - if (f) { - f->dump_int("promote_op_per_sec", promote); - } else { - if (have_output) - *out << ", "; - *out << pretty_si_t(promote) << "op/s promote"; - have_output = true; + if (i->second.state & PG_STATE_DEGRADED) { + if (i->second.last_undegraded < cutoff) + ++degraded; } - } - if (pos_delta.stats.sum.num_flush_mode_low) { - if (f) { - f->dump_int("num_flush_mode_low", pos_delta.stats.sum.num_flush_mode_low); - } else { - if (have_output) - *out << ", "; - *out << pretty_si_t(pos_delta.stats.sum.num_flush_mode_low) << "PG(s) flushing"; - have_output = true; + if (i->second.state & PG_STATE_UNDERSIZED) { + if (i->second.last_fullsized < cutoff) + ++undersized; } - } - if (pos_delta.stats.sum.num_flush_mode_high) { - if (f) { - f->dump_int("num_flush_mode_high", pos_delta.stats.sum.num_flush_mode_high); - } else { - if (have_output) - *out << ", "; - *out << pretty_si_t(pos_delta.stats.sum.num_flush_mode_high) << "PG(s) flushing (high)"; - have_output = true; + if (i->second.state & PG_STATE_STALE) { + if (i->second.last_unstale < cutoff) + ++stale; } } - if (pos_delta.stats.sum.num_evict_mode_some) { - if (f) { - f->dump_int("num_evict_mode_some", pos_delta.stats.sum.num_evict_mode_some); - } else { - if (have_output) - *out << ", "; - *out << pretty_si_t(pos_delta.stats.sum.num_evict_mode_some) << "PG(s) evicting"; - have_output = true; + + if (inactive) + note["stuck inactive"] = inactive; + + if (unclean) + note["stuck unclean"] = unclean; + + if (undersized) + note["stuck undersized"] = undersized; + + if (degraded) + note["stuck degraded"] = degraded; + + if (stale) + note["stuck stale"] = stale; + + return inactive || unclean || undersized || degraded || stale; +} + +void PGMap::dump_stuck(Formatter *f, int types, utime_t cutoff) const +{ + mempool::pgmap::unordered_map stuck_pg_stats; + get_stuck_stats(types, cutoff, stuck_pg_stats); + f->open_array_section("stuck_pg_stats"); + for (auto i = stuck_pg_stats.begin(); + i != stuck_pg_stats.end(); + ++i) { + f->open_object_section("pg_stat"); + f->dump_stream("pgid") << i->first; + i->second.dump(f); + f->close_section(); + } + f->close_section(); +} + +void PGMap::dump_stuck_plain(ostream& ss, int types, utime_t cutoff) const +{ + mempool::pgmap::unordered_map stuck_pg_stats; + get_stuck_stats(types, cutoff, stuck_pg_stats); + if (!stuck_pg_stats.empty()) + dump_pg_stats_plain(ss, stuck_pg_stats, true); +} + +int PGMap::dump_stuck_pg_stats( + stringstream &ds, + Formatter *f, + int threshold, + vector& args) const +{ + int stuck_types = 0; + + for (auto i = args.begin(); i != args.end(); ++i) { + if (*i == "inactive") + stuck_types |= PGMap::STUCK_INACTIVE; + else if (*i == "unclean") + stuck_types |= PGMap::STUCK_UNCLEAN; + else if (*i == "undersized") + stuck_types |= PGMap::STUCK_UNDERSIZED; + else if (*i == "degraded") + stuck_types |= PGMap::STUCK_DEGRADED; + else if (*i == "stale") + stuck_types |= PGMap::STUCK_STALE; + else { + ds << "Unknown type: " << *i << std::endl; + return -EINVAL; } } - if (pos_delta.stats.sum.num_evict_mode_full) { - if (f) { - f->dump_int("num_evict_mode_full", pos_delta.stats.sum.num_evict_mode_full); - } else { - if (have_output) - *out << ", "; - *out << pretty_si_t(pos_delta.stats.sum.num_evict_mode_full) << "PG(s) evicting (full)"; - } + + utime_t now(ceph_clock_now()); + utime_t cutoff = now - utime_t(threshold, 0); + + if (!f) { + dump_stuck_plain(ds, stuck_types, cutoff); + } else { + dump_stuck(f, stuck_types, cutoff); + f->flush(ds); } + + return 0; } -void PGMap::overall_cache_io_rate_summary(Formatter *f, ostream *out) const +void PGMap::dump_osd_perf_stats(Formatter *f) const { - cache_io_rate_summary(f, out, pg_sum_delta, stamp_delta); + f->open_array_section("osd_perf_infos"); + for (auto i = osd_stat.begin(); + i != osd_stat.end(); + ++i) { + f->open_object_section("osd"); + f->dump_int("id", i->first); + { + f->open_object_section("perf_stats"); + i->second.os_perf_stat.dump(f); + f->close_section(); + } + f->close_section(); + } + f->close_section(); } - -void PGMap::pool_cache_io_rate_summary(Formatter *f, ostream *out, - uint64_t poolid) const +void PGMap::print_osd_perf_stats(std::ostream *ss) const { - ceph::unordered_map >::const_iterator p = - per_pool_sum_delta.find(poolid); - if (p == per_pool_sum_delta.end()) - return; + TextTable tab; + tab.define_column("osd", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("commit_latency(ms)", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("apply_latency(ms)", TextTable::LEFT, TextTable::RIGHT); + for (auto i = osd_stat.begin(); + i != osd_stat.end(); + ++i) { + tab << i->first; + tab << i->second.os_perf_stat.os_commit_latency; + tab << i->second.os_perf_stat.os_apply_latency; + tab << TextTable::endrow; + } + (*ss) << tab; +} - ceph::unordered_map::const_iterator ts = - per_pool_sum_deltas_stamps.find(p->first); - assert(ts != per_pool_sum_deltas_stamps.end()); - cache_io_rate_summary(f, out, p->second.first, ts->second); +void PGMap::dump_osd_blocked_by_stats(Formatter *f) const +{ + f->open_array_section("osd_blocked_by_infos"); + for (auto i = blocked_by_sum.begin(); + i != blocked_by_sum.end(); + ++i) { + f->open_object_section("osd"); + f->dump_int("id", i->first); + f->dump_int("num_blocked", i->second); + f->close_section(); + } + f->close_section(); +} +void PGMap::print_osd_blocked_by_stats(std::ostream *ss) const +{ + TextTable tab; + tab.define_column("osd", TextTable::LEFT, TextTable::RIGHT); + tab.define_column("num_blocked", TextTable::LEFT, TextTable::RIGHT); + for (auto i = blocked_by_sum.begin(); + i != blocked_by_sum.end(); + ++i) { + tab << i->first; + tab << i->second; + tab << TextTable::endrow; + } + (*ss) << tab; } + /** * update aggregated delta * @@ -1524,14 +2161,15 @@ void PGMap::pool_cache_io_rate_summary(Formatter *f, ostream *out, * @param result_ts_delta Resulting timestamp delta * @param delta_avg_list List of last N computed deltas, used to average */ -void PGMap::update_delta(CephContext *cct, - const utime_t ts, - const pool_stat_t& old_pool_sum, - utime_t *last_ts, - const pool_stat_t& current_pool_sum, - pool_stat_t *result_pool_delta, - utime_t *result_ts_delta, - list > *delta_avg_list) +void PGMap::update_delta( + CephContext *cct, + const utime_t ts, + const pool_stat_t& old_pool_sum, + utime_t *last_ts, + const pool_stat_t& current_pool_sum, + pool_stat_t *result_pool_delta, + utime_t *result_ts_delta, + mempool::pgmap::list > *delta_avg_list) { /* @p ts is the timestamp we want to associate with the data * in @p old_pool_sum, and on which we will base ourselves to @@ -1542,7 +2180,11 @@ void PGMap::update_delta(CephContext *cct, delta_t -= *last_ts; // take the last timestamp we saw *last_ts = ts; // @p ts becomes the last timestamp we saw - // calculate a delta, and average over the last 2 deltas. + // adjust delta_t, quick start if there is no update in a long period + delta_t = std::min(delta_t, + utime_t(2 * (cct ? cct->_conf->mon_delta_reset_interval : 10), 0)); + + // calculate a delta, and average over the last 6 deltas by default. /* start by taking a copy of our current @p result_pool_sum, and by * taking out the stats from @p old_pool_sum. This generates a stats * delta. Stash this stats delta in @p delta_avg_list, along with the @@ -1587,17 +2229,18 @@ void PGMap::update_global_delta(CephContext *cct, * @param pool Pool's id * @param old_pool_sum Previous stats sum */ -void PGMap::update_one_pool_delta(CephContext *cct, - const utime_t ts, - const uint64_t pool, - const pool_stat_t& old_pool_sum) +void PGMap::update_one_pool_delta( + CephContext *cct, + const utime_t ts, + const uint64_t pool, + const pool_stat_t& old_pool_sum) { if (per_pool_sum_deltas.count(pool) == 0) { assert(per_pool_sum_deltas_stamps.count(pool) == 0); assert(per_pool_sum_delta.count(pool) == 0); } - pair& sum_delta = per_pool_sum_delta[pool]; + auto& sum_delta = per_pool_sum_delta[pool]; update_delta(cct, ts, old_pool_sum, &sum_delta.second, pg_pool_sum[pool], &sum_delta.first, &per_pool_sum_deltas_stamps[pool], @@ -1611,10 +2254,11 @@ void PGMap::update_one_pool_delta(CephContext *cct, * @param ts Timestamp for the stats being delta'ed * @param pg_pool_sum_old Map of pool stats for delta calcs. */ -void PGMap::update_pool_deltas(CephContext *cct, const utime_t ts, - const ceph::unordered_map& pg_pool_sum_old) +void PGMap::update_pool_deltas( + CephContext *cct, const utime_t ts, + const mempool::pgmap::unordered_map& pg_pool_sum_old) { - for (ceph::unordered_map::const_iterator it = pg_pool_sum_old.begin(); + for (auto it = pg_pool_sum_old.begin(); it != pg_pool_sum_old.end(); ++it) { update_one_pool_delta(cct, ts, it->first, it->second); } @@ -1627,181 +2271,6 @@ void PGMap::clear_delta() stamp_delta = utime_t(); } -void PGMap::print_summary(Formatter *f, ostream *out) const -{ - std::stringstream ss; - if (f) - f->open_array_section("pgs_by_state"); - - // list is descending numeric order (by count) - multimap state_by_count; // count -> state - for (ceph::unordered_map::const_iterator p = num_pg_by_state.begin(); - p != num_pg_by_state.end(); - ++p) { - state_by_count.insert(make_pair(p->second, p->first)); - } - for (multimap::reverse_iterator p = state_by_count.rbegin(); - p != state_by_count.rend(); - ++p) { - if (f) { - f->open_object_section("pgs_by_state_element"); - f->dump_string("state_name", pg_state_string(p->second)); - f->dump_unsigned("count", p->first); - f->close_section(); - } else { - ss.setf(std::ios::right); - ss << " " << std::setw(7) << p->first - << " " << pg_state_string(p->second) << "\n"; - ss.unsetf(std::ios::right); - } - } - if (f) - f->close_section(); - - if (f) { - f->dump_unsigned("version", version); - f->dump_unsigned("num_pgs", pg_stat.size()); - f->dump_unsigned("num_pools", pg_pool_sum.size()); - f->dump_unsigned("num_objects", pg_sum.stats.sum.num_objects); - f->dump_unsigned("data_bytes", pg_sum.stats.sum.num_bytes); - f->dump_unsigned("bytes_used", osd_sum.kb_used * 1024ull); - f->dump_unsigned("bytes_avail", osd_sum.kb_avail * 1024ull); - f->dump_unsigned("bytes_total", osd_sum.kb * 1024ull); - } else { - *out << " pgmap v" << version << ": " - << pg_stat.size() << " pgs, " << pg_pool_sum.size() << " pools, " - << prettybyte_t(pg_sum.stats.sum.num_bytes) << " data, " - << si_t(pg_sum.stats.sum.num_objects) << " objects\n"; - *out << " " - << kb_t(osd_sum.kb_used) << " used, " - << kb_t(osd_sum.kb_avail) << " / " - << kb_t(osd_sum.kb) << " avail\n"; - } - - - if (num_pg_active < num_pg) { - float p = (float)num_pg_active / (float)num_pg; - if (f) { - f->dump_float("active_pgs_ratio", p); - } else { - char b[20]; - snprintf(b, sizeof(b), "%.3lf", (1.0 - p) * 100.0); - *out << " " << b << "% pgs inactive\n"; - } - } - - list sl; - overall_recovery_summary(f, &sl); - if (!f && !sl.empty()) { - for (list::iterator p = sl.begin(); p != sl.end(); ++p) - *out << " " << *p << "\n"; - } - sl.clear(); - - if (!f) - *out << ss.str(); // pgs by state - - ostringstream ssr; - overall_recovery_rate_summary(f, &ssr); - if (!f && ssr.str().length()) - *out << "recovery io " << ssr.str() << "\n"; - - ssr.clear(); - ssr.str(""); - - overall_client_io_rate_summary(f, &ssr); - if (!f && ssr.str().length()) - *out << " client io " << ssr.str() << "\n"; - - ssr.clear(); - ssr.str(""); - - overall_cache_io_rate_summary(f, &ssr); - if (!f && ssr.str().length()) - *out << " cache io " << ssr.str() << "\n"; -} - -void PGMap::print_oneline_summary(Formatter *f, ostream *out) const -{ - std::stringstream ss; - - if (f) - f->open_array_section("num_pg_by_state"); - for (ceph::unordered_map::const_iterator p = num_pg_by_state.begin(); - p != num_pg_by_state.end(); - ++p) { - if (f) { - f->open_object_section("state"); - f->dump_string("name", pg_state_string(p->first)); - f->dump_unsigned("num", p->second); - f->close_section(); - } - if (p != num_pg_by_state.begin()) - ss << ", "; - ss << p->second << " " << pg_state_string(p->first); - } - if (f) - f->close_section(); - - string states = ss.str(); - if (out) - *out << "v" << version << ": " - << pg_stat.size() << " pgs: " - << states << "; " - << prettybyte_t(pg_sum.stats.sum.num_bytes) << " data, " - << kb_t(osd_sum.kb_used) << " used, " - << kb_t(osd_sum.kb_avail) << " / " - << kb_t(osd_sum.kb) << " avail"; - if (f) { - f->dump_unsigned("version", version); - f->dump_unsigned("num_pgs", pg_stat.size()); - f->dump_unsigned("num_bytes", pg_sum.stats.sum.num_bytes); - f->dump_unsigned("raw_bytes_used", osd_sum.kb_used << 10); - f->dump_unsigned("raw_bytes_avail", osd_sum.kb_avail << 10); - f->dump_unsigned("raw_bytes", osd_sum.kb << 10); - } - - // make non-negative; we can get negative values if osds send - // uncommitted stats and then "go backward" or if they are just - // buggy/wrong. - pool_stat_t pos_delta = pg_sum_delta; - pos_delta.floor(0); - if (pos_delta.stats.sum.num_rd || - pos_delta.stats.sum.num_wr) { - if (out) - *out << "; "; - if (pos_delta.stats.sum.num_rd) { - int64_t rd = (pos_delta.stats.sum.num_rd_kb << 10) / (double)stamp_delta; - if (out) - *out << pretty_si_t(rd) << "B/s rd, "; - if (f) - f->dump_unsigned("read_bytes_sec", rd); - } - if (pos_delta.stats.sum.num_wr) { - int64_t wr = (pos_delta.stats.sum.num_wr_kb << 10) / (double)stamp_delta; - if (out) - *out << pretty_si_t(wr) << "B/s wr, "; - if (f) - f->dump_unsigned("write_bytes_sec", wr); - } - int64_t iops = (pos_delta.stats.sum.num_rd + pos_delta.stats.sum.num_wr) / (double)stamp_delta; - if (out) - *out << pretty_si_t(iops) << "op/s"; - if (f) - f->dump_unsigned("io_sec", iops); - } - - list sl; - overall_recovery_summary(f, &sl); - if (out) - for (list::iterator p = sl.begin(); p != sl.end(); ++p) - *out << "; " << *p; - std::stringstream ssr; - overall_recovery_rate_summary(f, &ssr); - if (out && ssr.str().length()) - *out << "; " << ssr.str() << " recovering"; -} - void PGMap::generate_test_instances(list& o) { o.push_back(new PGMap); @@ -1822,7 +2291,7 @@ void PGMap::generate_test_instances(list& o) void PGMap::get_filtered_pg_stats(uint32_t state, int64_t poolid, int64_t osdid, bool primary, set& pgs) const { - for (ceph::unordered_map::const_iterator i = pg_stat.begin(); + for (auto i = pg_stat.begin(); i != pg_stat.end(); ++i) { if ((poolid >= 0) && (uint64_t(poolid) != i->first.pool())) @@ -1838,7 +2307,7 @@ void PGMap::get_filtered_pg_stats(uint32_t state, int64_t poolid, int64_t osdid, void PGMap::dump_filtered_pg_stats(Formatter *f, set& pgs) const { f->open_array_section("pg_stats"); - for (set::iterator i = pgs.begin(); i != pgs.end(); ++i) { + for (auto i = pgs.begin(); i != pgs.end(); ++i) { const pg_stat_t& st = pg_stat.at(*i); f->open_object_section("pg_stat"); f->dump_stream("pgid") << *i; @@ -1874,7 +2343,7 @@ void PGMap::dump_filtered_pg_stats(ostream& ss, set& pgs) const tab.define_column("LAST_DEEP_SCRUB", TextTable::LEFT, TextTable::RIGHT); tab.define_column("DEEP_SCRUB_STAMP", TextTable::LEFT, TextTable::RIGHT); - for (set::iterator i = pgs.begin(); i != pgs.end(); ++i) { + for (auto i = pgs.begin(); i != pgs.end(); ++i) { const pg_stat_t& st = pg_stat.at(*i); ostringstream reported; @@ -1907,266 +2376,563 @@ void PGMap::dump_filtered_pg_stats(ostream& ss, set& pgs) const ss << tab; } -int64_t PGMap::get_rule_avail(const OSDMap& osdmap, int ruleno) const -{ - map wm; - int r = osdmap.crush->get_rule_weight_osd_map(ruleno, &wm); - if (r < 0) { - return r; - } - if (wm.empty()) { - return 0; - } - float fratio; - if (osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS) && osdmap.get_full_ratio() > 0) { - fratio = osdmap.get_full_ratio(); - } else if (full_ratio > 0) { - fratio = full_ratio; - } else { - // this shouldn't really happen - fratio = g_conf->mon_osd_full_ratio; - if (fratio > 1.0) fratio /= 100; - } - int64_t min = -1; - for (map::iterator p = wm.begin(); p != wm.end(); ++p) { - ceph::unordered_map::const_iterator osd_info = - osd_stat.find(p->first); - if (osd_info != osd_stat.end()) { - if (osd_info->second.kb == 0 || p->second == 0) { - // osd must be out, hence its stats have been zeroed - // (unless we somehow managed to have a disk with size 0...) - // - // (p->second == 0), if osd weight is 0, no need to - // calculate proj below. - continue; - } - double unusable = (double)osd_info->second.kb * - (1.0 - fratio); - double avail = MAX(0.0, (double)osd_info->second.kb_avail - unusable); - avail *= 1024.0; - int64_t proj = (int64_t)(avail / (double)p->second); - if (min < 0 || proj < min) { - min = proj; - } +// Only called with a single bit set in "what" +static void note_stuck_detail( + int what, + mempool::pgmap::unordered_map& stuck_pgs, + int max_detail, + list > *detail) +{ + int n = 0; + for (auto p = stuck_pgs.begin(); + p != stuck_pgs.end(); + ++p) { + ostringstream ss; + utime_t since; + const char *whatname = 0; + switch (what) { + case PGMap::STUCK_INACTIVE: + since = p->second.last_active; + whatname = "inactive"; + break; + case PGMap::STUCK_UNCLEAN: + since = p->second.last_clean; + whatname = "unclean"; + break; + case PGMap::STUCK_DEGRADED: + since = p->second.last_undegraded; + whatname = "degraded"; + break; + case PGMap::STUCK_UNDERSIZED: + since = p->second.last_fullsized; + whatname = "undersized"; + break; + case PGMap::STUCK_STALE: + since = p->second.last_unstale; + whatname = "stale"; + break; + default: + ceph_abort(); + } + if (--max_detail == 0) { + ostringstream ss; + ss << (stuck_pgs.size() - n) << " more pgs are also stuck " << whatname; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + break; + } + ++n; + ss << "pg " << p->first << " is stuck " << whatname; + if (since == utime_t()) { + ss << " since forever"; } else { - dout(0) << "Cannot get stat of OSD " << p->first << dendl; + utime_t dur = ceph_clock_now() - since; + ss << " for " << dur; } + ss << ", current state " << pg_state_string(p->second.state) + << ", last acting " << p->second.acting; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); } - return min; -} - -inline std::string percentify(const float& a) { - std::stringstream ss; - if (a < 0.01) - ss << "0"; - else - ss << std::fixed << std::setprecision(2) << a; - return ss.str(); } -void PGMap::dump_pool_stats(const OSDMap &osd_map, stringstream *ss, - Formatter *f, bool verbose) const +static pair _warn_slow_request_histogram( + CephContext *cct, + const pow2_hist_t& h, + string suffix, + list >& summary, + list > *detail) { - TextTable tbl; + if (h.h.empty()) + return make_pair(0, 0); - if (f) { - f->open_array_section("pools"); - } else { - tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT); - tbl.define_column("ID", TextTable::LEFT, TextTable::LEFT); - if (verbose) { - tbl.define_column("QUOTA OBJECTS", TextTable::LEFT, TextTable::LEFT); - tbl.define_column("QUOTA BYTES", TextTable::LEFT, TextTable::LEFT); + unsigned warn = 0, error = 0; + float err_age = + cct->_conf->mon_osd_warn_op_age * cct->_conf->mon_osd_err_op_age_ratio; + for (unsigned i = h.h.size() - 1; i > 0; --i) { + float ub = (float)(1 << i) / 1000.0; + if (ub < cct->_conf->mon_osd_warn_op_age) + break; + if (h.h[i]) { + auto sev = HEALTH_WARN; + if (ub > err_age) { + sev = HEALTH_ERR; + error += h.h[i]; + } else { + warn += h.h[i]; + } + if (detail) { + ostringstream ss; + ss << h.h[i] << " ops are blocked > " << ub << " sec" << suffix; + detail->push_back(make_pair(sev, ss.str())); + } } + } + return make_pair(warn, error); +} - tbl.define_column("USED", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("%USED", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("MAX AVAIL", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); - if (verbose) { - tbl.define_column("DIRTY", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("READ", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("WRITE", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); +namespace { + enum class scrubbed_or_deepscrubbed_t { SCRUBBED, DEEPSCRUBBED }; + + void print_unscrubbed_detailed( + const std::pair &pg_entry, + list > *detail, + scrubbed_or_deepscrubbed_t how_scrubbed) + { + std::stringstream ss; + const auto& pg_stat(pg_entry.second); + + ss << "pg " << pg_entry.first << " is not "; + if (how_scrubbed == scrubbed_or_deepscrubbed_t::SCRUBBED) { + ss << "scrubbed, last_scrub_stamp " + << pg_stat.last_scrub_stamp; + } else if (how_scrubbed == scrubbed_or_deepscrubbed_t::DEEPSCRUBBED) { + ss << "deep-scrubbed, last_deep_scrub_stamp " + << pg_stat.last_deep_scrub_stamp; } + + detail->push_back(make_pair(HEALTH_WARN, ss.str())); } - map avail_by_rule; - for (map::const_iterator p = osd_map.get_pools().begin(); - p != osd_map.get_pools().end(); ++p) { - int64_t pool_id = p->first; - if ((pool_id < 0) || (pg_pool_sum.count(pool_id) == 0)) - continue; - const string& pool_name = osd_map.get_pool_name(pool_id); - const pool_stat_t &stat = pg_pool_sum.at(pool_id); + using pg_stat_map_t = const mempool::pgmap::unordered_map; - const pg_pool_t *pool = osd_map.get_pg_pool(pool_id); - int ruleno = osd_map.crush->find_rule(pool->get_crush_ruleset(), - pool->get_type(), - pool->get_size()); - int64_t avail; - float raw_used_rate; - if (avail_by_rule.count(ruleno) == 0) { - avail = get_rule_avail(osd_map, ruleno); - if (avail < 0) - avail = 0; - avail_by_rule[ruleno] = avail; - } else { - avail = avail_by_rule[ruleno]; - } - switch (pool->get_type()) { - case pg_pool_t::TYPE_REPLICATED: - avail /= pool->get_size(); - raw_used_rate = pool->get_size(); - break; - case pg_pool_t::TYPE_ERASURE: - { - auto& ecp = - osd_map.get_erasure_code_profile(pool->erasure_code_profile); - auto pm = ecp.find("m"); - auto pk = ecp.find("k"); - if (pm != ecp.end() && pk != ecp.end()) { - int k = atoi(pk->second.c_str()); - int m = atoi(pm->second.c_str()); - avail = avail * k / (m + k); - raw_used_rate = (float)(m + k) / k; - } else { - raw_used_rate = 0.0; + void print_unscrubbed_pgs( + pg_stat_map_t& pg_stats, + list > &summary, + list > *detail, + const CephContext* cct) + { + if (cct->_conf->mon_warn_not_scrubbed == 0 && + cct->_conf->mon_warn_not_deep_scrubbed == 0) + return; + + int pgs_count = 0; + const utime_t now = ceph_clock_now(); + for (const auto& pg_entry : pg_stats) { + const auto& pg_stat(pg_entry.second); + const utime_t time_since_ls = now - pg_stat.last_scrub_stamp; + const utime_t time_since_lds = now - pg_stat.last_deep_scrub_stamp; + + const int mon_warn_not_scrubbed = + cct->_conf->mon_warn_not_scrubbed + cct->_conf->mon_scrub_interval; + + const int mon_warn_not_deep_scrubbed = + cct->_conf->mon_warn_not_deep_scrubbed + cct->_conf->osd_deep_scrub_interval; + + bool not_scrubbed = (time_since_ls >= mon_warn_not_scrubbed && + cct->_conf->mon_warn_not_scrubbed != 0); + + bool not_deep_scrubbed = (time_since_lds >= mon_warn_not_deep_scrubbed && + cct->_conf->mon_warn_not_deep_scrubbed != 0); + + if (detail != nullptr) { + if (not_scrubbed) { + print_unscrubbed_detailed(pg_entry, + detail, + scrubbed_or_deepscrubbed_t::SCRUBBED); + } + if (not_deep_scrubbed) { + print_unscrubbed_detailed(pg_entry, + detail, + scrubbed_or_deepscrubbed_t::DEEPSCRUBBED); + } + } + if (not_scrubbed || not_deep_scrubbed) { + ++pgs_count; } } - break; - default: - assert(0 == "unrecognized pool type"); + + if (pgs_count > 0) { + std::stringstream ss; + ss << pgs_count << " unscrubbed pgs"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); } - if (f) { - f->open_object_section("pool"); - f->dump_string("name", pool_name); - f->dump_int("id", pool_id); - f->open_object_section("stats"); - } else { - tbl << pool_name - << pool_id; - if (verbose) { - if (pool->quota_max_objects == 0) - tbl << "N/A"; - else - tbl << si_t(pool->quota_max_objects); + } +} - if (pool->quota_max_bytes == 0) - tbl << "N/A"; - else - tbl << si_t(pool->quota_max_bytes); +void PGMap::get_health( + CephContext *cct, + const OSDMap& osdmap, + list >& summary, + list > *detail) const +{ + map note; + auto p = num_pg_by_state.begin(); + auto p_end = num_pg_by_state.end(); + for (; p != p_end; ++p) { + if (p->first & PG_STATE_STALE) + note["stale"] += p->second; + if (p->first & PG_STATE_DOWN) + note["down"] += p->second; + if (p->first & PG_STATE_UNDERSIZED) + note["undersized"] += p->second; + if (p->first & PG_STATE_DEGRADED) + note["degraded"] += p->second; + if (p->first & PG_STATE_INCONSISTENT) + note["inconsistent"] += p->second; + if (p->first & PG_STATE_PEERING) + note["peering"] += p->second; + if (p->first & PG_STATE_REPAIR) + note["repair"] += p->second; + if (p->first & PG_STATE_RECOVERING) + note["recovering"] += p->second; + if (p->first & PG_STATE_RECOVERY_WAIT) + note["recovery_wait"] += p->second; + if (p->first & PG_STATE_INCOMPLETE) + note["incomplete"] += p->second; + if (p->first & PG_STATE_BACKFILL_WAIT) + note["backfill_wait"] += p->second; + if (p->first & PG_STATE_BACKFILL) + note["backfilling"] += p->second; + if (p->first & PG_STATE_BACKFILL_TOOFULL) + note["backfill_toofull"] += p->second; + if (p->first & PG_STATE_RECOVERY_TOOFULL) + note["recovery_toofull"] += p->second; + } + + mempool::pgmap::unordered_map stuck_pgs; + utime_t now(ceph_clock_now()); + utime_t cutoff = now - utime_t(cct->_conf->mon_pg_stuck_threshold, 0); + uint64_t num_inactive_pgs = 0; + + if (detail) { + // we need to collect details of stuck pgs, first do a quick check + // whether this will yield any results + if (get_stuck_counts(cutoff, note)) { + + // there are stuck pgs. gather details for specified statuses + // only if we know that there are pgs stuck in that status + + if (note.find("stuck inactive") != note.end()) { + get_stuck_stats(PGMap::STUCK_INACTIVE, cutoff, stuck_pgs); + note["stuck inactive"] = stuck_pgs.size(); + num_inactive_pgs += stuck_pgs.size(); + note_stuck_detail(PGMap::STUCK_INACTIVE, stuck_pgs, + cct->_conf->mon_health_max_detail, detail); + stuck_pgs.clear(); + } + + if (note.find("stuck unclean") != note.end()) { + get_stuck_stats(PGMap::STUCK_UNCLEAN, cutoff, stuck_pgs); + note["stuck unclean"] = stuck_pgs.size(); + note_stuck_detail(PGMap::STUCK_UNCLEAN, stuck_pgs, + cct->_conf->mon_health_max_detail, detail); + stuck_pgs.clear(); } + if (note.find("stuck undersized") != note.end()) { + get_stuck_stats(PGMap::STUCK_UNDERSIZED, cutoff, stuck_pgs); + note["stuck undersized"] = stuck_pgs.size(); + note_stuck_detail(PGMap::STUCK_UNDERSIZED, stuck_pgs, + cct->_conf->mon_health_max_detail, detail); + stuck_pgs.clear(); + } + + if (note.find("stuck degraded") != note.end()) { + get_stuck_stats(PGMap::STUCK_DEGRADED, cutoff, stuck_pgs); + note["stuck degraded"] = stuck_pgs.size(); + note_stuck_detail(PGMap::STUCK_DEGRADED, stuck_pgs, + cct->_conf->mon_health_max_detail, detail); + stuck_pgs.clear(); + } + + if (note.find("stuck stale") != note.end()) { + get_stuck_stats(PGMap::STUCK_STALE, cutoff, stuck_pgs); + note["stuck stale"] = stuck_pgs.size(); + num_inactive_pgs += stuck_pgs.size(); + note_stuck_detail(PGMap::STUCK_STALE, stuck_pgs, + cct->_conf->mon_health_max_detail, detail); + } } - dump_object_stat_sum(tbl, f, stat.stats.sum, avail, raw_used_rate, verbose, pool); - if (f) - f->close_section(); // stats - else - tbl << TextTable::endrow; + } else { + get_stuck_counts(cutoff, note); + auto p = note.find("stuck inactive"); + if (p != note.end()) + num_inactive_pgs += p->second; + p = note.find("stuck stale"); + if (p != note.end()) + num_inactive_pgs += p->second; + } - if (f) - f->close_section(); // pool + if (cct->_conf->mon_pg_min_inactive > 0 && + num_inactive_pgs >= cct->_conf->mon_pg_min_inactive) { + ostringstream ss; + ss << num_inactive_pgs << " pgs are stuck inactive for more than " << cct->_conf->mon_pg_stuck_threshold << " seconds"; + summary.push_back(make_pair(HEALTH_ERR, ss.str())); } - if (f) - f->close_section(); - else { - assert(ss != nullptr); - *ss << "POOLS:\n"; - tbl.set_indent(4); - *ss << tbl; + + if (!note.empty()) { + for (auto p = note.begin(); p != note.end(); ++p) { + ostringstream ss; + ss << p->second << " pgs " << p->first; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + } + if (detail) { + int n = 0, more = 0; + int max = cct->_conf->mon_health_max_detail; + for (auto p = pg_stat.begin(); + p != pg_stat.end(); + ++p) { + if ((p->second.state & (PG_STATE_STALE | + PG_STATE_DOWN | + PG_STATE_UNDERSIZED | + PG_STATE_DEGRADED | + PG_STATE_INCONSISTENT | + PG_STATE_PEERING | + PG_STATE_REPAIR | + PG_STATE_RECOVERING | + PG_STATE_RECOVERY_WAIT | + PG_STATE_RECOVERY_TOOFULL | + PG_STATE_INCOMPLETE | + PG_STATE_BACKFILL_WAIT | + PG_STATE_BACKFILL | + PG_STATE_BACKFILL_TOOFULL)) && + stuck_pgs.count(p->first) == 0) { + if (max > 0) { + --max; + } else { + ++more; + continue; + } + ++n; + ostringstream ss; + ss << "pg " << p->first << " is " << pg_state_string(p->second.state); + ss << ", acting " << p->second.acting; + if (p->second.stats.sum.num_objects_unfound) + ss << ", " << p->second.stats.sum.num_objects_unfound << " unfound"; + if (p->second.state & PG_STATE_INCOMPLETE) { + const pg_pool_t *pi = osdmap.get_pg_pool(p->first.pool()); + if (pi && pi->min_size > 1) { + ss << " (reducing pool " << osdmap.get_pool_name(p->first.pool()) + << " min_size from " << (int)pi->min_size + << " may help; search ceph.com/docs for 'incomplete')"; + } + } + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + if (more) { + ostringstream ss; + ss << more << " more pgs are also unhealthy"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } } -} -void PGMap::dump_fs_stats( - stringstream *ss, Formatter *f, bool verbose) const -{ - if (f) { - f->open_object_section("stats"); - f->dump_int("total_bytes", osd_sum.kb * 1024ull); - f->dump_int("total_used_bytes", osd_sum.kb_used * 1024ull); - f->dump_int("total_avail_bytes", osd_sum.kb_avail * 1024ull); - if (verbose) { - f->dump_int("total_objects", pg_sum.stats.sum.num_objects); + // slow requests + if (cct->_conf->mon_osd_warn_op_age > 0 && + osd_sum.op_queue_age_hist.upper_bound() > cct->_conf->mon_osd_warn_op_age) { + auto sum = _warn_slow_request_histogram( + cct, osd_sum.op_queue_age_hist, "", summary, NULL); + if (sum.first > 0 || sum.second > 0) { + if (sum.first > 0) { + ostringstream ss; + ss << sum.first << " requests are blocked > " + << cct->_conf->mon_osd_warn_op_age + << " sec"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + } + if (sum.second > 0) { + ostringstream ss; + ss << sum.first << " requests are blocked > " + << (cct->_conf->mon_osd_warn_op_age * + cct->_conf->mon_osd_err_op_age_ratio) + << " sec"; + summary.push_back(make_pair(HEALTH_ERR, ss.str())); + } + + if (detail) { + unsigned num_warn = 0, num_err = 0; + // do per-osd warnings + for (auto p = osd_stat.begin(); + p != osd_stat.end(); + ++p) { + auto sum = _warn_slow_request_histogram( + cct, + p->second.op_queue_age_hist, + string(" on osd.") + stringify(p->first), + summary, detail); + if (sum.second) + ++num_err; + else if (sum.first) + ++num_warn; + } + if (num_err) { + ostringstream ss2; + ss2 << num_err << " osds have very slow requests"; + summary.push_back(make_pair(HEALTH_ERR, ss2.str())); + detail->push_back(make_pair(HEALTH_ERR, ss2.str())); + } + if (num_warn) { + ostringstream ss2; + ss2 << num_warn << " osds have slow requests"; + summary.push_back(make_pair(HEALTH_WARN, ss2.str())); + detail->push_back(make_pair(HEALTH_WARN, ss2.str())); + } + } } - f->close_section(); - } else { - assert(ss != nullptr); - TextTable tbl; - tbl.define_column("SIZE", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("%RAW USED", TextTable::LEFT, TextTable::RIGHT); - if (verbose) { - tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + } + + if (cct->_conf->mon_warn_osd_usage_min_max_delta) { + float max_osd_usage = 0.0, min_osd_usage = 1.0; + for (auto p = osd_stat.begin(); p != osd_stat.end(); ++p) { + // kb should never be 0, but avoid divide by zero in case of corruption + if (p->second.kb <= 0) + continue; + float usage = ((float)p->second.kb_used) / ((float)p->second.kb); + if (usage > max_osd_usage) + max_osd_usage = usage; + if (usage < min_osd_usage) + min_osd_usage = usage; + } + float diff = max_osd_usage - min_osd_usage; + if (diff > cct->_conf->mon_warn_osd_usage_min_max_delta) { + ostringstream ss; + ss << "difference between min (" << roundf(min_osd_usage*1000.0)/100.0 + << "%) and max (" << roundf(max_osd_usage*1000.0)/100.0 + << "%) osd usage " << roundf(diff*1000.0)/100.0 << "% > " + << roundf(cct->_conf->mon_warn_osd_usage_min_max_delta*1000.0)/100.0 + << " (mon_warn_osd_usage_min_max_delta)"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) + detail->push_back(make_pair(HEALTH_WARN, ss.str())); } - tbl << stringify(si_t(osd_sum.kb*1024)) - << stringify(si_t(osd_sum.kb_avail*1024)) - << stringify(si_t(osd_sum.kb_used*1024)); - float used = 0.0; - if (osd_sum.kb > 0) { - used = ((float)osd_sum.kb_used / osd_sum.kb); + } + + // recovery + list sl; + overall_recovery_summary(NULL, &sl); + for (auto p = sl.begin(); p != sl.end(); ++p) { + summary.push_back(make_pair(HEALTH_WARN, "recovery " + *p)); + if (detail) + detail->push_back(make_pair(HEALTH_WARN, "recovery " + *p)); + } + + // near-target max pools + auto& pools = osdmap.get_pools(); + for (auto p = pools.begin(); + p != pools.end(); ++p) { + if ((!p->second.target_max_objects && !p->second.target_max_bytes) || + !pg_pool_sum.count(p->first)) + continue; + bool nearfull = false; + const string& name = osdmap.get_pool_name(p->first); + const pool_stat_t& st = get_pg_pool_sum_stat(p->first); + uint64_t ratio = p->second.cache_target_full_ratio_micro + + ((1000000 - p->second.cache_target_full_ratio_micro) * + cct->_conf->mon_cache_target_full_warn_ratio); + if (p->second.target_max_objects && + (uint64_t)(st.stats.sum.num_objects - + st.stats.sum.num_objects_hit_set_archive) > + p->second.target_max_objects * (ratio / 1000000.0)) { + nearfull = true; + if (detail) { + ostringstream ss; + ss << "cache pool '" << name << "' with " + << si_t(st.stats.sum.num_objects) + << " objects at/near target max " + << si_t(p->second.target_max_objects) << " objects"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } } - tbl << percentify(used*100); - if (verbose) { - tbl << stringify(si_t(pg_sum.stats.sum.num_objects)); + if (p->second.target_max_bytes && + (uint64_t)(st.stats.sum.num_bytes - + st.stats.sum.num_bytes_hit_set_archive) > + p->second.target_max_bytes * (ratio / 1000000.0)) { + nearfull = true; + if (detail) { + ostringstream ss; + ss << "cache pool '" << name + << "' with " << si_t(st.stats.sum.num_bytes) + << "B at/near target max " + << si_t(p->second.target_max_bytes) << "B"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + if (nearfull) { + ostringstream ss; + ss << "'" << name << "' at/near target max"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); } - tbl << TextTable::endrow; - - *ss << "GLOBAL:\n"; - tbl.set_indent(4); - *ss << tbl; } -} -void PGMap::dump_object_stat_sum(TextTable &tbl, Formatter *f, - const object_stat_sum_t &sum, uint64_t avail, - float raw_used_rate, bool verbose, - const pg_pool_t *pool) -{ - float curr_object_copies_rate = 0.0; - if (sum.num_object_copies > 0) - curr_object_copies_rate = (float)(sum.num_object_copies - sum.num_objects_degraded) / sum.num_object_copies; - - if (f) { - f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10)); - f->dump_int("bytes_used", sum.num_bytes); - f->dump_unsigned("max_avail", avail); - f->dump_int("objects", sum.num_objects); - if (verbose) { - f->dump_int("quota_objects", pool->quota_max_objects); - f->dump_int("quota_bytes", pool->quota_max_bytes); - f->dump_int("dirty", sum.num_objects_dirty); - f->dump_int("rd", sum.num_rd); - f->dump_int("rd_bytes", sum.num_rd_kb * 1024ull); - f->dump_int("wr", sum.num_wr); - f->dump_int("wr_bytes", sum.num_wr_kb * 1024ull); - f->dump_int("raw_bytes_used", sum.num_bytes * raw_used_rate * curr_object_copies_rate); + // scrub + if (pg_sum.stats.sum.num_scrub_errors) { + ostringstream ss; + ss << pg_sum.stats.sum.num_scrub_errors << " scrub errors"; + summary.push_back(make_pair(HEALTH_ERR, ss.str())); + if (detail) { + detail->push_back(make_pair(HEALTH_ERR, ss.str())); } - } else { - tbl << stringify(si_t(sum.num_bytes)); - float used = 0.0; - if (avail) { - used = sum.num_bytes * curr_object_copies_rate; - used /= used + avail; - } else if (sum.num_bytes) { - used = 1.0; + } + + // pg skew + int num_in = osdmap.get_num_in_osds(); + int sum_pg_up = MAX(pg_sum.up, static_cast(pg_stat.size())); + if (num_in && cct->_conf->mon_pg_warn_min_per_osd > 0) { + int per = sum_pg_up / num_in; + if (per < cct->_conf->mon_pg_warn_min_per_osd && per) { + ostringstream ss; + ss << "too few PGs per OSD (" << per << " < min " << cct->_conf->mon_pg_warn_min_per_osd << ")"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) + detail->push_back(make_pair(HEALTH_WARN, ss.str())); } - tbl << percentify(used*100); - tbl << si_t(avail); - tbl << sum.num_objects; - if (verbose) { - tbl << stringify(si_t(sum.num_objects_dirty)) - << stringify(si_t(sum.num_rd)) - << stringify(si_t(sum.num_wr)) - << stringify(si_t(sum.num_bytes * raw_used_rate * curr_object_copies_rate)); + } + if (num_in && cct->_conf->mon_pg_warn_max_per_osd > 0) { + int per = sum_pg_up / num_in; + if (per > cct->_conf->mon_pg_warn_max_per_osd) { + ostringstream ss; + ss << "too many PGs per OSD (" << per << " > max " << cct->_conf->mon_pg_warn_max_per_osd << ")"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + if (!pg_stat.empty()) { + for (auto p = pg_pool_sum.begin(); + p != pg_pool_sum.end(); + ++p) { + const pg_pool_t *pi = osdmap.get_pg_pool(p->first); + if (!pi) + continue; // in case osdmap changes haven't propagated to PGMap yet + const string& name = osdmap.get_pool_name(p->first); + if (pi->get_pg_num() > pi->get_pgp_num() && + !(name.find(".DELETED") != string::npos && + cct->_conf->mon_fake_pool_delete)) { + ostringstream ss; + ss << "pool " << name << " pg_num " + << pi->get_pg_num() << " > pgp_num " << pi->get_pgp_num(); + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + int average_objects_per_pg = pg_sum.stats.sum.num_objects / pg_stat.size(); + if (average_objects_per_pg > 0 && + pg_sum.stats.sum.num_objects >= cct->_conf->mon_pg_warn_min_objects && + p->second.stats.sum.num_objects >= cct->_conf->mon_pg_warn_min_pool_objects) { + int objects_per_pg = p->second.stats.sum.num_objects / pi->get_pg_num(); + float ratio = (float)objects_per_pg / (float)average_objects_per_pg; + if (cct->_conf->mon_pg_warn_max_object_skew > 0 && + ratio > cct->_conf->mon_pg_warn_max_object_skew) { + ostringstream ss; + ss << "pool " << name << " has many more objects per pg than average (too few pgs?)"; + summary.push_back(make_pair(HEALTH_WARN, ss.str())); + if (detail) { + ostringstream ss; + ss << "pool " << name << " objects per pg (" + << objects_per_pg << ") is more than " << ratio << " times cluster average (" + << average_objects_per_pg << ")"; + detail->push_back(make_pair(HEALTH_WARN, ss.str())); + } + } + } } } -} + print_unscrubbed_pgs(pg_stat, summary, detail, cct); +} int process_pg_map_command( const string& orig_prefix, @@ -2548,7 +3314,9 @@ void PGMapUpdater::check_osd_map(const OSDMap::Incremental &osd_inc, for (const auto &p : osd_inc.new_weight) { if (p.second == CEPH_OSD_OUT) { dout(10) << __func__ << " osd." << p.first << " went OUT" << dendl; - pending_inc->stat_osd_out(p.first); + auto j = pg_map->osd_epochs.find(p.first); + if (j != pg_map->osd_epochs.end()) + pending_inc->stat_osd_out(p.first, j->second); } } @@ -2560,7 +3328,7 @@ void PGMapUpdater::check_osd_map(const OSDMap::Incremental &osd_inc, need_check_down_pg_osds->insert(p.first); // clear out the last_osd_report for this OSD - map::iterator report = last_osd_report->find(p.first); + auto report = last_osd_report->find(p.first); if (report != last_osd_report->end()) { last_osd_report->erase(report); } @@ -2568,7 +3336,7 @@ void PGMapUpdater::check_osd_map(const OSDMap::Incremental &osd_inc, // clear out osd_stat slow request histogram dout(20) << __func__ << " clearing osd." << p.first << " request histogram" << dendl; - pending_inc->stat_osd_down_up(p.first, *pg_map); + pending_inc->stat_osd_down_up(p.first, osd_inc.epoch, *pg_map); } if (p.second & CEPH_OSD_EXISTS) { @@ -2585,6 +3353,84 @@ void PGMapUpdater::check_osd_map(const OSDMap::Incremental &osd_inc, } } +void PGMapUpdater::check_osd_map( + CephContext *cct, + const OSDMap& osdmap, + const PGMap& pgmap, + PGMap::Incremental *pending_inc) +{ + for (auto& p : pgmap.osd_stat) { + if (!osdmap.exists(p.first)) { + // remove osd_stat + pending_inc->rm_stat(p.first); + } else if (osdmap.is_out(p.first)) { + // zero osd_stat + if (p.second.kb != 0) { + auto j = pgmap.osd_epochs.find(p.first); + if (j != pgmap.osd_epochs.end()) { + pending_inc->stat_osd_out(p.first, j->second); + } + } + } else if (!osdmap.is_up(p.first)) { + // zero the op_queue_age_hist + if (!p.second.op_queue_age_hist.empty()) { + pending_inc->stat_osd_down_up(p.first, osdmap.get_epoch(), pgmap); + } + } + } + + // deleted pgs (pools)? + for (auto& p : pgmap.pg_pool_sum) { + if (!osdmap.have_pg_pool(p.first)) { + ldout(cct, 10) << __func__ << " pool " << p.first << " gone, removing pgs" + << dendl; + for (auto& q : pgmap.pg_stat) { + if (q.first.pool() == (uint64_t)p.first) { + pending_inc->pg_remove.insert(q.first); + } + } + auto q = pending_inc->pg_stat_updates.begin(); + while (q != pending_inc->pg_stat_updates.end()) { + if (q->first.pool() == (uint64_t)p.first) { + q = pending_inc->pg_stat_updates.erase(q); + } else { + ++q; + } + } + } + } + + // new pgs (split or new pool)? + for (auto& p : osdmap.get_pools()) { + int64_t poolid = p.first; + const pg_pool_t& pi = p.second; + auto q = pgmap.num_pg_by_pool.find(poolid); + unsigned my_pg_num = 0; + if (q != pgmap.num_pg_by_pool.end()) + my_pg_num = q->second; + unsigned pg_num = pi.get_pg_num(); + if (my_pg_num != pg_num) { + for (unsigned ps = my_pg_num; ps < pg_num; ++ps) { + pg_t pgid(ps, poolid); + if (pending_inc->pg_stat_updates.count(pgid) == 0) { + pg_stat_t &stats = pending_inc->pg_stat_updates[pgid]; + stats.last_fresh = osdmap.get_modified(); + stats.last_active = osdmap.get_modified(); + stats.last_change = osdmap.get_modified(); + stats.last_peered = osdmap.get_modified(); + stats.last_clean = osdmap.get_modified(); + stats.last_unstale = osdmap.get_modified(); + stats.last_undegraded = osdmap.get_modified(); + stats.last_fullsized = osdmap.get_modified(); + stats.last_scrub_stamp = osdmap.get_modified(); + stats.last_deep_scrub_stamp = osdmap.get_modified(); + stats.last_clean_scrub_stamp = osdmap.get_modified(); + } + } + } + } +} + void PGMapUpdater::register_pg( const OSDMap &osd_map, pg_t pgid, epoch_t epoch, @@ -2686,7 +3532,7 @@ void PGMapUpdater::register_new_pgs( for (const auto &p : pools) { int64_t poolid = p.first; const pg_pool_t &pool = p.second; - int ruleno = osd_map.crush->find_rule(pool.get_crush_ruleset(), + int ruleno = osd_map.crush->find_rule(pool.get_crush_rule(), pool.get_type(), pool.get_size()); if (ruleno < 0 || !osd_map.crush->rule_exists(ruleno)) continue; @@ -2762,13 +3608,12 @@ void PGMapUpdater::update_creating_pgs( << dendl; unsigned changed = 0; - for (set::const_iterator p = pg_map.creating_pgs.begin(); + for (auto p = pg_map.creating_pgs.begin(); p != pg_map.creating_pgs.end(); ++p) { pg_t pgid = *p; pg_t on = pgid; - ceph::unordered_map::const_iterator q = - pg_map.pg_stat.find(pgid); + auto q = pg_map.pg_stat.find(pgid); assert(q != pg_map.pg_stat.end()); const pg_stat_t *s = &q->second; diff --git a/ceph/src/mon/PGMap.h b/ceph/src/mon/PGMap.h index 6231407b0..6d58e6b25 100644 --- a/ceph/src/mon/PGMap.h +++ b/ceph/src/mon/PGMap.h @@ -24,7 +24,9 @@ #include "common/debug.h" #include "common/TextTable.h" #include "osd/osd_types.h" +#include "include/mempool.h" #include +#include "mon/PGStatService.h" // FIXME: don't like including this here to get OSDMap::Incremental, maybe // PGMapUpdater needs its own header. @@ -32,72 +34,256 @@ namespace ceph { class Formatter; } -class PGMap { +class PGMapDigest { public: + MEMPOOL_CLASS_HELPERS(); + virtual ~PGMapDigest() {} + + mempool::pgmap::vector osd_last_seq; + + mutable std::map avail_space_by_rule; + + // aggregate state, populated by PGMap child + int64_t num_pg = 0, num_osd = 0; + int64_t num_pg_active = 0; + int64_t num_pg_unknown = 0; + mempool::pgmap::unordered_map pg_pool_sum; + mempool::pgmap::map num_pg_by_pool; + pool_stat_t pg_sum; + osd_stat_t osd_sum; + mempool::pgmap::unordered_map num_pg_by_state; + struct pg_count { + int32_t acting = 0; + int32_t up = 0; + int32_t primary = 0; + void encode(bufferlist& bl) const { + ::encode(acting, bl); + ::encode(up, bl); + ::encode(primary, bl); + } + void decode(bufferlist::iterator& p) { + ::decode(acting, p); + ::decode(up, p); + ::decode(primary, p); + } + }; + mempool::pgmap::unordered_map num_pg_by_osd; + + // recent deltas, and summation + /** + * keep track of last deltas for each pool, calculated using + * @p pg_pool_sum as baseline. + */ + mempool::pgmap::unordered_map > > per_pool_sum_deltas; + /** + * keep track of per-pool timestamp deltas, according to last update on + * each pool. + */ + mempool::pgmap::unordered_map per_pool_sum_deltas_stamps; + /** + * keep track of sum deltas, per-pool, taking into account any previous + * deltas existing in @p per_pool_sum_deltas. The utime_t as second member + * of the pair is the timestamp refering to the last update (i.e., the first + * member of the pair) for a given pool. + */ + mempool::pgmap::unordered_map > per_pool_sum_delta; + + pool_stat_t pg_sum_delta; + utime_t stamp_delta; + + + void print_summary(Formatter *f, ostream *out) const; + void print_oneline_summary(Formatter *f, ostream *out) const; + + void recovery_summary(Formatter *f, list *psl, + const pool_stat_t& delta_sum) const; + void overall_recovery_summary(Formatter *f, list *psl) const; + void pool_recovery_summary(Formatter *f, list *psl, + uint64_t poolid) const; + void recovery_rate_summary(Formatter *f, ostream *out, + const pool_stat_t& delta_sum, + utime_t delta_stamp) const; + void overall_recovery_rate_summary(Formatter *f, ostream *out) const; + void pool_recovery_rate_summary(Formatter *f, ostream *out, + uint64_t poolid) const; + /** + * Obtain a formatted/plain output for client I/O, source from stats for a + * given @p delta_sum pool over a given @p delta_stamp period of time. + */ + void client_io_rate_summary(Formatter *f, ostream *out, + const pool_stat_t& delta_sum, + utime_t delta_stamp) const; + /** + * Obtain a formatted/plain output for the overall client I/O, which is + * calculated resorting to @p pg_sum_delta and @p stamp_delta. + */ + void overall_client_io_rate_summary(Formatter *f, ostream *out) const; + /** + * Obtain a formatted/plain output for client I/O over a given pool + * with id @p pool_id. We will then obtain pool-specific data + * from @p per_pool_sum_delta. + */ + void pool_client_io_rate_summary(Formatter *f, ostream *out, + uint64_t poolid) const; + /** + * Obtain a formatted/plain output for cache tier IO, source from stats for a + * given @p delta_sum pool over a given @p delta_stamp period of time. + */ + void cache_io_rate_summary(Formatter *f, ostream *out, + const pool_stat_t& delta_sum, + utime_t delta_stamp) const; + /** + * Obtain a formatted/plain output for the overall cache tier IO, which is + * calculated resorting to @p pg_sum_delta and @p stamp_delta. + */ + void overall_cache_io_rate_summary(Formatter *f, ostream *out) const; + /** + * Obtain a formatted/plain output for cache tier IO over a given pool + * with id @p pool_id. We will then obtain pool-specific data + * from @p per_pool_sum_delta. + */ + void pool_cache_io_rate_summary(Formatter *f, ostream *out, + uint64_t poolid) const; + + virtual void dump_pool_stats_full(const OSDMap &osd_map, stringstream *ss, + Formatter *f, bool verbose) const; + void dump_fs_stats(stringstream *ss, Formatter *f, bool verbose) const; + static void dump_object_stat_sum(TextTable &tbl, Formatter *f, + const object_stat_sum_t &sum, + uint64_t avail, + float raw_used_rate, + bool verbose, const pg_pool_t *pool); + + size_t get_num_pg_by_osd(int osd) const { + auto p = num_pg_by_osd.find(osd); + if (p == num_pg_by_osd.end()) + return 0; + else + return p->second.acting; + } + int get_num_primary_pg_by_osd(int osd) const { + auto p = num_pg_by_osd.find(osd); + if (p == num_pg_by_osd.end()) + return 0; + else + return p->second.primary; + } + + ceph_statfs get_statfs() const { + ceph_statfs statfs; + // these are in KB. + statfs.kb = osd_sum.kb; + statfs.kb_used = osd_sum.kb_used; + statfs.kb_avail = osd_sum.kb_avail; + statfs.num_objects = pg_sum.stats.sum.num_objects; + return statfs; + } + + int64_t get_rule_avail(int ruleno) const { + auto i = avail_space_by_rule.find(ruleno); + if (i != avail_space_by_rule.end()) + return avail_space_by_rule[ruleno]; + else + return 0; + } + + // kill me post-luminous: + virtual float get_fallback_full_ratio() const { + return .95; + } + + uint64_t get_last_osd_stat_seq(int osd) { + if (osd < (int)osd_last_seq.size()) + return osd_last_seq[osd]; + return 0; + } + + void encode(bufferlist& bl, uint64_t features) const; + void decode(bufferlist::iterator& p); + void dump(Formatter *f) const; + static void generate_test_instances(list& ls); +}; +WRITE_CLASS_ENCODER(PGMapDigest::pg_count); +WRITE_CLASS_ENCODER_FEATURES(PGMapDigest); + +class PGMap : public PGMapDigest { +public: + MEMPOOL_CLASS_HELPERS(); + // the map version_t version; epoch_t last_osdmap_epoch; // last osdmap epoch i applied to the pgmap epoch_t last_pg_scan; // osdmap epoch - ceph::unordered_map pg_stat; - ceph::unordered_map osd_stat; - set full_osds; - set nearfull_osds; + mempool::pgmap::unordered_map osd_stat; + mempool::pgmap::unordered_map pg_stat; + mempool::pgmap::set full_osds; // for pre-luminous only + mempool::pgmap::set nearfull_osds; // for pre-luminous only float full_ratio; float nearfull_ratio; // mapping of osd to most recently reported osdmap epoch - ceph::unordered_map osd_epochs; + mempool::pgmap::unordered_map osd_epochs; class Incremental { public: + MEMPOOL_CLASS_HELPERS(); version_t version; - map pg_stat_updates; + mempool::pgmap::map pg_stat_updates; epoch_t osdmap_epoch; epoch_t pg_scan; // osdmap epoch - set pg_remove; + mempool::pgmap::set pg_remove; float full_ratio; float nearfull_ratio; utime_t stamp; private: - map osd_stat_updates; - set osd_stat_rm; + mempool::pgmap::map osd_stat_updates; + mempool::pgmap::set osd_stat_rm; - // mapping of osd to most recently reported osdmap epoch - map osd_epochs; + // mapping of osd to most recently reported osdmap epoch. + // 1:1 with osd_stat_updates. + mempool::pgmap::map osd_epochs; public: - const map &get_osd_stat_updates() const { + const mempool::pgmap::map &get_osd_stat_updates() const { return osd_stat_updates; } - const set &get_osd_stat_rm() const { + const mempool::pgmap::set &get_osd_stat_rm() const { return osd_stat_rm; } - const map &get_osd_epochs() const { + const mempool::pgmap::map &get_osd_epochs() const { return osd_epochs; } - void update_stat(int32_t osd, epoch_t epoch, const osd_stat_t &stat) { - osd_stat_updates[osd] = stat; + template + void update_stat(int32_t osd, epoch_t epoch, OsdStat&& stat) { + osd_stat_updates[osd] = std::forward(stat); osd_epochs[osd] = epoch; assert(osd_epochs.size() == osd_stat_updates.size()); } - void stat_osd_out(int32_t osd) { + void stat_osd_out(int32_t osd, epoch_t epoch) { // 0 the stats for the osd osd_stat_updates[osd] = osd_stat_t(); + // only fill in the epoch if the osd didn't already report htis + // epoch. that way we zero the stat but still preserve a reported + // new epoch... + if (!osd_epochs.count(osd)) + osd_epochs[osd] = epoch; + // ...and maintain our invariant. + assert(osd_epochs.size() == osd_stat_updates.size()); } - void stat_osd_down_up(int32_t osd, PGMap& pg_map) { + void stat_osd_down_up(int32_t osd, epoch_t epoch, const PGMap& pg_map) { // 0 the op_queue_age_hist for this osd - map::iterator p = osd_stat_updates.find(osd); + auto p = osd_stat_updates.find(osd); if (p != osd_stat_updates.end()) { p->second.op_queue_age_hist.clear(); return; } - ceph::unordered_map::iterator q = - pg_map.osd_stat.find(osd); + auto q = pg_map.osd_stat.find(osd); if (q != pg_map.osd_stat.end()) { osd_stat_t& t = osd_stat_updates[osd] = q->second; t.op_queue_age_hist.clear(); + osd_epochs[osd] = epoch; } } void rm_stat(int32_t osd) { @@ -116,65 +302,40 @@ public: // aggregate stats (soft state), generated by calc_stats() - ceph::unordered_map num_pg_by_state; - int64_t num_pg = 0, num_osd = 0; - int64_t num_pg_active = 0; - ceph::unordered_map pg_pool_sum; - pool_stat_t pg_sum; - osd_stat_t osd_sum; mutable epoch_t min_last_epoch_clean = 0; - ceph::unordered_map blocked_by_sum; - ceph::unordered_map > pg_by_osd; - ceph::unordered_map num_primary_pg_by_osd; + mempool::pgmap::unordered_map > pg_by_osd; + mempool::pgmap::unordered_map blocked_by_sum; + mempool::pgmap::list< pair > pg_sum_deltas; utime_t stamp; - // recent deltas, and summation - /** - * keep track of last deltas for each pool, calculated using - * @p pg_pool_sum as baseline. - */ - ceph::unordered_map > > per_pool_sum_deltas; - /** - * keep track of per-pool timestamp deltas, according to last update on - * each pool. - */ - ceph::unordered_map per_pool_sum_deltas_stamps; - /** - * keep track of sum deltas, per-pool, taking into account any previous - * deltas existing in @p per_pool_sum_deltas. The utime_t as second member - * of the pair is the timestamp refering to the last update (i.e., the first - * member of the pair) for a given pool. - */ - ceph::unordered_map > per_pool_sum_delta; - - list< pair > pg_sum_deltas; - pool_stat_t pg_sum_delta; - utime_t stamp_delta; - - void update_global_delta(CephContext *cct, - const utime_t ts, const pool_stat_t& pg_sum_old); - void update_pool_deltas(CephContext *cct, - const utime_t ts, - const ceph::unordered_map& pg_pool_sum_old); + void update_global_delta( + CephContext *cct, + const utime_t ts, const pool_stat_t& pg_sum_old); + void update_pool_deltas( + CephContext *cct, + const utime_t ts, + const mempool::pgmap::unordered_map& pg_pool_sum_old); void clear_delta(); void deleted_pool(int64_t pool) { pg_pool_sum.erase(pool); + num_pg_by_pool.erase(pool); per_pool_sum_deltas.erase(pool); per_pool_sum_deltas_stamps.erase(pool); per_pool_sum_delta.erase(pool); } private: - void update_delta(CephContext *cct, - const utime_t ts, - const pool_stat_t& old_pool_sum, - utime_t *last_ts, - const pool_stat_t& current_pool_sum, - pool_stat_t *result_pool_delta, - utime_t *result_ts_delta, - list > *delta_avg_list); + void update_delta( + CephContext *cct, + const utime_t ts, + const pool_stat_t& old_pool_sum, + utime_t *last_ts, + const pool_stat_t& current_pool_sum, + pool_stat_t *result_pool_delta, + utime_t *result_ts_delta, + mempool::pgmap::list > *delta_avg_list); void update_one_pool_delta(CephContext *cct, const utime_t ts, @@ -183,12 +344,10 @@ public: epoch_t calc_min_last_epoch_clean() const; - int64_t get_rule_avail(const OSDMap& osdmap, int ruleno) const; - public: - set creating_pgs; - map > > creating_pgs_by_osd_epoch; + mempool::pgmap::set creating_pgs; + mempool::pgmap::map > > creating_pgs_by_osd_epoch; // Bits that use to be enum StuckPG static const int STUCK_INACTIVE = (1<<0); @@ -236,30 +395,13 @@ public: stamp = s; } - size_t get_num_pg_by_osd(int osd) const { - ceph::unordered_map >::const_iterator p = pg_by_osd.find(osd); - if (p == pg_by_osd.end()) - return 0; - else - return p->second.size(); - } - pool_stat_t get_pg_pool_sum_stat(int64_t pool) const { - ceph::unordered_map::const_iterator p = - pg_pool_sum.find(pool); + auto p = pg_pool_sum.find(pool); if (p != pg_pool_sum.end()) return p->second; return pool_stat_t(); } - int get_num_primary_pg_by_osd(int osd) const { - assert(osd >= 0); - int num = 0; - auto it = num_primary_pg_by_osd.find(osd); - if (it != num_primary_pg_by_osd.end()) - num = it->second; - return num; - } void update_pg(pg_t pgid, bufferlist& bl); void remove_pg(pg_t pgid); @@ -275,35 +417,41 @@ public: void stat_pg_sub(const pg_t &pgid, const pg_stat_t &s, bool sameosds=false); void stat_pg_update(const pg_t pgid, pg_stat_t &prev, bufferlist::iterator& blp); - void stat_osd_add(const osd_stat_t &s); - void stat_osd_sub(const osd_stat_t &s); + void stat_osd_add(int osd, const osd_stat_t &s); + void stat_osd_sub(int osd, const osd_stat_t &s); void encode(bufferlist &bl, uint64_t features=-1) const; void decode(bufferlist::iterator &bl); + /// encode subset of our data to a PGMapDigest + void encode_digest(const OSDMap& osdmap, + bufferlist& bl, uint64_t features) const; + void dirty_all(Incremental& inc); + int64_t get_rule_avail(const OSDMap& osdmap, int ruleno) const; + void get_rules_avail(const OSDMap& osdmap, + std::map *avail_map) const; void dump(Formatter *f) const; - void dump_pool_stats(const OSDMap &osd_map, stringstream *ss, Formatter *f, - bool verbose) const; - void dump_fs_stats(stringstream *ss, Formatter *f, bool verbose) const; - static void dump_object_stat_sum(TextTable &tbl, Formatter *f, - const object_stat_sum_t &sum, - uint64_t avail, - float raw_used_rate, - bool verbose, const pg_pool_t *pool); void dump_basic(Formatter *f) const; void dump_pg_stats(Formatter *f, bool brief) const; void dump_pool_stats(Formatter *f) const; void dump_osd_stats(Formatter *f) const; void dump_delta(Formatter *f) const; void dump_filtered_pg_stats(Formatter *f, set& pgs) const; + void dump_pool_stats_full(const OSDMap &osd_map, stringstream *ss, + Formatter *f, bool verbose) const override { + get_rules_avail(osd_map, &avail_space_by_rule); + PGMapDigest::dump_pool_stats_full(osd_map, ss, f, verbose); + } - void dump_pg_stats_plain(ostream& ss, - const ceph::unordered_map& pg_stats, - bool brief) const; - void get_stuck_stats(int types, const utime_t cutoff, - ceph::unordered_map& stuck_pgs) const; + void dump_pg_stats_plain( + ostream& ss, + const mempool::pgmap::unordered_map& pg_stats, + bool brief) const; + void get_stuck_stats( + int types, const utime_t cutoff, + mempool::pgmap::unordered_map& stuck_pgs) const; bool get_stuck_counts(const utime_t cutoff, map& note) const; void dump_stuck(Formatter *f, int types, utime_t cutoff) const; void dump_stuck_plain(ostream& ss, int types, utime_t cutoff) const; @@ -328,58 +476,6 @@ public: void get_filtered_pg_stats(uint32_t state, int64_t poolid, int64_t osdid, bool primary, set& pgs) const; - void recovery_summary(Formatter *f, list *psl, - const pool_stat_t& delta_sum) const; - void overall_recovery_summary(Formatter *f, list *psl) const; - void pool_recovery_summary(Formatter *f, list *psl, - uint64_t poolid) const; - void recovery_rate_summary(Formatter *f, ostream *out, - const pool_stat_t& delta_sum, - utime_t delta_stamp) const; - void overall_recovery_rate_summary(Formatter *f, ostream *out) const; - void pool_recovery_rate_summary(Formatter *f, ostream *out, - uint64_t poolid) const; - /** - * Obtain a formatted/plain output for client I/O, source from stats for a - * given @p delta_sum pool over a given @p delta_stamp period of time. - */ - void client_io_rate_summary(Formatter *f, ostream *out, - const pool_stat_t& delta_sum, - utime_t delta_stamp) const; - /** - * Obtain a formatted/plain output for the overall client I/O, which is - * calculated resorting to @p pg_sum_delta and @p stamp_delta. - */ - void overall_client_io_rate_summary(Formatter *f, ostream *out) const; - /** - * Obtain a formatted/plain output for client I/O over a given pool - * with id @p pool_id. We will then obtain pool-specific data - * from @p per_pool_sum_delta. - */ - void pool_client_io_rate_summary(Formatter *f, ostream *out, - uint64_t poolid) const; - /** - * Obtain a formatted/plain output for cache tier IO, source from stats for a - * given @p delta_sum pool over a given @p delta_stamp period of time. - */ - void cache_io_rate_summary(Formatter *f, ostream *out, - const pool_stat_t& delta_sum, - utime_t delta_stamp) const; - /** - * Obtain a formatted/plain output for the overall cache tier IO, which is - * calculated resorting to @p pg_sum_delta and @p stamp_delta. - */ - void overall_cache_io_rate_summary(Formatter *f, ostream *out) const; - /** - * Obtain a formatted/plain output for cache tier IO over a given pool - * with id @p pool_id. We will then obtain pool-specific data - * from @p per_pool_sum_delta. - */ - void pool_cache_io_rate_summary(Formatter *f, ostream *out, - uint64_t poolid) const; - - void print_summary(Formatter *f, ostream *out) const; - void print_oneline_summary(Formatter *f, ostream *out) const; epoch_t get_min_last_epoch_clean() const { if (!min_last_epoch_clean) @@ -387,12 +483,24 @@ public: return min_last_epoch_clean; } + float get_fallback_full_ratio() const override { + if (full_ratio > 0) { + return full_ratio; + } + return .95; + } + + void get_health(CephContext *cct, + const OSDMap& osdmap, + list >& summary, + list > *detail) const; + static void generate_test_instances(list& o); }; WRITE_CLASS_ENCODER_FEATURES(PGMap::Incremental) WRITE_CLASS_ENCODER_FEATURES(PGMap) -inline ostream& operator<<(ostream& out, const PGMap& m) { +inline ostream& operator<<(ostream& out, const PGMapDigest& m) { m.print_oneline_summary(NULL, &out); return out; } @@ -416,6 +524,11 @@ public: PGMap *pg_map, PGMap::Incremental *pending_inc); + static void check_osd_map( + CephContext *cct, + const OSDMap &osdmap, + const PGMap& pg_map, + PGMap::Incremental *pending_inc); /** * check latest osdmap for new pgs to register */ @@ -467,4 +580,91 @@ namespace reweight { Formatter *f); } + +class PGMapStatService : virtual public PGStatService { +protected: + const PGMap& pgmap; +public: + PGMapStatService(const PGMap& o) + : pgmap(o) {} + + bool is_readable() const override { return true; } + + const pool_stat_t* get_pool_stat(int poolid) const override { + auto i = pgmap.pg_pool_sum.find(poolid); + if (i != pgmap.pg_pool_sum.end()) { + return &i->second; + } + return nullptr; + } + + const osd_stat_t& get_osd_sum() const override { return pgmap.osd_sum; } + + const osd_stat_t *get_osd_stat(int osd) const override { + auto i = pgmap.osd_stat.find(osd); + if (i == pgmap.osd_stat.end()) { + return nullptr; + } + return &i->second; + } + const mempool::pgmap::unordered_map& get_osd_stat() const override { + return pgmap.osd_stat; + } + float get_full_ratio() const override { return pgmap.full_ratio; } + float get_nearfull_ratio() const override { return pgmap.nearfull_ratio; } + + bool have_creating_pgs() const override { + return !pgmap.creating_pgs.empty(); + } + bool is_creating_pg(pg_t pgid) const override { + return pgmap.creating_pgs.count(pgid); + } + + epoch_t get_min_last_epoch_clean() const override { + return pgmap.get_min_last_epoch_clean(); + } + + bool have_full_osds() const override { return !pgmap.full_osds.empty(); } + bool have_nearfull_osds() const override { + return !pgmap.nearfull_osds.empty(); + } + + size_t get_num_pg_by_osd(int osd) const override { + return pgmap.get_num_pg_by_osd(osd); + } + ceph_statfs get_statfs() const override { + ceph_statfs statfs; + statfs.kb = pgmap.osd_sum.kb; + statfs.kb_used = pgmap.osd_sum.kb_used; + statfs.kb_avail = pgmap.osd_sum.kb_avail; + statfs.num_objects = pgmap.pg_sum.stats.sum.num_objects; + return statfs; + } + void print_summary(Formatter *f, ostream *out) const override { + pgmap.print_summary(f, out); + } + virtual void dump_info(Formatter *f) const override { + f->dump_object("pgmap", pgmap); + } + void dump_fs_stats(stringstream *ss, + Formatter *f, + bool verbose) const override { + pgmap.dump_fs_stats(ss, f, verbose); + } + void dump_pool_stats(const OSDMap& osdm, stringstream *ss, Formatter *f, + bool verbose) const override { + pgmap.dump_pool_stats_full(osdm, ss, f, verbose); + } + + int process_pg_command(const string& prefix, + const map& cmdmap, + const OSDMap& osdmap, + Formatter *f, + stringstream *ss, + bufferlist *odata) const override { + return process_pg_map_command(prefix, cmdmap, pgmap, osdmap, f, ss, odata); + } +}; + + #endif diff --git a/ceph/src/mon/PGMonitor.cc b/ceph/src/mon/PGMonitor.cc index 151468a58..7fdb5bd63 100644 --- a/ceph/src/mon/PGMonitor.cc +++ b/ceph/src/mon/PGMonitor.cc @@ -19,14 +19,11 @@ #include "Monitor.h" #include "OSDMonitor.h" #include "MonitorDBStore.h" +#include "PGStatService.h" #include "messages/MPGStats.h" #include "messages/MPGStatsAck.h" -#include "messages/MGetPoolStats.h" -#include "messages/MGetPoolStatsReply.h" -#include "messages/MStatfs.h" -#include "messages/MStatfsReply.h" #include "messages/MOSDPGCreate.h" #include "messages/MMonCommand.h" #include "messages/MOSDScrub.h" @@ -72,12 +69,17 @@ void PGMonitor::on_active() update_logger(); - if (mon->is_leader()) + if (mon->is_leader() && + mon->osdmon()->osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { mon->clog->info() << "pgmap " << pg_map; + } } void PGMonitor::update_logger() { + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + return; + } dout(10) << "update_logger" << dendl; mon->cluster_logger->set(l_cluster_osd_bytes, pg_map.osd_sum.kb * 1024ull); @@ -115,6 +117,9 @@ void PGMonitor::update_logger() void PGMonitor::tick() { if (!is_active()) return; + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + return; + } handle_osd_timeouts(); @@ -162,6 +167,19 @@ void PGMonitor::create_initial() void PGMonitor::update_from_paxos(bool *need_bootstrap) { + if (did_delete) + return; + + if (get_value("deleted")) { + did_delete = true; + dout(10) << __func__ << " deleted, clearing in-memory PGMap" << dendl; + pg_map = PGMap(); + pending_inc = PGMap::Incremental(); + pgservice.reset(); + last_osd_report.clear(); + return; + } + version_t version = get_last_committed(); if (version == pg_map.version) return; @@ -216,21 +234,13 @@ void PGMonitor::on_upgrade() void PGMonitor::upgrade_format() { unsigned current = 1; - assert(format_version <= current); - if (format_version == current) - return; - - dout(1) << __func__ << " to " << current << dendl; - - // upgrade by dirtying it all - pg_map.dirty_all(pending_inc); - - format_version = current; - propose_pending(); + assert(format_version == current); } void PGMonitor::post_paxos_update() { + if (did_delete) + return; dout(10) << __func__ << dendl; OSDMap& osdmap = mon->osdmon()->osdmap; if (mon->monmap->get_required_features().contains_all( @@ -250,6 +260,8 @@ void PGMonitor::handle_osd_timeouts() { if (!mon->is_leader()) return; + if (did_delete) + return; utime_t now(ceph_clock_now()); utime_t timeo(g_conf->mon_osd_report_timeout, 0); @@ -264,6 +276,9 @@ void PGMonitor::handle_osd_timeouts() void PGMonitor::create_pending() { + if (did_delete) + return; + do_delete = false; pending_inc = PGMap::Incremental(); pending_inc.version = pg_map.version + 1; if (pg_map.version == 0) { @@ -362,7 +377,7 @@ void PGMonitor::apply_pgmap_delta(bufferlist& bl) } pool_stat_t pg_sum_old = pg_map.pg_sum; - ceph::unordered_map pg_pool_sum_old; + mempool::pgmap::unordered_map pg_pool_sum_old; // pgs set deleted_pools; @@ -429,6 +444,32 @@ void PGMonitor::apply_pgmap_delta(bufferlist& bl) void PGMonitor::encode_pending(MonitorDBStore::TransactionRef t) { + if (did_delete) + return; + + string prefix = pgmap_meta_prefix; + if (do_delete) { + dout(1) << __func__ << " clearing pgmap data at v" << pending_inc.version + << dendl; + do_delete = false; + for (auto key : { "version", "stamp", "last_osdmap_epoch", + "last_pg_scan", "full_ratio", "nearfull_ratio" }) { + t->erase(prefix, key); + } + for (auto& p : pg_map.pg_stat) { + t->erase(prefix, stringify(p.first)); + } + for (auto& p : pg_map.osd_stat) { + t->erase(prefix, stringify(p.first)); + } + put_last_committed(t, pending_inc.version); + put_value(t, "deleted", 1); + return; + } + + assert(mon->osdmon()->osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS || + pending_inc.version == 1 /* rebuild-mondb.yaml case */); + version_t version = pending_inc.version; dout(10) << __func__ << " v " << version << dendl; assert(get_last_committed() + 1 == version); @@ -436,8 +477,6 @@ void PGMonitor::encode_pending(MonitorDBStore::TransactionRef t) uint64_t features = mon->get_quorum_con_features(); - string prefix = pgmap_meta_prefix; - t->put(prefix, "version", pending_inc.version); { bufferlist bl; @@ -519,17 +558,14 @@ version_t PGMonitor::get_trim_to() bool PGMonitor::preprocess_query(MonOpRequestRef op) { + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + return false; + } + op->mark_pgmon_event(__func__); PaxosServiceMessage *m = static_cast(op->get_req()); dout(10) << "preprocess_query " << *m << " from " << m->get_orig_source_inst() << dendl; switch (m->get_type()) { - case CEPH_MSG_STATFS: - handle_statfs(op); - return true; - - case MSG_GETPOOLSTATS: - return preprocess_getpoolstats(op); - case MSG_PGSTATS: return preprocess_pg_stats(op); @@ -545,6 +581,10 @@ bool PGMonitor::preprocess_query(MonOpRequestRef op) bool PGMonitor::prepare_update(MonOpRequestRef op) { + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + return false; + } + op->mark_pgmon_event(__func__); PaxosServiceMessage *m = static_cast(op->get_req()); dout(10) << "prepare_update " << *m << " from " << m->get_orig_source_inst() << dendl; @@ -561,85 +601,6 @@ bool PGMonitor::prepare_update(MonOpRequestRef op) } } -void PGMonitor::handle_statfs(MonOpRequestRef op) -{ - op->mark_pgmon_event(__func__); - MStatfs *statfs = static_cast(op->get_req()); - // check caps - MonSession *session = statfs->get_session(); - if (!session) - return; - - if (!session->is_capable("pg", MON_CAP_R)) { - dout(0) << "MStatfs received from entity with insufficient privileges " - << session->caps << dendl; - return; - } - - if (statfs->fsid != mon->monmap->fsid) { - dout(0) << "handle_statfs on fsid " << statfs->fsid - << " != " << mon->monmap->fsid << dendl; - return; - } - - - dout(10) << "handle_statfs " << *statfs - << " from " << statfs->get_orig_source() << dendl; - - // fill out stfs - MStatfsReply *reply = new MStatfsReply(mon->monmap->fsid, statfs->get_tid(), - get_last_committed()); - - // these are in KB. - reply->h.st.kb = pg_map.osd_sum.kb; - reply->h.st.kb_used = pg_map.osd_sum.kb_used; - reply->h.st.kb_avail = pg_map.osd_sum.kb_avail; - reply->h.st.num_objects = pg_map.pg_sum.stats.sum.num_objects; - - // reply - mon->send_reply(op, reply); -} - -bool PGMonitor::preprocess_getpoolstats(MonOpRequestRef op) -{ - op->mark_pgmon_event(__func__); - MGetPoolStats *m = static_cast(op->get_req()); - MGetPoolStatsReply *reply; - - MonSession *session = m->get_session(); - if (!session) - goto out; - if (!session->is_capable("pg", MON_CAP_R)) { - dout(0) << "MGetPoolStats received from entity with insufficient caps " - << session->caps << dendl; - goto out; - } - - if (m->fsid != mon->monmap->fsid) { - dout(0) << "preprocess_getpoolstats on fsid " << m->fsid << " != " << mon->monmap->fsid << dendl; - goto out; - } - - reply = new MGetPoolStatsReply(m->fsid, m->get_tid(), get_last_committed()); - - for (list::iterator p = m->pools.begin(); - p != m->pools.end(); - ++p) { - int64_t poolid = mon->osdmon()->osdmap.lookup_pg_pool_name(p->c_str()); - if (poolid < 0) - continue; - if (pg_map.pg_pool_sum.count(poolid) == 0) - continue; - reply->pool_stats[*p] = pg_map.pg_pool_sum[poolid]; - } - - mon->send_reply(op, reply); - -out: - return true; -} - - bool PGMonitor::preprocess_pg_stats(MonOpRequestRef op) { op->mark_pgmon_event(__func__); @@ -758,7 +719,7 @@ bool PGMonitor::prepare_pg_stats(MonOpRequestRef op) // osd stat if (mon->osdmon()->osdmap.is_in(from)) { - pending_inc.update_stat(from, stats->epoch, stats->osd_stat); + pending_inc.update_stat(from, stats->epoch, std::move(stats->osd_stat)); } else { pending_inc.update_stat(from, stats->epoch, osd_stat_t()); } @@ -844,6 +805,9 @@ void PGMonitor::check_osd_map(epoch_t epoch) if (mon->is_peon()) return; // whatever. + if (did_delete) + return; + if (pg_map.last_osdmap_epoch >= epoch) { dout(10) << __func__ << " already seen " << pg_map.last_osdmap_epoch << " >= " << epoch << dendl; @@ -862,11 +826,19 @@ void PGMonitor::check_osd_map(epoch_t epoch) return; } + const OSDMap& osdmap = mon->osdmon()->osdmap; + if (!did_delete && osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + // delete all my data + dout(1) << __func__ << " will clear pg_map data" << dendl; + do_delete = true; + propose_pending(); + return; + } + // osds that went up or down set need_check_down_pg_osds; // apply latest map(s) - const OSDMap& osdmap = mon->osdmon()->osdmap; epoch = std::max(epoch, osdmap.get_epoch()); for (epoch_t e = pg_map.last_osdmap_epoch+1; e <= epoch; @@ -938,16 +910,6 @@ epoch_t PGMonitor::send_pg_creates(int osd, Connection *con, epoch_t next) return last + 1; } -void PGMonitor::dump_info(Formatter *f) const -{ - f->open_object_section("pgmap"); - pg_map.dump(f); - f->close_section(); - - f->dump_unsigned("pgmap_first_committed", get_first_committed()); - f->dump_unsigned("pgmap_last_committed", get_last_committed()); -} - bool PGMonitor::preprocess_command(MonOpRequestRef op) { op->mark_pgmon_event(__func__); @@ -1000,12 +962,12 @@ bool PGMonitor::preprocess_command(MonOpRequestRef op) r = -ENOENT; goto reply; } - if (pg_map.pg_stat[pgid].acting_primary == -1) { + int osd = pg_map.pg_stat[pgid].acting_primary; + if (osd == -1) { ss << "pg " << pgid << " has no primary osd"; r = -EAGAIN; goto reply; } - int osd = pg_map.pg_stat[pgid].acting_primary; if (!mon->osdmon()->osdmap.is_up(osd)) { ss << "pg " << pgid << " primary osd." << osd << " not up"; r = -EAGAIN; @@ -1098,7 +1060,7 @@ bool PGMonitor::prepare_command(MonOpRequestRef op) goto update; } else if (prefix == "pg set_full_ratio" || prefix == "pg set_nearfull_ratio") { - if (mon->osdmon()->osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { ss << "please use the new luminous interfaces" << " ('osd set-full-ratio' and 'osd set-nearfull-ratio')"; r = -EPERM; @@ -1136,498 +1098,23 @@ update: return true; } -// Only called with a single bit set in "what" -static void note_stuck_detail(int what, - ceph::unordered_map& stuck_pgs, - list > *detail) -{ - for (ceph::unordered_map::iterator p = stuck_pgs.begin(); - p != stuck_pgs.end(); - ++p) { - ostringstream ss; - utime_t since; - const char *whatname = 0; - switch (what) { - case PGMap::STUCK_INACTIVE: - since = p->second.last_active; - whatname = "inactive"; - break; - case PGMap::STUCK_UNCLEAN: - since = p->second.last_clean; - whatname = "unclean"; - break; - case PGMap::STUCK_DEGRADED: - since = p->second.last_undegraded; - whatname = "degraded"; - break; - case PGMap::STUCK_UNDERSIZED: - since = p->second.last_fullsized; - whatname = "undersized"; - break; - case PGMap::STUCK_STALE: - since = p->second.last_unstale; - whatname = "stale"; - break; - default: - ceph_abort(); - } - ss << "pg " << p->first << " is stuck " << whatname; - if (since == utime_t()) { - ss << " since forever"; - } else { - utime_t dur = ceph_clock_now() - since; - ss << " for " << dur; - } - ss << ", current state " << pg_state_string(p->second.state) - << ", last acting " << p->second.acting; - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } -} - -int PGMonitor::_warn_slow_request_histogram(const pow2_hist_t& h, string suffix, - list >& summary, - list > *detail) const -{ - if (h.h.empty()) - return 0; - - unsigned sum = 0; - for (unsigned i = h.h.size() - 1; i > 0; --i) { - float ub = (float)(1 << i) / 1000.0; - if (ub < g_conf->mon_osd_max_op_age) - break; - ostringstream ss; - if (h.h[i]) { - ss << h.h[i] << " ops are blocked > " << ub << " sec" << suffix; - if (detail) - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - sum += h.h[i]; - } - } - return sum; -} - -namespace { - enum class scrubbed_or_deepscrubbed_t { SCRUBBED, DEEPSCRUBBED }; - - void print_unscrubbed_detailed(const std::pair &pg_entry, - list > *detail, - scrubbed_or_deepscrubbed_t how_scrubbed) { - - std::stringstream ss; - const auto& pg_stat(pg_entry.second); - - ss << "pg " << pg_entry.first << " is not "; - if (how_scrubbed == scrubbed_or_deepscrubbed_t::SCRUBBED) { - ss << "scrubbed, last_scrub_stamp " - << pg_stat.last_scrub_stamp; - } else if (how_scrubbed == scrubbed_or_deepscrubbed_t::DEEPSCRUBBED) { - ss << "deep-scrubbed, last_deep_scrub_stamp " - << pg_stat.last_deep_scrub_stamp; - } - - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - - - using pg_stat_map_t = const ceph::unordered_map; - - void print_unscrubbed_pgs(pg_stat_map_t& pg_stats, - list > &summary, - list > *detail, - const CephContext* cct) { - if (cct->_conf->mon_warn_not_scrubbed == 0 && - cct->_conf->mon_warn_not_deep_scrubbed == 0) - return; - - int pgs_count = 0; - const utime_t now = ceph_clock_now(); - for (const auto& pg_entry : pg_stats) { - const auto& pg_stat(pg_entry.second); - const utime_t time_since_ls = now - pg_stat.last_scrub_stamp; - const utime_t time_since_lds = now - pg_stat.last_deep_scrub_stamp; - - const int mon_warn_not_scrubbed = - cct->_conf->mon_warn_not_scrubbed + cct->_conf->mon_scrub_interval; - - const int mon_warn_not_deep_scrubbed = - cct->_conf->mon_warn_not_deep_scrubbed + cct->_conf->osd_deep_scrub_interval; - - bool not_scrubbed = (time_since_ls >= mon_warn_not_scrubbed && - cct->_conf->mon_warn_not_scrubbed != 0); - - bool not_deep_scrubbed = (time_since_lds >= mon_warn_not_deep_scrubbed && - cct->_conf->mon_warn_not_deep_scrubbed != 0); - - if (detail != nullptr) { - if (not_scrubbed) { - print_unscrubbed_detailed(pg_entry, - detail, - scrubbed_or_deepscrubbed_t::SCRUBBED); - } - if (not_deep_scrubbed) { - print_unscrubbed_detailed(pg_entry, - detail, - scrubbed_or_deepscrubbed_t::DEEPSCRUBBED); - } - } - if (not_scrubbed || not_deep_scrubbed) { - ++pgs_count; - } - } - - if (pgs_count > 0) { - std::stringstream ss; - ss << pgs_count << " unscrubbed pgs"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - } - - } -} - void PGMonitor::get_health(list >& summary, list > *detail, CephContext *cct) const { - map note; - ceph::unordered_map::const_iterator p = pg_map.num_pg_by_state.begin(); - ceph::unordered_map::const_iterator p_end = pg_map.num_pg_by_state.end(); - for (; p != p_end; ++p) { - if (p->first & PG_STATE_STALE) - note["stale"] += p->second; - if (p->first & PG_STATE_DOWN) - note["down"] += p->second; - if (p->first & PG_STATE_UNDERSIZED) - note["undersized"] += p->second; - if (p->first & PG_STATE_DEGRADED) - note["degraded"] += p->second; - if (p->first & PG_STATE_INCONSISTENT) - note["inconsistent"] += p->second; - if (p->first & PG_STATE_PEERING) - note["peering"] += p->second; - if (p->first & PG_STATE_REPAIR) - note["repair"] += p->second; - if (p->first & PG_STATE_RECOVERING) - note["recovering"] += p->second; - if (p->first & PG_STATE_RECOVERY_WAIT) - note["recovery_wait"] += p->second; - if (p->first & PG_STATE_INCOMPLETE) - note["incomplete"] += p->second; - if (p->first & PG_STATE_BACKFILL_WAIT) - note["backfill_wait"] += p->second; - if (p->first & PG_STATE_BACKFILL) - note["backfilling"] += p->second; - if (p->first & PG_STATE_BACKFILL_TOOFULL) - note["backfill_toofull"] += p->second; - if (p->first & PG_STATE_RECOVERY_TOOFULL) - note["recovery_toofull"] += p->second; - } - - ceph::unordered_map stuck_pgs; - utime_t now(ceph_clock_now()); - utime_t cutoff = now - utime_t(g_conf->mon_pg_stuck_threshold, 0); - uint64_t num_inactive_pgs = 0; - - if (detail) { - - // we need to collect details of stuck pgs, first do a quick check - // whether this will yield any results - if (pg_map.get_stuck_counts(cutoff, note)) { - - // there are stuck pgs. gather details for specified statuses - // only if we know that there are pgs stuck in that status - - if (note.find("stuck inactive") != note.end()) { - pg_map.get_stuck_stats(PGMap::STUCK_INACTIVE, cutoff, stuck_pgs); - note["stuck inactive"] = stuck_pgs.size(); - num_inactive_pgs += stuck_pgs.size(); - note_stuck_detail(PGMap::STUCK_INACTIVE, stuck_pgs, detail); - stuck_pgs.clear(); - } - - if (note.find("stuck unclean") != note.end()) { - pg_map.get_stuck_stats(PGMap::STUCK_UNCLEAN, cutoff, stuck_pgs); - note["stuck unclean"] = stuck_pgs.size(); - note_stuck_detail(PGMap::STUCK_UNCLEAN, stuck_pgs, detail); - stuck_pgs.clear(); - } - - if (note.find("stuck undersized") != note.end()) { - pg_map.get_stuck_stats(PGMap::STUCK_UNDERSIZED, cutoff, stuck_pgs); - note["stuck undersized"] = stuck_pgs.size(); - note_stuck_detail(PGMap::STUCK_UNDERSIZED, stuck_pgs, detail); - stuck_pgs.clear(); - } - - if (note.find("stuck degraded") != note.end()) { - pg_map.get_stuck_stats(PGMap::STUCK_DEGRADED, cutoff, stuck_pgs); - note["stuck degraded"] = stuck_pgs.size(); - note_stuck_detail(PGMap::STUCK_DEGRADED, stuck_pgs, detail); - stuck_pgs.clear(); - } - - if (note.find("stuck stale") != note.end()) { - pg_map.get_stuck_stats(PGMap::STUCK_STALE, cutoff, stuck_pgs); - note["stuck stale"] = stuck_pgs.size(); - num_inactive_pgs += stuck_pgs.size(); - note_stuck_detail(PGMap::STUCK_STALE, stuck_pgs, detail); - } - } - } else { - pg_map.get_stuck_counts(cutoff, note); - map::const_iterator p = note.find("stuck inactive"); - if (p != note.end()) - num_inactive_pgs += p->second; - p = note.find("stuck stale"); - if (p != note.end()) - num_inactive_pgs += p->second; - } - - if (g_conf->mon_pg_min_inactive > 0 && num_inactive_pgs >= g_conf->mon_pg_min_inactive) { - ostringstream ss; - ss << num_inactive_pgs << " pgs are stuck inactive for more than " << g_conf->mon_pg_stuck_threshold << " seconds"; - summary.push_back(make_pair(HEALTH_ERR, ss.str())); - } - - if (!note.empty()) { - for (map::iterator p = note.begin(); p != note.end(); ++p) { - ostringstream ss; - ss << p->second << " pgs " << p->first; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - } - if (detail) { - for (ceph::unordered_map::const_iterator p = pg_map.pg_stat.begin(); - p != pg_map.pg_stat.end(); - ++p) { - if ((p->second.state & (PG_STATE_STALE | - PG_STATE_DOWN | - PG_STATE_UNDERSIZED | - PG_STATE_DEGRADED | - PG_STATE_INCONSISTENT | - PG_STATE_PEERING | - PG_STATE_REPAIR | - PG_STATE_RECOVERING | - PG_STATE_RECOVERY_WAIT | - PG_STATE_RECOVERY_TOOFULL | - PG_STATE_INCOMPLETE | - PG_STATE_BACKFILL_WAIT | - PG_STATE_BACKFILL | - PG_STATE_BACKFILL_TOOFULL)) && - stuck_pgs.count(p->first) == 0) { - ostringstream ss; - ss << "pg " << p->first << " is " << pg_state_string(p->second.state); - ss << ", acting " << p->second.acting; - if (p->second.stats.sum.num_objects_unfound) - ss << ", " << p->second.stats.sum.num_objects_unfound << " unfound"; - if (p->second.state & PG_STATE_INCOMPLETE) { - const pg_pool_t *pi = mon->osdmon()->osdmap.get_pg_pool(p->first.pool()); - if (pi && pi->min_size > 1) { - ss << " (reducing pool " << mon->osdmon()->osdmap.get_pool_name(p->first.pool()) - << " min_size from " << (int)pi->min_size << " may help; search ceph.com/docs for 'incomplete')"; - } - } - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - } - } - - // slow requests - if (g_conf->mon_osd_max_op_age > 0 && - pg_map.osd_sum.op_queue_age_hist.upper_bound() > g_conf->mon_osd_max_op_age) { - unsigned sum = _warn_slow_request_histogram(pg_map.osd_sum.op_queue_age_hist, "", summary, NULL); - if (sum > 0) { - ostringstream ss; - ss << sum << " requests are blocked > " << g_conf->mon_osd_max_op_age << " sec"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - - if (detail) { - unsigned num_slow_osds = 0; - // do per-osd warnings - for (ceph::unordered_map::const_iterator p = pg_map.osd_stat.begin(); - p != pg_map.osd_stat.end(); - ++p) { - if (_warn_slow_request_histogram(p->second.op_queue_age_hist, - string(" on osd.") + stringify(p->first), - summary, detail)) - ++num_slow_osds; - } - ostringstream ss2; - ss2 << num_slow_osds << " osds have slow requests"; - summary.push_back(make_pair(HEALTH_WARN, ss2.str())); - detail->push_back(make_pair(HEALTH_WARN, ss2.str())); - } - } - } - - if (g_conf->mon_warn_osd_usage_min_max_delta) { - float max_osd_usage = 0.0, min_osd_usage = 1.0; - for (auto p = pg_map.osd_stat.begin(); p != pg_map.osd_stat.end(); ++p) { - // kb should never be 0, but avoid divide by zero in case of corruption - if (p->second.kb <= 0) - continue; - float usage = ((float)p->second.kb_used) / ((float)p->second.kb); - if (usage > max_osd_usage) - max_osd_usage = usage; - if (usage < min_osd_usage) - min_osd_usage = usage; - } - float diff = max_osd_usage - min_osd_usage; - if (diff > g_conf->mon_warn_osd_usage_min_max_delta) { - ostringstream ss; - ss << "difference between min (" << roundf(min_osd_usage*1000.0)/100.0 - << "%) and max (" << roundf(max_osd_usage*1000.0)/100.0 - << "%) osd usage " << roundf(diff*1000.0)/100.0 << "% > " - << roundf(g_conf->mon_warn_osd_usage_min_max_delta*1000.0)/100.0 - << " (mon_warn_osd_usage_min_max_delta)"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - if (detail) - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - - // recovery - list sl; - pg_map.overall_recovery_summary(NULL, &sl); - for (list::iterator p = sl.begin(); p != sl.end(); ++p) { - summary.push_back(make_pair(HEALTH_WARN, "recovery " + *p)); - if (detail) - detail->push_back(make_pair(HEALTH_WARN, "recovery " + *p)); - } - - // full/nearfull - if (!mon->osdmon()->osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + // legacy pre-luminous full/nearfull + if (mon->osdmon()->osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) { check_full_osd_health(summary, detail, pg_map.full_osds, "full", HEALTH_ERR); check_full_osd_health(summary, detail, pg_map.nearfull_osds, "near full", HEALTH_WARN); + pg_map.get_health(cct, mon->osdmon()->osdmap, summary, detail); } - - // near-target max pools - auto& pools = mon->osdmon()->osdmap.get_pools(); - for (auto p = pools.begin(); - p != pools.end(); ++p) { - if ((!p->second.target_max_objects && !p->second.target_max_bytes) || - !pg_map.pg_pool_sum.count(p->first)) - continue; - bool nearfull = false; - const string& name = mon->osdmon()->osdmap.get_pool_name(p->first); - const pool_stat_t& st = pg_map.get_pg_pool_sum_stat(p->first); - uint64_t ratio = p->second.cache_target_full_ratio_micro + - ((1000000 - p->second.cache_target_full_ratio_micro) * - g_conf->mon_cache_target_full_warn_ratio); - if (p->second.target_max_objects && (uint64_t)(st.stats.sum.num_objects - st.stats.sum.num_objects_hit_set_archive) > - p->second.target_max_objects * (ratio / 1000000.0)) { - nearfull = true; - if (detail) { - ostringstream ss; - ss << "cache pool '" << name << "' with " - << si_t(st.stats.sum.num_objects) - << " objects at/near target max " - << si_t(p->second.target_max_objects) << " objects"; - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - if (p->second.target_max_bytes && (uint64_t)(st.stats.sum.num_bytes - st.stats.sum.num_bytes_hit_set_archive) > - p->second.target_max_bytes * (ratio / 1000000.0)) { - nearfull = true; - if (detail) { - ostringstream ss; - ss << "cache pool '" << name - << "' with " << si_t(st.stats.sum.num_bytes) - << "B at/near target max " - << si_t(p->second.target_max_bytes) << "B"; - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - if (nearfull) { - ostringstream ss; - ss << "'" << name << "' at/near target max"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - - // scrub - if (pg_map.pg_sum.stats.sum.num_scrub_errors) { - ostringstream ss; - ss << pg_map.pg_sum.stats.sum.num_scrub_errors << " scrub errors"; - summary.push_back(make_pair(HEALTH_ERR, ss.str())); - if (detail) { - detail->push_back(make_pair(HEALTH_ERR, ss.str())); - } - } - - // pg skew - int num_in = mon->osdmon()->osdmap.get_num_in_osds(); - int sum_pg_up = MAX(pg_map.pg_sum.up, static_cast(pg_map.pg_stat.size())); - if (num_in && g_conf->mon_pg_warn_min_per_osd > 0) { - int per = sum_pg_up / num_in; - if (per < g_conf->mon_pg_warn_min_per_osd && per) { - ostringstream ss; - ss << "too few PGs per OSD (" << per << " < min " << g_conf->mon_pg_warn_min_per_osd << ")"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - if (detail) - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - if (num_in && g_conf->mon_pg_warn_max_per_osd > 0) { - int per = sum_pg_up / num_in; - if (per > g_conf->mon_pg_warn_max_per_osd) { - ostringstream ss; - ss << "too many PGs per OSD (" << per << " > max " << g_conf->mon_pg_warn_max_per_osd << ")"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - if (detail) - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - if (!pg_map.pg_stat.empty()) { - for (ceph::unordered_map::const_iterator p = pg_map.pg_pool_sum.begin(); - p != pg_map.pg_pool_sum.end(); - ++p) { - const pg_pool_t *pi = mon->osdmon()->osdmap.get_pg_pool(p->first); - if (!pi) - continue; // in case osdmap changes haven't propagated to PGMap yet - const string& name = mon->osdmon()->osdmap.get_pool_name(p->first); - if (pi->get_pg_num() > pi->get_pgp_num() && - !(name.find(".DELETED") != string::npos && - g_conf->mon_fake_pool_delete)) { - ostringstream ss; - ss << "pool " << name << " pg_num " - << pi->get_pg_num() << " > pgp_num " << pi->get_pgp_num(); - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - if (detail) - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - int average_objects_per_pg = pg_map.pg_sum.stats.sum.num_objects / pg_map.pg_stat.size(); - if (average_objects_per_pg > 0 && - pg_map.pg_sum.stats.sum.num_objects >= g_conf->mon_pg_warn_min_objects && - p->second.stats.sum.num_objects >= g_conf->mon_pg_warn_min_pool_objects) { - int objects_per_pg = p->second.stats.sum.num_objects / pi->get_pg_num(); - float ratio = (float)objects_per_pg / (float)average_objects_per_pg; - if (g_conf->mon_pg_warn_max_object_skew > 0 && - ratio > g_conf->mon_pg_warn_max_object_skew) { - ostringstream ss; - ss << "pool " << name << " has many more objects per pg than average (too few pgs?)"; - summary.push_back(make_pair(HEALTH_WARN, ss.str())); - if (detail) { - ostringstream ss; - ss << "pool " << name << " objects per pg (" - << objects_per_pg << ") is more than " << ratio << " times cluster average (" - << average_objects_per_pg << ")"; - detail->push_back(make_pair(HEALTH_WARN, ss.str())); - } - } - } - } - } - - print_unscrubbed_pgs(pg_map.pg_stat, summary, detail, cct); - } void PGMonitor::check_full_osd_health(list >& summary, list > *detail, - const set& s, const char *desc, + const mempool::pgmap::set& s, const char *desc, health_status_t sev) const { if (!s.empty()) { @@ -1648,6 +1135,10 @@ void PGMonitor::check_full_osd_health(list >& summa void PGMonitor::check_subs() { + if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { + return; + } + dout(10) << __func__ << dendl; const string type = "osd_pg_creates"; @@ -1680,3 +1171,95 @@ bool PGMonitor::check_sub(Subscription *sub) } return true; } + +class PGMonStatService : public MonPGStatService, public PGMapStatService { + PGMonitor *pgmon; +public: + PGMonStatService(const PGMap& o, PGMonitor *pgm) + : MonPGStatService(), PGMapStatService(o), pgmon(pgm) {} + + + bool is_readable() const override { return pgmon->is_readable(); } + + unsigned maybe_add_creating_pgs(epoch_t scan_epoch, + const mempool::osdmap::map& pools, + creating_pgs_t *pending_creates) const override + { + if (pgmap.last_pg_scan < scan_epoch) { + return 0; + } + unsigned added = 0; + for (auto& pgid : pgmap.creating_pgs) { + if (!pools.count(pgid.pool())) { + continue; + } + auto st = pgmap.pg_stat.find(pgid); + assert(st != pgmap.pg_stat.end()); + auto created = make_pair(st->second.created, + st->second.last_scrub_stamp); + // no need to add the pg, if it already exists in creating_pgs + if (pending_creates->pgs.emplace(pgid, created).second) { + added++; + } + } + return added; + } + void maybe_trim_creating_pgs(creating_pgs_t *creates) const override { + auto p = creates->pgs.begin(); + while (p != creates->pgs.end()) { + auto q = pgmap.pg_stat.find(p->first); + if (q != pgmap.pg_stat.end() && + !(q->second.state & PG_STATE_CREATING)) { + p = creates->pgs.erase(p); + creates->created_pools.insert(q->first.pool()); + } else { + ++p; + } + } + } + void dump_info(Formatter *f) const override { + f->dump_object("pgmap", pgmap); + f->dump_unsigned("pgmap_first_committed", pgmon->get_first_committed()); + f->dump_unsigned("pgmap_last_committed", pgmon->get_last_committed()); + } + int process_pg_command(const string& prefix, + const map& cmdmap, + const OSDMap& osdmap, + Formatter *f, + stringstream *ss, + bufferlist *odata) const override { + return process_pg_map_command(prefix, cmdmap, pgmap, osdmap, f, ss, odata); + } + + int reweight_by_utilization(const OSDMap &osd_map, + int oload, + double max_changef, + int max_osds, + bool by_pg, const set *pools, + bool no_increasing, + mempool::osdmap::map* new_weights, + std::stringstream *ss, + std::string *out_str, + Formatter *f) const override { + return reweight::by_utilization(osd_map, pgmap, oload, max_changef, + max_osds, by_pg, pools, no_increasing, + new_weights, ss, out_str, f); + } +}; + +MonPGStatService *PGMonitor::get_pg_stat_service() +{ + if (!pgservice) { + pgservice.reset(new PGMonStatService(pg_map, this)); + } + return pgservice.get(); +} + +PGMonitor::PGMonitor(Monitor *mn, Paxos *p, const string& service_name) + : PaxosService(mn, p, service_name), + pgmap_meta_prefix("pgmap_meta"), + pgmap_pg_prefix("pgmap_pg"), + pgmap_osd_prefix("pgmap_osd") +{} + +PGMonitor::~PGMonitor() = default; diff --git a/ceph/src/mon/PGMonitor.h b/ceph/src/mon/PGMonitor.h index 5f7650b03..5395c5bb3 100644 --- a/ceph/src/mon/PGMonitor.h +++ b/ceph/src/mon/PGMonitor.h @@ -32,16 +32,16 @@ using namespace std; #include "msg/Messenger.h" #include "mon/MonitorDBStore.h" -class MStatfs; -class MMonCommand; -class MGetPoolStats; - -class TextTable; class MPGStats; +class MonPGStatService; +class PGMonStatService; class PGMonitor : public PaxosService { -public: PGMap pg_map; + std::unique_ptr pgservice; + + bool do_delete = false; ///< propose deleting pgmap data + bool did_delete = false; ///< we already deleted pgmap data private: PGMap::Incremental pending_inc; @@ -78,9 +78,6 @@ private: struct C_Stats; - void handle_statfs(MonOpRequestRef op); - bool preprocess_getpoolstats(MonOpRequestRef op); - bool preprocess_command(MonOpRequestRef op); bool prepare_command(MonOpRequestRef op); @@ -90,13 +87,8 @@ private: epoch_t send_pg_creates(int osd, Connection *con, epoch_t next); public: - PGMonitor(Monitor *mn, Paxos *p, const string& service_name) - : PaxosService(mn, p, service_name), - pgmap_meta_prefix("pgmap_meta"), - pgmap_pg_prefix("pgmap_pg"), - pgmap_osd_prefix("pgmap_osd") - { } - ~PGMonitor() override { } + PGMonitor(Monitor *mn, Paxos *p, const string& service_name); + ~PGMonitor() override; void get_store_prefixes(set& s) override { s.insert(get_service_name()); @@ -124,8 +116,6 @@ public: void check_osd_map(epoch_t epoch); - void dump_info(Formatter *f) const; - int _warn_slow_request_histogram(const pow2_hist_t& h, string suffix, list >& summary, list > *detail) const; @@ -133,13 +123,17 @@ public: void get_health(list >& summary, list > *detail, CephContext *cct) const override; - void check_full_osd_health(list >& summary, - list > *detail, - const set& s, const char *desc, health_status_t sev) const; + void check_full_osd_health( + list >& summary, + list > *detail, + const mempool::pgmap::set& s, + const char *desc, health_status_t sev) const; void check_subs(); bool check_sub(Subscription *sub); + MonPGStatService *get_pg_stat_service(); + private: // no copying allowed PGMonitor(const PGMonitor &rhs); diff --git a/ceph/src/mon/PGStatService.h b/ceph/src/mon/PGStatService.h new file mode 100644 index 000000000..7c8cb004b --- /dev/null +++ b/ceph/src/mon/PGStatService.h @@ -0,0 +1,130 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 Greg Farnum/Red Hat + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +/** + * This service abstracts out the specific implementation providing information + * needed by parts of the Monitor based around PGStats. This'll make for + * an easier transition from the PGMonitor-based queries where we handle + * PGStats directly, to where we are getting information passed in from + * the Ceph Manager. + * + * This initial implementation cheats by wrapping a PGMap so we don't need + * to reimplement everything in one go. + */ + +#ifndef CEPH_PGSTATSERVICE_H +#define CEPH_PGSTATSERVICE_H + +struct creating_pgs_t; + +class PGStatService { +public: + PGStatService() {} + virtual ~PGStatService() {} + // FIXME: Kill this once we rip out PGMonitor post-luminous + /** returns true if the underlying data is readable. Always true + * post-luminous, but not when we are redirecting to the PGMonitor + */ + virtual bool is_readable() const { return true; } + virtual const pool_stat_t* get_pool_stat(int poolid) const = 0; + virtual const osd_stat_t& get_osd_sum() const { + ceph_abort(); + } + virtual const osd_stat_t *get_osd_stat(int osd) const { + ceph_abort(); + } + virtual const mempool::pgmap::unordered_map& get_osd_stat() const { + ceph_abort(); + } + virtual float get_full_ratio() const { + ceph_abort(); + } + virtual float get_nearfull_ratio() const { + ceph_abort(); + } + virtual bool have_creating_pgs() const { + ceph_abort(); + } + virtual bool is_creating_pg(pg_t pgid) const { + ceph_abort(); + } + virtual epoch_t get_min_last_epoch_clean() const { + ceph_abort(); + } + + virtual bool have_full_osds() const { + ceph_abort(); + } + virtual bool have_nearfull_osds() const { + ceph_abort(); + } + + virtual size_t get_num_pg_by_osd(int osd) const { + ceph_abort(); + } + virtual ceph_statfs get_statfs() const = 0; + virtual void print_summary(Formatter *f, ostream *out) const = 0; + virtual void dump_info(Formatter *f) const = 0; + virtual void dump_fs_stats(stringstream *ss, Formatter *f, bool verbose) const = 0; + virtual void dump_pool_stats(const OSDMap& osdm, stringstream *ss, Formatter *f, + bool verbose) const = 0; + + virtual int process_pg_command(const string& prefix, + const map& cmdmap, + const OSDMap& osdmap, + Formatter *f, + stringstream *ss, + bufferlist *odata) const { + ceph_abort(); + } + +}; + +class MonPGStatService : virtual public PGStatService { +public: + MonPGStatService() : PGStatService() {} + virtual ~MonPGStatService() {} + /** + * For upgrades. If the PGMap has newer data than the monitor's new + * creating_pgs (scan_epoch), insert them into the passed pending_creates. + */ + virtual unsigned maybe_add_creating_pgs(epoch_t scan_epoch, + const mempool::osdmap::map& pools, + creating_pgs_t *pending_creates) const { + ceph_abort(); + return 0; + } + /** + * For upgrades. If some PGs are created before all OSDs are luminous + * and start sending MOSDPGCreated, we need to be sync with pgmap + * + */ + virtual void maybe_trim_creating_pgs(creating_pgs_t *creates) const { + ceph_abort(); + } + virtual int reweight_by_utilization(const OSDMap &osd_map, + int oload, + double max_changef, + int max_osds, + bool by_pg, const set *pools, + bool no_increasing, + mempool::osdmap::map* new_weights, + std::stringstream *ss, + std::string *out_str, + Formatter *f) const { + ceph_abort(); + } +}; + +#endif diff --git a/ceph/src/mon/Paxos.cc b/ceph/src/mon/Paxos.cc index 8ba73118e..b1680d25a 100644 --- a/ceph/src/mon/Paxos.cc +++ b/ceph/src/mon/Paxos.cc @@ -17,6 +17,7 @@ #include "Monitor.h" #include "messages/MMonPaxos.h" +#include "mon/mon_types.h" #include "common/config.h" #include "include/assert.h" #include "include/stringify.h" @@ -1113,6 +1114,7 @@ void Paxos::handle_lease(MonOpRequestRef op) ack->last_committed = last_committed; ack->first_committed = first_committed; ack->lease_timestamp = ceph_clock_now(); + ::encode(mon->session_map.feature_map, ack->feature_map); lease->get_connection()->send_message(ack); // (re)set timeout event. @@ -1136,7 +1138,11 @@ void Paxos::handle_lease_ack(MonOpRequestRef op) } else if (acked_lease.count(from) == 0) { acked_lease.insert(from); - + if (ack->feature_map.length()) { + auto p = ack->feature_map.begin(); + FeatureMap& t = mon->quorum_feature_map[from]; + ::decode(t, p); + } if (acked_lease == mon->get_quorum()) { // yay! dout(10) << "handle_lease_ack from " << ack->get_source() @@ -1539,7 +1545,10 @@ MonitorDBStore::TransactionRef Paxos::get_pending_transaction() bool Paxos::trigger_propose() { - if (is_active()) { + if (plugged) { + dout(10) << __func__ << " plugged, not proposing now" << dendl; + return false; + } else if (is_active()) { dout(10) << __func__ << " active, proposing now" << dendl; propose_pending(); return true; diff --git a/ceph/src/mon/Paxos.h b/ceph/src/mon/Paxos.h index aef914d43..4ba84e6cc 100644 --- a/ceph/src/mon/Paxos.h +++ b/ceph/src/mon/Paxos.h @@ -350,7 +350,7 @@ private: * * On the Leader, it will be the Proposal Number picked by the Leader * itself. On the Peon, however, it will be the proposal sent by the Leader - * and it will only be updated iif its value is higher than the one + * and it will only be updated if its value is higher than the one * already known by the Peon. */ version_t accepted_pn; @@ -614,6 +614,11 @@ private: */ bool trimming; + /** + * true if we want trigger_propose to *not* propose (yet) + */ + bool plugged = false; + /** * @defgroup Paxos_h_callbacks Callback classes. * @{ @@ -707,7 +712,7 @@ private: * Once a Peon receives a collect message from the Leader it will reply * with its first and last committed versions, as well as information so * the Leader may know if its Proposal Number was, or was not, accepted by - * the Peon. The Peon will accept the Leader's Proposal Number iif it is + * the Peon. The Peon will accept the Leader's Proposal Number if it is * higher than the Peon's currently accepted Proposal Number. The Peon may * also inform the Leader of accepted but uncommitted values. * @@ -783,9 +788,9 @@ private: * * @pre We are the Leader * @pre We are on STATE_ACTIVE - * @post We commit, iif we are alone, or we send a message to each quorum + * @post We commit, if we are alone, or we send a message to each quorum * member - * @post We are on STATE_ACTIVE, iif we are alone, or on + * @post We are on STATE_ACTIVE, if we are alone, or on * STATE_UPDATING otherwise * * @param value The value being proposed to the quorum @@ -800,8 +805,8 @@ private: * * @pre We are a Peon * @pre We are on STATE_ACTIVE - * @post We are on STATE_UPDATING iif we accept the Leader's proposal - * @post We send a reply message to the Leader iif we accept its proposal + * @post We are on STATE_UPDATING if we accept the Leader's proposal + * @post We send a reply message to the Leader if we accept its proposal * * @invariant The received message is an operation of type OP_BEGIN * @@ -823,11 +828,11 @@ private: * * @pre We are the Leader * @pre We are on STATE_UPDATING - * @post We are on STATE_ACTIVE iif we received accepts from the full quorum - * @post We extended the lease iif we moved on to STATE_ACTIVE - * @post We are on STATE_UPDATING iif we didn't received accepts from the + * @post We are on STATE_ACTIVE if we received accepts from the full quorum + * @post We extended the lease if we moved on to STATE_ACTIVE + * @post We are on STATE_UPDATING if we didn't received accepts from the * full quorum - * @post We have committed iif we received accepts from a majority + * @post We have committed if we received accepts from a majority * * @invariant The received message is an operation of type OP_ACCEPT * @@ -924,7 +929,7 @@ private: * @post A lease timeout callback is set * @post Move to STATE_ACTIVE * @post Fire up all the callbacks waiting for STATE_ACTIVE - * @post Fire up all the callbacks waiting for readable iif we are readable + * @post Fire up all the callbacks waiting for readable if we are readable * @post Ack the lease to the Leader * * @invariant The received message is an operation of type OP_LEASE @@ -941,7 +946,7 @@ private: * fresh elections. * * @pre We are the Leader - * @post Cancel the Lease Ack timeout callback iif we receive acks from all + * @post Cancel the Lease Ack timeout callback if we receive acks from all * the quorum members * * @invariant The received message is an operation of type OP_LEASE_ACK @@ -1194,7 +1199,19 @@ public: return true; } - + + bool is_plugged() const { + return plugged; + } + void plug() { + assert(plugged == false); + plugged = true; + } + void unplug() { + assert(plugged == true); + plugged = false; + } + // read /** * @defgroup Paxos_h_read_funcs Read-related functions diff --git a/ceph/src/mon/PaxosService.cc b/ceph/src/mon/PaxosService.cc index a1c9df895..621f94214 100644 --- a/ceph/src/mon/PaxosService.cc +++ b/ceph/src/mon/PaxosService.cc @@ -88,37 +88,51 @@ bool PaxosService::dispatch(MonOpRequestRef op) } // update - if (prepare_update(op)) { - double delay = 0.0; - if (should_propose(delay)) { - if (delay == 0.0) { - propose_pending(); - } else { - // delay a bit - if (!proposal_timer) { - /** - * Callback class used to propose the pending value once the proposal_timer - * fires up. - */ - proposal_timer = new C_MonContext(mon, [this](int r) { - proposal_timer = 0; - if (r >= 0) - propose_pending(); - else if (r == -ECANCELED || r == -EAGAIN) - return; - else - assert(0 == "bad return value for proposal_timer"); - }); - dout(10) << " setting proposal_timer " << proposal_timer << " with delay of " << delay << dendl; - mon->timer.add_event_after(delay, proposal_timer); - } else { - dout(10) << " proposal_timer already set" << dendl; - } - } - } else { - dout(10) << " not proposing" << dendl; - } - } + if (!prepare_update(op)) { + // no changes made. + return true; + } + + if (need_immediate_propose) { + dout(10) << __func__ << " forced immediate propose" << dendl; + need_immediate_propose = false; + propose_pending(); + return true; + } + + double delay = 0.0; + if (!should_propose(delay)) { + dout(10) << " not proposing" << dendl; + return true; + } + + if (delay == 0.0) { + propose_pending(); + return true; + } + + // delay a bit + if (!proposal_timer) { + /** + * Callback class used to propose the pending value once the proposal_timer + * fires up. + */ + proposal_timer = new C_MonContext(mon, [this](int r) { + proposal_timer = 0; + if (r >= 0) { + propose_pending(); + } else if (r == -ECANCELED || r == -EAGAIN) { + return; + } else { + assert(0 == "bad return value for proposal_timer"); + } + }); + dout(10) << " setting proposal_timer " << proposal_timer + << " with delay of " << delay << dendl; + mon->timer.add_event_after(delay, proposal_timer); + } else { + dout(10) << " proposal_timer already set" << dendl; + } return true; } @@ -154,9 +168,9 @@ void PaxosService::post_refresh() bool PaxosService::should_propose(double& delay) { // simple default policy: quick startup, then some damping. - if (get_last_committed() <= 1) + if (get_last_committed() <= 1) { delay = 0.0; - else { + } else { utime_t now = ceph_clock_now(); if ((now - paxos->last_commit_time) > g_conf->paxos_propose_interval) delay = (double)g_conf->paxos_min_wait; diff --git a/ceph/src/mon/PaxosService.h b/ceph/src/mon/PaxosService.h index 5c6b2872b..ca7591584 100644 --- a/ceph/src/mon/PaxosService.h +++ b/ceph/src/mon/PaxosService.h @@ -53,7 +53,9 @@ class PaxosService { */ bool proposing; - protected: + bool need_immediate_propose = false; + +protected: /** * Services implementing us used to depend on the Paxos version, back when * each service would have a Paxos instance for itself. However, now we only @@ -187,7 +189,7 @@ private: * @remarks We only create a pending state we our Monitor is the Leader. * * @pre Paxos is active - * @post have_pending is true iif our Monitor is the Leader and Paxos is + * @post have_pending is true if our Monitor is the Leader and Paxos is * active */ void _active(); @@ -356,6 +358,15 @@ public: */ virtual bool should_propose(double &delay); + /** + * force an immediate propose. + * + * This is meant to be called from prepare_update(op). + */ + void force_immediate_propose() { + need_immediate_propose = true; + } + /** * @defgroup PaxosService_h_courtesy Courtesy functions * @@ -774,6 +785,18 @@ public: t->put(get_service_name(), key, bl); } + /** + * Put integer value @v into the key @p key. + * + * @param t A transaction to which we will add this put operation + * @param key The key to which we will add the value + * @param v An integer + */ + void put_value(MonitorDBStore::TransactionRef t, + const string& key, version_t v) { + t->put(get_service_name(), key, v); + } + /** * @} */ diff --git a/ceph/src/mon/Session.h b/ceph/src/mon/Session.h index 75051bf63..cb5946449 100644 --- a/ceph/src/mon/Session.h +++ b/ceph/src/mon/Session.h @@ -17,6 +17,7 @@ #include "include/xlist.h" #include "msg/msg_types.h" +#include "mon/mon_types.h" #include "auth/AuthServiceHandler.h" #include "osd/OSDMap.h" @@ -39,6 +40,8 @@ struct Subscription { struct MonSession : public RefCountedObject { ConnectionRef con; + int con_type = 0; + uint64_t con_features = 0; // zero if AnonConnection entity_inst_t inst; utime_t session_timeout; utime_t time_established; @@ -60,13 +63,20 @@ struct MonSession : public RefCountedObject { MonSession(const entity_inst_t& i, Connection *c) : RefCountedObject(g_ceph_context), - con(c), inst(i), closed(false), item(this), + con(c), + con_type(c->get_peer_type()), + con_features(0), + inst(i), closed(false), item(this), auid(0), global_id(0), osd_epoch(0), auth_handler(NULL), proxy_con(NULL), proxy_tid(0) { time_established = ceph_clock_now(); + if (c->get_messenger()) { + // only fill in features if this is a non-anonymous connection + con_features = c->get_features(); + } } ~MonSession() override { //generic_dout(0) << "~MonSession " << this << dendl; @@ -92,6 +102,7 @@ struct MonSessionMap { xlist sessions; map* > subs; multimap by_osd; + FeatureMap feature_map; // type -> features -> count MonSessionMap() {} ~MonSessionMap() { @@ -123,6 +134,9 @@ struct MonSessionMap { break; } } + if (s->con_features) { + feature_map.rm(s->con_type, s->con_features); + } s->closed = true; s->put(); } @@ -133,6 +147,9 @@ struct MonSessionMap { sessions.push_back(&s->item); if (i.name.is_osd()) by_osd.insert(pair(i.name.num(), s)); + if (s->con_features) { + feature_map.add(s->con_type, s->con_features); + } s->get(); // caller gets a ref return s; } diff --git a/ceph/src/mon/mon_types.h b/ceph/src/mon/mon_types.h index c34e87268..883f4669e 100644 --- a/ceph/src/mon/mon_types.h +++ b/ceph/src/mon/mon_types.h @@ -15,12 +15,13 @@ #ifndef CEPH_MON_TYPES_H #define CEPH_MON_TYPES_H +#include + #include "include/utime.h" #include "include/util.h" #include "common/Formatter.h" #include "common/bit_str.h" #include "include/Context.h" -#include "mon/MonOpRequest.h" #define PAXOS_PGMAP 0 // before osd, for pg kick to behave #define PAXOS_MDSMAP 1 @@ -29,7 +30,8 @@ #define PAXOS_MONMAP 4 #define PAXOS_AUTH 5 #define PAXOS_MGR 6 -#define PAXOS_NUM 7 +#define PAXOS_MGRSTAT 7 +#define PAXOS_NUM 8 inline const char *get_paxos_name(int p) { switch (p) { @@ -40,12 +42,73 @@ inline const char *get_paxos_name(int p) { case PAXOS_LOG: return "logm"; case PAXOS_AUTH: return "auth"; case PAXOS_MGR: return "mgr"; + case PAXOS_MGRSTAT: return "mgrstat"; default: ceph_abort(); return 0; } } #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012" +// map of entity_type -> features -> count +struct FeatureMap { + std::map> m; + + void add(uint32_t type, uint64_t features) { + m[type][features]++; + } + + void rm(uint32_t type, uint64_t features) { + auto p = m.find(type); + assert(p != m.end()); + auto q = p->second.find(features); + assert(q != p->second.end()); + if (--q->second == 0) { + p->second.erase(q); + if (p->second.empty()) { + m.erase(p); + } + } + } + + FeatureMap& operator+=(const FeatureMap& o) { + for (auto& p : o.m) { + auto &v = m[p.first]; + for (auto& q : p.second) { + v[q.first] += q.second; + } + } + return *this; + } + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(m, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& p) { + DECODE_START(1, p); + ::decode(m, p); + DECODE_FINISH(p); + } + + void dump(Formatter *f) const { + for (auto& p : m) { + f->open_object_section(ceph_entity_type_name(p.first)); + for (auto& q : p.second) { + f->open_object_section("group"); + f->dump_unsigned("features", q.first); + f->dump_string("release", ceph_release_name( + ceph_release_from_features(q.first))); + f->dump_unsigned("num", q.second); + f->close_section(); + } + f->close_section(); + } + } +}; +WRITE_CLASS_ENCODER(FeatureMap) + /** * leveldb store stats * @@ -211,32 +274,6 @@ static inline ostream& operator<<(ostream& out, const ScrubResult& r) { /// for information like os, kernel, hostname, memory info, cpu model. typedef map Metadata; -struct C_MonOp : public Context -{ - MonOpRequestRef op; - - explicit C_MonOp(MonOpRequestRef o) : - op(o) { } - - void finish(int r) override { - if (op && r == -ECANCELED) { - op->mark_event("callback canceled"); - } else if (op && r == -EAGAIN) { - op->mark_event("callback retry"); - } else if (op && r == 0) { - op->mark_event("callback finished"); - } - _finish(r); - } - - void mark_op_event(const string &event) { - if (op) - op->mark_event_string(event); - } - - virtual void _finish(int r) = 0; -}; - namespace ceph { namespace features { namespace mon { diff --git a/ceph/src/msg/DispatchQueue.h b/ceph/src/msg/DispatchQueue.h index e07e5fbbe..556988193 100644 --- a/ceph/src/msg/DispatchQueue.h +++ b/ceph/src/msg/DispatchQueue.h @@ -20,7 +20,6 @@ #include #include "include/assert.h" #include "include/xlist.h" -#include "include/atomic.h" #include "common/Mutex.h" #include "common/Cond.h" #include "common/Thread.h" diff --git a/ceph/src/msg/Message.cc b/ceph/src/msg/Message.cc index 5579e3482..8232ba39c 100644 --- a/ceph/src/msg/Message.cc +++ b/ceph/src/msg/Message.cc @@ -168,6 +168,7 @@ using namespace std; #include "messages/MMgrReport.h" #include "messages/MMgrOpen.h" #include "messages/MMgrConfigure.h" +#include "messages/MMonMgrReport.h" #include "messages/MLock.h" @@ -746,6 +747,10 @@ Message *decode_message(CephContext *cct, int crcflags, m = new MMgrBeacon(); break; + case MSG_MON_MGR_REPORT: + m = new MMonMgrReport(); + break; + case MSG_MGR_MAP: m = new MMgrMap(); break; diff --git a/ceph/src/msg/Message.h b/ceph/src/msg/Message.h index b3a836c12..b7220e2de 100644 --- a/ceph/src/msg/Message.h +++ b/ceph/src/msg/Message.h @@ -196,6 +196,8 @@ // *** ceph-mon(MgrMonitor) -> ceph-mgr #define MSG_MGR_DIGEST 0x705 +// *** cephmgr -> ceph-mon +#define MSG_MON_MGR_REPORT 0x706 // ====================================================== diff --git a/ceph/src/msg/async/AsyncConnection.cc b/ceph/src/msg/async/AsyncConnection.cc index 8eec59684..f7e8fff0f 100644 --- a/ceph/src/msg/async/AsyncConnection.cc +++ b/ceph/src/msg/async/AsyncConnection.cc @@ -122,9 +122,9 @@ AsyncConnection::AsyncConnection(CephContext *cct, AsyncMessenger *m, DispatchQu Worker *w) : Connection(cct, m), delay_state(NULL), async_msgr(m), conn_id(q->get_id()), logger(w->get_perf_counter()), global_seq(0), connect_seq(0), peer_global_seq(0), - out_seq(0), ack_left(0), in_seq(0), state(STATE_NONE), state_after_send(STATE_NONE), port(-1), + state(STATE_NONE), state_after_send(STATE_NONE), port(-1), dispatch_queue(q), can_write(WriteStatus::NOWRITE), - open_write(false), keepalive(false), recv_buf(NULL), + keepalive(false), recv_buf(NULL), recv_max_prefetch(MAX(msgr->cct->_conf->ms_tcp_prefetch_max_size, TCP_PREFETCH_MIN_SIZE)), recv_start(0), recv_end(0), last_active(ceph::coarse_mono_clock::now()), @@ -203,6 +203,7 @@ ssize_t AsyncConnection::_try_send(bool more) } } + assert(center->in_thread()); ssize_t r = cs.send(outcoming_bl, more); if (r < 0) { ldout(async_msgr->cct, 1) << __func__ << " send error: " << cpp_strerror(r) << dendl; @@ -213,21 +214,13 @@ ssize_t AsyncConnection::_try_send(bool more) << " remaining bytes " << outcoming_bl.length() << dendl; if (!open_write && is_queued()) { - if (center->in_thread()) { - center->create_file_event(cs.fd(), EVENT_WRITABLE, write_handler); - open_write = true; - } else { - center->dispatch_event_external(write_handler); - } + center->create_file_event(cs.fd(), EVENT_WRITABLE, write_handler); + open_write = true; } if (open_write && !is_queued()) { - if (center->in_thread()) { - center->delete_file_event(cs.fd(), EVENT_WRITABLE); - open_write = false; - } else { - center->dispatch_event_external(write_handler); - } + center->delete_file_event(cs.fd(), EVENT_WRITABLE); + open_write = false; if (state_after_send != STATE_NONE) center->dispatch_event_external(read_handler); } @@ -336,6 +329,7 @@ void AsyncConnection::process() bool need_dispatch_writer = false; std::lock_guard l(lock); last_active = ceph::coarse_mono_clock::now(); + auto recv_start_time = ceph::mono_clock::now(); do { ldout(async_msgr->cct, 20) << __func__ << " prev state is " << get_state_name(prev_state) << dendl; prev_state = state; @@ -734,7 +728,7 @@ void AsyncConnection::process() // side queueing because messages can't be renumbered, but the (kernel) client will // occasionally pull a message out of the sent queue to send elsewhere. in that case // it doesn't matter if we "got" it or not. - uint64_t cur_seq = in_seq.read(); + uint64_t cur_seq = in_seq; if (message->get_seq() <= cur_seq) { ldout(async_msgr->cct,0) << __func__ << " got old message " << message->get_seq() << " <= " << cur_seq << " " << message << " " << *message @@ -766,13 +760,13 @@ void AsyncConnection::process() #endif // note last received message. - in_seq.set(message->get_seq()); + in_seq = message->get_seq(); ldout(async_msgr->cct, 5) << " rx " << message->get_source() << " seq " << message->get_seq() << " " << message << " " << *message << dendl; if (!policy.lossy) { - ack_left.inc(); + ack_left++; need_dispatch_writer = true; } state = STATE_OPEN; @@ -781,6 +775,8 @@ void AsyncConnection::process() logger->inc(l_msgr_recv_bytes, cur_msg_size + sizeof(ceph_msg_header) + sizeof(ceph_msg_footer)); async_msgr->ms_fast_preprocess(message); + auto fast_dispatch_time = ceph::mono_clock::now(); + logger->tinc(l_msgr_running_recv_time, fast_dispatch_time - recv_start_time); if (delay_state) { utime_t release = message->get_recv_stamp(); double delay_period = 0; @@ -794,6 +790,9 @@ void AsyncConnection::process() } else if (async_msgr->ms_can_fast_dispatch(message)) { lock.unlock(); dispatch_queue->fast_dispatch(message); + recv_start_time = ceph::mono_clock::now(); + logger->tinc(l_msgr_running_fast_dispatch_time, + recv_start_time - fast_dispatch_time); lock.lock(); } else { dispatch_queue->enqueue(message, message->get_priority(), conn_id); @@ -845,6 +844,8 @@ void AsyncConnection::process() if (need_dispatch_writer && is_connected()) center->dispatch_event_external(write_handler); + + logger->tinc(l_msgr_running_recv_time, ceph::mono_clock::now() - recv_start_time); return; fail: @@ -1134,7 +1135,7 @@ ssize_t AsyncConnection::_process_connection() newly_acked_seq = *((uint64_t*)state_buffer); ldout(async_msgr->cct, 2) << __func__ << " got newly_acked_seq " << newly_acked_seq - << " vs out_seq " << out_seq.read() << dendl; + << " vs out_seq " << out_seq << dendl; discard_requeued_up_to(newly_acked_seq); //while (newly_acked_seq > out_seq.read()) { // Message *m = _get_next_outgoing(NULL); @@ -1147,7 +1148,7 @@ ssize_t AsyncConnection::_process_connection() //} bufferlist bl; - uint64_t s = in_seq.read(); + uint64_t s = in_seq; bl.append((char*)&s, sizeof(s)); r = try_send(bl); if (r == 0) { @@ -1418,6 +1419,8 @@ int AsyncConnection::handle_connect_reply(ceph_msg_connect &connect, ceph_msg_co if (reply.tag == CEPH_MSGR_TAG_RESETSESSION) { ldout(async_msgr->cct, 0) << __func__ << " connect got RESETSESSION" << dendl; was_session_reset(); + // see was_session_reset + outcoming_bl.clear(); state = STATE_CONNECTING_SEND_CONNECT_MSG; } if (reply.tag == CEPH_MSGR_TAG_RETRY_GLOBAL) { @@ -1535,8 +1538,15 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis // connection's lock existing->lock.lock(); // skip lockdep check (we are locking a second AsyncConnection here) - if (existing->replacing || existing->state == STATE_CLOSED) { - ldout(async_msgr->cct, 1) << __func__ << " existing racing replace or mark_down happened while replacing." + if (existing->state == STATE_CLOSED) { + ldout(async_msgr->cct, 1) << __func__ << " existing already closed." << dendl; + existing->lock.unlock(); + existing = NULL; + goto open; + } + + if (existing->replacing) { + ldout(async_msgr->cct, 1) << __func__ << " existing racing replace happened while replacing." << " existing_state=" << get_state_name(existing->state) << dendl; reply.global_seq = existing->peer_global_seq; r = _reply_accept(CEPH_MSGR_TAG_RETRY_GLOBAL, connect, reply, authorizer_reply); @@ -1672,13 +1682,10 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis center->delete_file_event(cs.fd(), EVENT_READABLE|EVENT_WRITABLE); - // Clean up output buffer - existing->outcoming_bl.clear(); if (existing->delay_state) { existing->delay_state->flush(); assert(!delay_state); } - existing->requeue_sent(); existing->reset_recv_state(); auto temp_cs = std::move(cs); @@ -1691,7 +1698,6 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis dispatch_queue->queue_reset(this); ldout(async_msgr->cct, 1) << __func__ << " stop myself to swap existing" << dendl; existing->can_write = WriteStatus::REPLACING; - existing->open_write = false; existing->replacing = true; existing->state_offset = 0; // avoid previous thread modify event @@ -1706,6 +1712,11 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis // we need to delete time event in original thread { std::lock_guard l(existing->lock); + existing->write_lock.lock(); + existing->requeue_sent(); + existing->outcoming_bl.clear(); + existing->open_write = false; + existing->write_lock.unlock(); if (existing->state == STATE_NONE) { existing->shutdown_socket(); existing->cs = std::move(cs); @@ -1763,7 +1774,7 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis connect_seq = connect.connect_seq + 1; peer_global_seq = connect.global_seq; ldout(async_msgr->cct, 10) << __func__ << " accept success, connect_seq = " - << connect_seq << " in_seq=" << in_seq.read() << ", sending READY" << dendl; + << connect_seq << " in_seq=" << in_seq << ", sending READY" << dendl; int next_state; @@ -1776,7 +1787,7 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis next_state = STATE_ACCEPTING_READY; discard_requeued_up_to(0); is_reset_from_peer = false; - in_seq.set(0); + in_seq = 0; } // send READY reply @@ -1801,7 +1812,7 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis reply_bl.append(authorizer_reply.c_str(), authorizer_reply.length()); if (reply.tag == CEPH_MSGR_TAG_SEQ) { - uint64_t s = in_seq.read(); + uint64_t s = in_seq; reply_bl.append((char*)&s, sizeof(s)); } @@ -1934,16 +1945,7 @@ int AsyncConnection::send_message(Message *m) ldout(async_msgr->cct, 5) << __func__ << " clear encoded buffer previous " << f << " != " << get_features() << dendl; } - if (!is_queued() && can_write == WriteStatus::CANWRITE && async_msgr->cct->_conf->ms_async_send_inline) { - if (!bl.length()) - prepare_send_message(get_features(), m, bl); - logger->inc(l_msgr_send_messages_inline); - if (write_message(m, bl, false) < 0) { - ldout(async_msgr->cct, 1) << __func__ << " send msg failed" << dendl; - // we want to handle fault within internal thread - center->dispatch_event_external(write_handler); - } - } else if (can_write == WriteStatus::CLOSED) { + if (can_write == WriteStatus::CLOSED) { ldout(async_msgr->cct, 10) << __func__ << " connection closed." << " Drop message " << m << dendl; m->put(); @@ -1969,7 +1971,7 @@ void AsyncConnection::requeue_sent() ldout(async_msgr->cct, 10) << __func__ << " " << *m << " for resend " << " (" << m->get_seq() << ")" << dendl; rq.push_front(make_pair(bufferlist(), m)); - out_seq.dec(); + out_seq--; } } @@ -1988,7 +1990,7 @@ void AsyncConnection::discard_requeued_up_to(uint64_t seq) << " <= " << seq << ", discarding" << dendl; p.second->put(); rq.pop_front(); - out_seq.inc(); + out_seq++; } if (rq.empty()) out_q.erase(CEPH_MSG_PRIO_HIGHEST); @@ -1996,7 +1998,7 @@ void AsyncConnection::discard_requeued_up_to(uint64_t seq) /* * Tears down the AsyncConnection's message queues, and removes them from the DispatchQueue - * Must hold pipe_lock prior to calling. + * Must hold write_lock prior to calling. */ void AsyncConnection::discard_out_queue() { @@ -2013,7 +2015,6 @@ void AsyncConnection::discard_out_queue() r->second->put(); } out_q.clear(); - outcoming_bl.clear(); } int AsyncConnection::randomize_out_seq() @@ -2025,11 +2026,11 @@ int AsyncConnection::randomize_out_seq() int seq_error = get_random_bytes((char *)&rand_seq, sizeof(rand_seq)); rand_seq &= SEQ_MASK; lsubdout(async_msgr->cct, ms, 10) << __func__ << " randomize_out_seq " << rand_seq << dendl; - out_seq.set(rand_seq); + out_seq = rand_seq; return seq_error; } else { // previously, seq #'s always started at 0. - out_seq.set(0); + out_seq = 0; return 0; } } @@ -2065,7 +2066,7 @@ void AsyncConnection::fault() outcoming_bl.clear(); if (!once_ready && !is_queued() && state >=STATE_ACCEPTING && state <= STATE_ACCEPTING_WAIT_CONNECT_MSG_AUTH) { - ldout(async_msgr->cct, 0) << __func__ << " with nothing to send and in the half " + ldout(async_msgr->cct, 10) << __func__ << " with nothing to send and in the half " << " accept state just closed" << dendl; write_lock.unlock(); _stop(); @@ -2074,7 +2075,7 @@ void AsyncConnection::fault() } reset_recv_state(); if (policy.standby && !is_queued() && state != STATE_WAIT) { - ldout(async_msgr->cct,0) << __func__ << " with nothing to send, going to standby" << dendl; + ldout(async_msgr->cct, 10) << __func__ << " with nothing to send, going to standby" << dendl; state = STATE_STANDBY; write_lock.unlock(); return; @@ -2121,17 +2122,20 @@ void AsyncConnection::was_session_reset() delay_state->discard(); dispatch_queue->discard_queue(conn_id); discard_out_queue(); + // note: we need to clear outcoming_bl here, but was_session_reset may be + // called by other thread, so let caller clear this itself! + // outcoming_bl.clear(); dispatch_queue->queue_remote_reset(this); if (randomize_out_seq()) { - ldout(async_msgr->cct, 15) << __func__ << " could not get random bytes to set seq number for session reset; set seq number to " << out_seq.read() << dendl; + ldout(async_msgr->cct, 15) << __func__ << " could not get random bytes to set seq number for session reset; set seq number to " << out_seq << dendl; } - in_seq.set(0); + in_seq = 0; connect_seq = 0; // it's safe to directly set 0, double locked - ack_left.set(0); + ack_left = 0; once_ready = false; can_write = WriteStatus::NOWRITE; } @@ -2184,14 +2188,8 @@ void AsyncConnection::prepare_send_message(uint64_t features, Message *m, buffer ssize_t AsyncConnection::write_message(Message *m, bufferlist& bl, bool more) { FUNCTRACE(); - assert(can_write == WriteStatus::CANWRITE); - m->set_seq(out_seq.inc()); - - if (!policy.lossy) { - // put on sent list - sent.push_back(m); - m->get(); - } + assert(center->in_thread()); + m->set_seq(++out_seq); if (msgr->crcflags & MSG_CRC_HEADER) m->calc_header_crc(); @@ -2441,41 +2439,52 @@ void AsyncConnection::handle_write() keepalive = false; } - while (1) { + auto start = ceph::mono_clock::now(); + bool more; + do { bufferlist data; Message *m = _get_next_outgoing(&data); if (!m) break; + if (!policy.lossy) { + // put on sent list + sent.push_back(m); + m->get(); + } + more = _has_next_outgoing(); + write_lock.unlock(); + // send_message or requeue messages may not encode message if (!data.length()) prepare_send_message(get_features(), m, data); - r = write_message(m, data, _has_next_outgoing()); + r = write_message(m, data, more); if (r < 0) { ldout(async_msgr->cct, 1) << __func__ << " send msg failed" << dendl; - write_lock.unlock(); goto fail; - } else if (r > 0) { - break; } - } + write_lock.lock(); + if (r > 0) + break; + } while (can_write == WriteStatus::CANWRITE); + write_lock.unlock(); - uint64_t left = ack_left.read(); + uint64_t left = ack_left; if (left) { ceph_le64 s; - s = in_seq.read(); + s = in_seq; outcoming_bl.append(CEPH_MSGR_TAG_ACK); outcoming_bl.append((char*)&s, sizeof(s)); ldout(async_msgr->cct, 10) << __func__ << " try send msg ack, acked " << left << " messages" << dendl; - ack_left.sub(left); - left = ack_left.read(); + ack_left -= left; + left = ack_left; r = _try_send(left); } else if (is_queued()) { r = _try_send(); } - write_lock.unlock(); + logger->tinc(l_msgr_running_send_time, ceph::mono_clock::now() - start); if (r < 0) { ldout(async_msgr->cct, 1) << __func__ << " send msg failed" << dendl; goto fail; @@ -2522,7 +2531,6 @@ void AsyncConnection::tick(uint64_t id) auto now = ceph::coarse_mono_clock::now(); ldout(async_msgr->cct, 20) << __func__ << " last_id=" << last_tick_id << " last_active" << last_active << dendl; - assert(last_tick_id == id); std::lock_guard l(lock); last_tick_id = 0; auto idle_period = std::chrono::duration_cast(now - last_active).count(); diff --git a/ceph/src/msg/async/AsyncConnection.h b/ceph/src/msg/async/AsyncConnection.h index 24773afa9..005b7c13a 100644 --- a/ceph/src/msg/async/AsyncConnection.h +++ b/ceph/src/msg/async/AsyncConnection.h @@ -294,8 +294,8 @@ class AsyncConnection : public Connection { PerfCounters *logger; int global_seq; __u32 connect_seq, peer_global_seq; - atomic64_t out_seq; - atomic64_t ack_left, in_seq; + std::atomic out_seq{0}; + std::atomic ack_left{0}, in_seq{0}; int state; int state_after_send; ConnectedSocket cs; @@ -304,6 +304,10 @@ class AsyncConnection : public Connection { DispatchQueue *dispatch_queue; + // lockfree, only used in own thread + bufferlist outcoming_bl; + bool open_write = false; + std::mutex write_lock; enum class WriteStatus { NOWRITE, @@ -312,10 +316,8 @@ class AsyncConnection : public Connection { CLOSED }; std::atomic can_write; - bool open_write; - map > > out_q; // priority queue for outbound msgs list sent; // the first bufferlist need to inject seq - bufferlist outcoming_bl; + map > > out_q; // priority queue for outbound msgs bool keepalive; std::mutex lock; diff --git a/ceph/src/msg/async/AsyncMessenger.cc b/ceph/src/msg/async/AsyncMessenger.cc index 122473179..469584405 100644 --- a/ceph/src/msg/async/AsyncMessenger.cc +++ b/ceph/src/msg/async/AsyncMessenger.cc @@ -412,6 +412,8 @@ int AsyncMessenger::rebind(const set& avoid_ports) int AsyncMessenger::client_bind(const entity_addr_t &bind_addr) { + if (!cct->_conf->ms_bind_before_connect) + return 0; Mutex::Locker l(lock); if (did_bind) { assert(my_inst.addr == bind_addr); diff --git a/ceph/src/msg/async/AsyncMessenger.h b/ceph/src/msg/async/AsyncMessenger.h index 01af51104..0b1f2c8e9 100644 --- a/ceph/src/msg/async/AsyncMessenger.h +++ b/ceph/src/msg/async/AsyncMessenger.h @@ -26,10 +26,11 @@ using namespace std; #include "include/unordered_set.h" #include "common/Mutex.h" -#include "include/atomic.h" #include "common/Cond.h" #include "common/Thread.h" +#include "include/Spinlock.h" + #include "msg/SimplePolicyMessenger.h" #include "msg/DispatchQueue.h" #include "include/assert.h" @@ -353,6 +354,8 @@ public: // If conn already in, we will return 0 Mutex::Locker l(deleted_lock); if (deleted_conns.erase(existing)) { + existing->get_perf_counter()->dec(l_msgr_active_connections); + conns.erase(it); } else if (conn != existing) { return -1; } diff --git a/ceph/src/msg/async/Event.cc b/ceph/src/msg/async/Event.cc index 23999eba6..690a24531 100644 --- a/ceph/src/msg/async/Event.cc +++ b/ceph/src/msg/async/Event.cc @@ -355,7 +355,7 @@ int EventCenter::process_time_events() return processed; } -int EventCenter::process_events(int timeout_microseconds) +int EventCenter::process_events(int timeout_microseconds, ceph::timespan *working_dur) { struct timeval tv; int numevents; @@ -393,6 +393,7 @@ int EventCenter::process_events(int timeout_microseconds) ldout(cct, 30) << __func__ << " wait second " << tv.tv_sec << " usec " << tv.tv_usec << dendl; vector fired_events; numevents = driver->event_wait(fired_events, &tv); + auto working_start = ceph::mono_clock::now(); for (int j = 0; j < numevents; j++) { int rfired = 0; FileEvent *event; @@ -441,6 +442,8 @@ int EventCenter::process_events(int timeout_microseconds) numevents += pollers[i]->poll(); } + if (working_dur) + *working_dur = ceph::mono_clock::now() - working_start; return numevents; } diff --git a/ceph/src/msg/async/Event.h b/ceph/src/msg/async/Event.h index 5b89f53fb..b4743c1b2 100644 --- a/ceph/src/msg/async/Event.h +++ b/ceph/src/msg/async/Event.h @@ -203,7 +203,7 @@ class EventCenter { uint64_t create_time_event(uint64_t milliseconds, EventCallbackRef ctxt); void delete_file_event(int fd, int mask); void delete_time_event(uint64_t id); - int process_events(int timeout_microseconds); + int process_events(int timeout_microseconds, ceph::timespan *working_dur = nullptr); void wakeup(); // Used by external thread diff --git a/ceph/src/msg/async/PosixStack.cc b/ceph/src/msg/async/PosixStack.cc index 0422b4e26..cf52db9a7 100644 --- a/ceph/src/msg/async/PosixStack.cc +++ b/ceph/src/msg/async/PosixStack.cc @@ -30,7 +30,6 @@ #include "common/errno.h" #include "common/strtol.h" #include "common/dout.h" -#include "include/assert.h" #include "common/simple_spin.h" #define dout_subsys ceph_subsys_ms diff --git a/ceph/src/msg/async/Stack.cc b/ceph/src/msg/async/Stack.cc index 888462a31..807db1136 100644 --- a/ceph/src/msg/async/Stack.cc +++ b/ceph/src/msg/async/Stack.cc @@ -47,12 +47,14 @@ std::function NetworkStack::add_thread(unsigned i) while (!w->done) { ldout(cct, 30) << __func__ << " calling event process" << dendl; - int r = w->center.process_events(EventMaxWaitUs); + ceph::timespan dur; + int r = w->center.process_events(EventMaxWaitUs, &dur); if (r < 0) { ldout(cct, 20) << __func__ << " process events failed: " << cpp_strerror(errno) << dendl; // TODO do something? } + w->perf_logger->tinc(l_msgr_running_total_time, dur); } w->reset(); w->destroy(); @@ -99,6 +101,8 @@ Worker* NetworkStack::create_worker(CephContext *c, const string &type, unsigned NetworkStack::NetworkStack(CephContext *c, const string &t): type(t), started(false), cct(c) { + assert(cct->_conf->ms_async_op_threads > 0); + const uint64_t InitEventNumber = 5000; num_workers = cct->_conf->ms_async_op_threads; if (num_workers >= EventCenter::MAX_EVENTCENTER) { diff --git a/ceph/src/msg/async/Stack.h b/ceph/src/msg/async/Stack.h index 3b7adca35..f16732980 100644 --- a/ceph/src/msg/async/Stack.h +++ b/ceph/src/msg/async/Stack.h @@ -189,11 +189,16 @@ enum { l_msgr_first = 94000, l_msgr_recv_messages, l_msgr_send_messages, - l_msgr_send_messages_inline, l_msgr_recv_bytes, l_msgr_send_bytes, l_msgr_created_connections, l_msgr_active_connections, + + l_msgr_running_total_time, + l_msgr_running_send_time, + l_msgr_running_recv_time, + l_msgr_running_fast_dispatch_time, + l_msgr_last, }; @@ -224,12 +229,16 @@ class Worker { plb.add_u64_counter(l_msgr_recv_messages, "msgr_recv_messages", "Network received messages"); plb.add_u64_counter(l_msgr_send_messages, "msgr_send_messages", "Network sent messages"); - plb.add_u64_counter(l_msgr_send_messages_inline, "msgr_send_messages_inline", "Network sent inline messages"); plb.add_u64_counter(l_msgr_recv_bytes, "msgr_recv_bytes", "Network received bytes"); plb.add_u64_counter(l_msgr_send_bytes, "msgr_send_bytes", "Network received bytes"); plb.add_u64_counter(l_msgr_active_connections, "msgr_active_connections", "Active connection number"); plb.add_u64_counter(l_msgr_created_connections, "msgr_created_connections", "Created connection number"); + plb.add_time(l_msgr_running_total_time, "msgr_running_total_time", "The total time of thread running"); + plb.add_time(l_msgr_running_send_time, "msgr_running_send_time", "The total time of message sending"); + plb.add_time(l_msgr_running_recv_time, "msgr_running_recv_time", "The total time of message receiving"); + plb.add_time(l_msgr_running_fast_dispatch_time, "msgr_running_fast_dispatch_time", "The total time of fast dispatch"); + perf_logger = plb.create_perf_counters(); cct->get_perfcounters_collection()->add(perf_logger); } diff --git a/ceph/src/msg/async/dpdk/IP.cc b/ceph/src/msg/async/dpdk/IP.cc index 3d3e8fb50..9f36d2eaf 100644 --- a/ceph/src/msg/async/dpdk/IP.cc +++ b/ceph/src/msg/async/dpdk/IP.cc @@ -48,7 +48,7 @@ #undef dout_prefix #define dout_prefix *_dout << "dpdk " -std::ostream& operator<<(std::ostream& os, ipv4_address a) { +std::ostream& operator<<(std::ostream& os, const ipv4_address& a) { auto ip = a.ip; return os << ((ip >> 24) & 0xff) << "." << ((ip >> 16) & 0xff) << "." << ((ip >> 8) & 0xff) << "." << ((ip >> 0) & 0xff); diff --git a/ceph/src/msg/async/dpdk/TCP.h b/ceph/src/msg/async/dpdk/TCP.h index eb3c10490..9923fab54 100644 --- a/ceph/src/msg/async/dpdk/TCP.h +++ b/ceph/src/msg/async/dpdk/TCP.h @@ -69,7 +69,7 @@ inline tcp_state operator|(tcp_state s1, tcp_state s2) { return tcp_state(uint16_t(s1) | uint16_t(s2)); } -inline std::ostream & operator<<(std::ostream & str, tcp_state s) { +inline std::ostream & operator<<(std::ostream & str, const tcp_state& s) { switch (s) { case tcp_state::CLOSED: return str << "CLOSED"; case tcp_state::LISTEN: return str << "LISTEN"; @@ -154,7 +154,7 @@ tcp_sequence hton(tcp_sequence ts) { return tcp_sequence { ::hton(ts.raw) }; } -inline std::ostream& operator<<(std::ostream& os, tcp_sequence s) { +inline std::ostream& operator<<(std::ostream& os, const tcp_sequence& s) { return os << s.raw; } diff --git a/ceph/src/msg/async/dpdk/ethernet.cc b/ceph/src/msg/async/dpdk/ethernet.cc index e1bf04665..9aca50788 100644 --- a/ceph/src/msg/async/dpdk/ethernet.cc +++ b/ceph/src/msg/async/dpdk/ethernet.cc @@ -2,7 +2,7 @@ #include "ethernet.h" -std::ostream& operator<<(std::ostream& os, ethernet_address ea) { +std::ostream& operator<<(std::ostream& os, const ethernet_address& ea) { auto& m = ea.mac; using u = uint32_t; os << std::hex << std::setw(2) diff --git a/ceph/src/msg/async/dpdk/ethernet.h b/ceph/src/msg/async/dpdk/ethernet.h index b602de62c..17546d73a 100644 --- a/ceph/src/msg/async/dpdk/ethernet.h +++ b/ceph/src/msg/async/dpdk/ethernet.h @@ -53,7 +53,7 @@ struct ethernet_address { inline bool operator==(const ethernet_address& a, const ethernet_address& b) { return a.mac == b.mac; } -std::ostream& operator<<(std::ostream& os, ethernet_address ea); +std::ostream& operator<<(std::ostream& os, const ethernet_address& ea); struct ethernet { using address = ethernet_address; diff --git a/ceph/src/msg/async/dpdk/ip_types.h b/ceph/src/msg/async/dpdk/ip_types.h index 55e0bcfb2..356d8fd6e 100644 --- a/ceph/src/msg/async/dpdk/ip_types.h +++ b/ceph/src/msg/async/dpdk/ip_types.h @@ -95,7 +95,7 @@ struct ipv4_address { static inline bool is_unspecified(ipv4_address addr) { return addr.ip == 0; } -std::ostream& operator<<(std::ostream& os, ipv4_address a); +std::ostream& operator<<(std::ostream& os, const ipv4_address& a); namespace std { diff --git a/ceph/src/msg/async/rdma/Device.cc b/ceph/src/msg/async/rdma/Device.cc deleted file mode 100644 index 6f7df5b11..000000000 --- a/ceph/src/msg/async/rdma/Device.cc +++ /dev/null @@ -1,550 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2016 XSKY - * - * Author: Haomai Wang - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#include "Infiniband.h" -#include "RDMAStack.h" -#include "Device.h" -#include "common/errno.h" -#include "common/debug.h" - -#include - -#define dout_subsys ceph_subsys_ms -#undef dout_prefix -#define dout_prefix *_dout << "IBDevice " - -static const uint32_t MAX_SHARED_RX_SGE_COUNT = 1; -static const uint32_t CQ_DEPTH = 30000; - -Port::Port(CephContext *cct, struct ibv_context* ictxt, uint8_t ipn): ctxt(ictxt), port_num(ipn), port_attr(new ibv_port_attr) -{ -#ifdef HAVE_IBV_EXP - union ibv_gid cgid; - struct ibv_exp_gid_attr gid_attr; - bool malformed = false; - - ldout(cct,1) << __func__ << " using experimental verbs for gid" << dendl; - int r = ibv_query_port(ctxt, port_num, port_attr); - if (r == -1) { - lderr(cct) << __func__ << " query port failed " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - - lid = port_attr->lid; - - // search for requested GID in GIDs table - ldout(cct, 1) << __func__ << " looking for local GID " << (cct->_conf->ms_async_rdma_local_gid) - << " of type " << (cct->_conf->ms_async_rdma_roce_ver) << dendl; - r = sscanf(cct->_conf->ms_async_rdma_local_gid.c_str(), - "%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx" - ":%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx", - &cgid.raw[ 0], &cgid.raw[ 1], - &cgid.raw[ 2], &cgid.raw[ 3], - &cgid.raw[ 4], &cgid.raw[ 5], - &cgid.raw[ 6], &cgid.raw[ 7], - &cgid.raw[ 8], &cgid.raw[ 9], - &cgid.raw[10], &cgid.raw[11], - &cgid.raw[12], &cgid.raw[13], - &cgid.raw[14], &cgid.raw[15]); - - if (r != 16) { - ldout(cct, 1) << __func__ << " malformed or no GID supplied, using GID index 0" << dendl; - malformed = true; - } - - gid_attr.comp_mask = IBV_EXP_QUERY_GID_ATTR_TYPE; - - for (gid_idx = 0; gid_idx < port_attr->gid_tbl_len; gid_idx++) { - r = ibv_query_gid(ctxt, port_num, gid_idx, &gid); - if (r) { - lderr(cct) << __func__ << " query gid of port " << port_num << " index " << gid_idx << " failed " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - r = ibv_exp_query_gid_attr(ctxt, port_num, gid_idx, &gid_attr); - if (r) { - lderr(cct) << __func__ << " query gid attributes of port " << port_num << " index " << gid_idx << " failed " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - - if (malformed) break; // stay with gid_idx=0 - if ( (gid_attr.type == cct->_conf->ms_async_rdma_roce_ver) && - (memcmp(&gid, &cgid, 16) == 0) ) { - ldout(cct, 1) << __func__ << " found at index " << gid_idx << dendl; - break; - } - } - - if (gid_idx == port_attr->gid_tbl_len) { - lderr(cct) << __func__ << " Requested local GID was not found in GID table" << dendl; - ceph_abort(); - } -#else - int r = ibv_query_port(ctxt, port_num, port_attr); - if (r == -1) { - lderr(cct) << __func__ << " query port failed " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - - lid = port_attr->lid; - r = ibv_query_gid(ctxt, port_num, 0, &gid); - if (r) { - lderr(cct) << __func__ << " query gid failed " << cpp_strerror(errno) << dendl; - ceph_abort(); - } -#endif -} - -Port::~Port() -{ - delete port_attr; -} - - -Device::Device(CephContext *cct, Infiniband *ib, ibv_device* d) - : cct(cct), device(d), lock("ibdev_lock"), - async_handler(new C_handle_cq_async(this)), infiniband(ib), - device_attr(new ibv_device_attr) -{ - if (device == NULL) { - lderr(cct) << __func__ << " device == NULL" << cpp_strerror(errno) << dendl; - ceph_abort(); - } - name = ibv_get_device_name(device); - ctxt = ibv_open_device(device); - if (ctxt == NULL) { - lderr(cct) << __func__ << " open rdma device failed. " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - int r = ibv_query_device(ctxt, device_attr); - if (r == -1) { - lderr(cct) << __func__ << " failed to query rdma device. " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - - port_cnt = device_attr->phys_port_cnt; - ports = new Port *[port_cnt + 1]; - assert(ports); - - for (int i = 1; i <= port_cnt; i++) { - ports[i] = new Port(cct, ctxt, i); - assert(ports[i]); - } - - tx_cc = create_comp_channel(cct); - assert(tx_cc); - - rx_cc = create_comp_channel(cct); - assert(rx_cc); - - assert(NetHandler(cct).set_nonblock(ctxt->async_fd) == 0); -} - -void Device::init(int ibport) -{ - Mutex::Locker l(lock); - - verify_port(ibport); - - if (initialized) - return; - - pd = new ProtectionDomain(cct, this); - - max_recv_wr = std::min(device_attr->max_srq_wr, (int)cct->_conf->ms_async_rdma_receive_buffers); - ldout(cct, 1) << __func__ << " assigning: " << max_recv_wr << " receive buffers" << dendl; - - max_send_wr = std::min(device_attr->max_qp_wr, (int)cct->_conf->ms_async_rdma_send_buffers); - ldout(cct, 1) << __func__ << " assigning: " << max_send_wr << " send buffers" << dendl; - - ldout(cct, 1) << __func__ << " device allow " << device_attr->max_cqe - << " completion entries" << dendl; - - memory_manager = new MemoryManager(this, pd, - cct->_conf->ms_async_rdma_enable_hugepage); - memory_manager->register_rx_tx( - cct->_conf->ms_async_rdma_buffer_size, max_recv_wr, max_send_wr); - - srq = create_shared_receive_queue(max_recv_wr, MAX_SHARED_RX_SGE_COUNT); - post_channel_cluster(); - - tx_cq = create_comp_queue(cct, tx_cc); - assert(tx_cq); - - rx_cq = create_comp_queue(cct, rx_cc); - assert(rx_cq); - - initialized = true; - - ldout(cct, 5) << __func__ << ":" << __LINE__ << " device " << *this << " is initialized" << dendl; -} - -void Device::uninit() -{ - Mutex::Locker l(lock); - - if (!initialized) - return; - - tx_cc->ack_events(); - rx_cc->ack_events(); - - initialized = false; - - delete rx_cq; - delete tx_cq; - delete rx_cc; - delete tx_cc; - - assert(ibv_destroy_srq(srq) == 0); - delete memory_manager; - delete pd; -} - -Device::~Device() -{ - delete async_handler; - - uninit(); - - for (int i = 1; i <= port_cnt; i++) - delete ports[i]; - delete[] ports; - - assert(ibv_close_device(ctxt) == 0); - delete device_attr; -} - -void Device::verify_port(int port_num) { - if (port_num < 0 || port_num > port_cnt) { - lderr(cct) << __func__ << " port not found" << dendl; - ceph_abort(); - } - - Port *port = ports[port_num]; - - if (port->get_port_attr()->state == IBV_PORT_ACTIVE) { - ldout(cct, 1) << __func__ << " found active port " << port_num << dendl; - } else { - ldout(cct, 10) << __func__ << " port " << port_num << - " is not what we want. state: " << port->get_port_attr()->state << ")"<< dendl; - ceph_abort(); - } -} - -Port *Device::get_port(int ibport) -{ - assert(ibport > 0 && ibport <= port_cnt); - return ports[ibport]; -} - -/** - * Create a new QueuePair. This factory should be used in preference to - * the QueuePair constructor directly, since this lets derivatives of - * Infiniband, e.g. MockInfiniband (if it existed), - * return mocked out QueuePair derivatives. - * - * \return - * QueuePair on success or NULL if init fails - * See QueuePair::QueuePair for parameter documentation. - */ -Infiniband::QueuePair* Device::create_queue_pair(int port, - ibv_qp_type type) -{ - Infiniband::QueuePair *qp = new QueuePair( - cct, *this, type, port, srq, tx_cq, rx_cq, max_send_wr, max_recv_wr); - if (qp->init()) { - delete qp; - return NULL; - } - return qp; -} - -/** - * Create a shared receive queue. This basically wraps the verbs call. - * - * \param[in] max_wr - * The max number of outstanding work requests in the SRQ. - * \param[in] max_sge - * The max number of scatter elements per WR. - * \return - * A valid ibv_srq pointer, or NULL on error. - */ -ibv_srq* Device::create_shared_receive_queue(uint32_t max_wr, uint32_t max_sge) -{ - ibv_srq_init_attr sia; - memset(&sia, 0, sizeof(sia)); - sia.srq_context = ctxt; - sia.attr.max_wr = max_wr; - sia.attr.max_sge = max_sge; - return ibv_create_srq(pd->pd, &sia); -} - -Infiniband::CompletionChannel* Device::create_comp_channel(CephContext *c) -{ - Infiniband::CompletionChannel *cc = new Infiniband::CompletionChannel(c, *this); - if (cc->init()) { - delete cc; - return NULL; - } - return cc; -} - -Infiniband::CompletionQueue* Device::create_comp_queue( - CephContext *cct, CompletionChannel *cc) -{ - Infiniband::CompletionQueue *cq = new Infiniband::CompletionQueue( - cct, *this, CQ_DEPTH, cc); - if (cq->init()) { - delete cq; - return NULL; - } - return cq; -} - -int Device::post_chunk(Chunk* chunk) -{ - ibv_sge isge; - isge.addr = reinterpret_cast(chunk->buffer); - isge.length = chunk->bytes; - isge.lkey = chunk->mr->lkey; - ibv_recv_wr rx_work_request; - - memset(&rx_work_request, 0, sizeof(rx_work_request)); - rx_work_request.wr_id = reinterpret_cast(chunk);// stash descriptor ptr - rx_work_request.next = NULL; - rx_work_request.sg_list = &isge; - rx_work_request.num_sge = 1; - - ibv_recv_wr *badWorkRequest; - int ret = ibv_post_srq_recv(srq, &rx_work_request, &badWorkRequest); - if (ret) - return -errno; - return 0; -} - -int Device::post_channel_cluster() -{ - vector free_chunks; - int r = memory_manager->get_channel_buffers(free_chunks, 0); - assert(r > 0); - for (vector::iterator iter = free_chunks.begin(); iter != free_chunks.end(); ++iter) { - r = post_chunk(*iter); - assert(r == 0); - } - return 0; -} - -int Device::get_tx_buffers(std::vector &c, size_t bytes) -{ - return memory_manager->get_send_buffers(c, bytes); -} - -int Device::poll_tx_cq(int n, ibv_wc *wc) -{ - if (!initialized) - return 0; - - return tx_cq->poll_cq(n, wc); -} - -int Device::poll_rx_cq(int n, ibv_wc *wc) -{ - if (!initialized) - return 0; - - return rx_cq->poll_cq(n, wc); -} - -void Device::rearm_cqs() -{ - int ret; - - if (!initialized) - return; - - ret = tx_cq->rearm_notify(); - assert(!ret); - - ret = rx_cq->rearm_notify(); - assert(!ret); -} - -void Device::handle_async_event() -{ - ibv_async_event async_event; - - ldout(cct, 30) << __func__ << dendl; - - while (!ibv_get_async_event(ctxt, &async_event)) { - RDMADispatcher *d = infiniband->get_dispatcher(); - d->process_async_event(this, async_event); - - ibv_ack_async_event(&async_event); - } - - if (errno != EAGAIN) { - lderr(cct) << __func__ << " ibv_get_async_event failed. (errno=" << errno - << " " << cpp_strerror(errno) << ")" << dendl; - } -} - - -DeviceList::DeviceList(CephContext *cct, Infiniband *ib) - : cct(cct), device_list(ibv_get_device_list(&num)) -{ - if (device_list == NULL || num == 0) { - lderr(cct) << __func__ << " failed to get rdma device list. " << cpp_strerror(errno) << dendl; - ceph_abort(); - } - devices = new Device*[num]; - - poll_fds = new struct pollfd[3 * num]; - - for (int i = 0; i < num; ++i) { - struct pollfd *pfd = &poll_fds[i * 3]; - struct Device *d; - - d = new Device(cct, ib, device_list[i]); - devices[i] = d; - - pfd[0].fd = d->tx_cc->get_fd(); - pfd[0].events = POLLIN | POLLERR | POLLNVAL | POLLHUP; - pfd[0].revents = 0; - - pfd[1].fd = d->rx_cc->get_fd(); - pfd[1].events = POLLIN | POLLERR | POLLNVAL | POLLHUP; - pfd[1].revents = 0; - - pfd[2].fd = d->ctxt->async_fd; - pfd[2].events = POLLIN | POLLERR | POLLNVAL | POLLHUP; - pfd[2].revents = 0; - } -} - -DeviceList::~DeviceList() -{ - delete[] poll_fds; - - for (int i=0; i < num; ++i) { - delete devices[i]; - } - delete []devices; - ibv_free_device_list(device_list); -} - -Device* DeviceList::get_device(const char* device_name) -{ - assert(devices); - for (int i = 0; i < num; ++i) { - if (!strlen(device_name) || !strcmp(device_name, devices[i]->get_name())) { - return devices[i]; - } - } - return NULL; -} - - -Device* DeviceList::get_device(const struct ibv_context *ctxt) -{ - ibv_device *device = ctxt->device; - - assert(devices); - for (int i = 0; i < num; ++i) { - if (devices[i]->ctxt->device == device) { - return devices[i]; - } - } - - return NULL; -} - -int DeviceList::poll_tx(int num_entries, Device **d, ibv_wc *wc) -{ - int n = 0; - - for (int i = 0; i < num; i++) { - *d = devices[++last_poll_dev % num]; - - n = (*d)->poll_tx_cq(num_entries, wc); - if (n) - break; - } - - return n; -} - -int DeviceList::poll_rx(int num_entries, Device **d, ibv_wc *wc) -{ - int n = 0; - - for (int i = 0; i < num; i++) { - *d = devices[++last_poll_dev % num]; - - n = (*d)->poll_rx_cq(num_entries, wc); - if (n) - break; - } - - return n; -} - -int DeviceList::poll_blocking(bool &done) -{ - int r = 0; - while (!done && r == 0) { - r = poll(poll_fds, num * 3, 100); - if (r < 0) { - r = -errno; - lderr(cct) << __func__ << " poll failed " << r << dendl; - ceph_abort(); - } - } - - if (r <= 0) - return r; - - for (int i = 0; i < num ; i++) { - Device *d = devices[i]; - - if (d->tx_cc->get_cq_event()) - ldout(cct, 20) << __func__ << " " << *d << ": got tx cq event" << dendl; - - if (d->rx_cc->get_cq_event()) - ldout(cct, 20) << __func__ << " " << *d << ": got rx cq event" << dendl; - - d->handle_async_event(); - } - - return r; -} - -void DeviceList::rearm_notify() -{ - for (int i = 0; i < num; i++) - devices[i]->rearm_cqs(); -} - -void DeviceList::handle_async_event() -{ - for (int i = 0; i < num; i++) - devices[i]->handle_async_event(); -} - -void DeviceList::uninit() -{ - for (int i = 0; i < num; i++) - devices[i]->uninit(); -} diff --git a/ceph/src/msg/async/rdma/Device.h b/ceph/src/msg/async/rdma/Device.h deleted file mode 100644 index 148a75174..000000000 --- a/ceph/src/msg/async/rdma/Device.h +++ /dev/null @@ -1,168 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2016 XSKY - * - * Author: Haomai Wang - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#ifndef CEPH_RDMA_DEVICE_H -#define CEPH_RDMA_DEVICE_H - -#include - -#include -#include - -#include "include/int_types.h" -#include "include/page.h" -#include "common/debug.h" -#include "common/errno.h" -#include "msg/msg_types.h" -#include "msg/async/net_handler.h" -#include "common/Mutex.h" -#include "msg/async/Event.h" - -typedef Infiniband::QueuePair QueuePair; -typedef Infiniband::CompletionChannel CompletionChannel; -typedef Infiniband::CompletionQueue CompletionQueue; -typedef Infiniband::ProtectionDomain ProtectionDomain; -typedef Infiniband::MemoryManager::Cluster Cluster; -typedef Infiniband::MemoryManager::Chunk Chunk; -typedef Infiniband::MemoryManager MemoryManager; - -class Port { - struct ibv_context* ctxt; - int port_num; - struct ibv_port_attr* port_attr; - uint16_t lid; - int gid_idx = 0; - union ibv_gid gid; - - public: - explicit Port(CephContext *cct, struct ibv_context* ictxt, uint8_t ipn); - ~Port(); - uint16_t get_lid() { return lid; } - ibv_gid get_gid() { return gid; } - int get_port_num() { return port_num; } - ibv_port_attr* get_port_attr() { return port_attr; } - int get_gid_idx() { return gid_idx; } -}; - - -class Device { - class C_handle_cq_async : public EventCallback { - Device *device; - public: - C_handle_cq_async(Device *d): device(d) {} - void do_request(int fd) { - device->handle_async_event(); - } - }; - - CephContext *cct; - ibv_device *device; - const char *name; - - Port **ports; // Array of Port objects. index is 1 based (IB port #1 is in - // index 1). Index 0 is not used - - int port_cnt; - - uint32_t max_send_wr; - uint32_t max_recv_wr; - uint32_t max_sge; - - Mutex lock; // Protects from concurrent intialization of the device - bool initialized = false; - EventCallbackRef async_handler; - Infiniband *infiniband; - - void verify_port(int port_num); - - public: - explicit Device(CephContext *c, Infiniband *ib, ibv_device* d); - ~Device(); - - void init(int ibport = -1); - void uninit(); - - void handle_async_event(); - - const char* get_name() const { return name;} - - Port *get_port(int ibport); - uint16_t get_lid(int p) { return get_port(p)->get_lid(); } - ibv_gid get_gid(int p) { return get_port(p)->get_gid(); } - int get_gid_idx(int p) { return get_port(p)->get_gid_idx(); } - - QueuePair *create_queue_pair(int port, - ibv_qp_type type); - ibv_srq* create_shared_receive_queue(uint32_t max_wr, uint32_t max_sge); - CompletionChannel *create_comp_channel(CephContext *c); - CompletionQueue *create_comp_queue(CephContext *c, CompletionChannel *cc=NULL); - int post_chunk(Chunk* chunk); - int post_channel_cluster(); - - MemoryManager* get_memory_manager() { return memory_manager; } - bool is_tx_buffer(const char* c) { return memory_manager->is_tx_buffer(c);} - bool is_rx_buffer(const char* c) { return memory_manager->is_rx_buffer(c);} - Chunk *get_tx_chunk_by_buffer(const char *c) { return memory_manager->get_tx_chunk_by_buffer(c); } - int get_tx_buffers(std::vector &c, size_t bytes); - int poll_tx_cq(int n, ibv_wc *wc); - int poll_rx_cq(int n, ibv_wc *wc); - void rearm_cqs(); - - struct ibv_context *ctxt; - ibv_device_attr *device_attr; - - MemoryManager* memory_manager = nullptr; - ibv_srq *srq = nullptr; - Infiniband::CompletionQueue *rx_cq = nullptr; - Infiniband::CompletionChannel *rx_cc = nullptr; - Infiniband::CompletionQueue *tx_cq = nullptr; - Infiniband::CompletionChannel *tx_cc = nullptr; - ProtectionDomain *pd = nullptr; -}; - -inline ostream& operator<<(ostream& out, const Device &d) -{ - return out << d.get_name(); -} - - -class DeviceList { - CephContext *cct; - struct ibv_device ** device_list; - int num; - Device** devices; - - unsigned last_poll_dev = 0; - struct pollfd *poll_fds; - - public: - DeviceList(CephContext *cct, Infiniband *ib); - ~DeviceList(); - - Device* get_device(const char* device_name); - Device* get_device(const struct ibv_context *ctxt); - - void uninit(); - - void rearm_notify(); - int poll_tx(int n, Device **d, ibv_wc *wc); - int poll_rx(int n, Device **d, ibv_wc *wc); - int poll_blocking(bool &done); - - void handle_async_event(); -}; - -#endif diff --git a/ceph/src/msg/async/rdma/Infiniband.cc b/ceph/src/msg/async/rdma/Infiniband.cc index b4a644e67..0597b09eb 100644 --- a/ceph/src/msg/async/rdma/Infiniband.cc +++ b/ceph/src/msg/async/rdma/Infiniband.cc @@ -15,28 +15,147 @@ */ #include "Infiniband.h" -#include "RDMAStack.h" -#include "Device.h" - #include "common/errno.h" #include "common/debug.h" +#include "RDMAStack.h" #define dout_subsys ceph_subsys_ms #undef dout_prefix #define dout_prefix *_dout << "Infiniband " +static const uint32_t MAX_SHARED_RX_SGE_COUNT = 1; static const uint32_t MAX_INLINE_DATA = 0; +static const uint32_t TCP_MSG_LEN = sizeof("0000:00000000:00000000:00000000:00000000000000000000000000000000"); +static const uint32_t CQ_DEPTH = 30000; + +Port::Port(CephContext *cct, struct ibv_context* ictxt, uint8_t ipn): ctxt(ictxt), port_num(ipn), port_attr(new ibv_port_attr) +{ +#ifdef HAVE_IBV_EXP + union ibv_gid cgid; + struct ibv_exp_gid_attr gid_attr; + bool malformed = false; + + ldout(cct,1) << __func__ << " using experimental verbs for gid" << dendl; + int r = ibv_query_port(ctxt, port_num, port_attr); + if (r == -1) { + lderr(cct) << __func__ << " query port failed " << cpp_strerror(errno) << dendl; + ceph_abort(); + } + + lid = port_attr->lid; + + // search for requested GID in GIDs table + ldout(cct, 1) << __func__ << " looking for local GID " << (cct->_conf->ms_async_rdma_local_gid) + << " of type " << (cct->_conf->ms_async_rdma_roce_ver) << dendl; + r = sscanf(cct->_conf->ms_async_rdma_local_gid.c_str(), + "%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx" + ":%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx", + &cgid.raw[ 0], &cgid.raw[ 1], + &cgid.raw[ 2], &cgid.raw[ 3], + &cgid.raw[ 4], &cgid.raw[ 5], + &cgid.raw[ 6], &cgid.raw[ 7], + &cgid.raw[ 8], &cgid.raw[ 9], + &cgid.raw[10], &cgid.raw[11], + &cgid.raw[12], &cgid.raw[13], + &cgid.raw[14], &cgid.raw[15]); + + if (r != 16) { + ldout(cct, 1) << __func__ << " malformed or no GID supplied, using GID index 0" << dendl; + malformed = true; + } + + gid_attr.comp_mask = IBV_EXP_QUERY_GID_ATTR_TYPE; + + for (gid_idx = 0; gid_idx < port_attr->gid_tbl_len; gid_idx++) { + r = ibv_query_gid(ctxt, port_num, gid_idx, &gid); + if (r) { + lderr(cct) << __func__ << " query gid of port " << port_num << " index " << gid_idx << " failed " << cpp_strerror(errno) << dendl; + ceph_abort(); + } + r = ibv_exp_query_gid_attr(ctxt, port_num, gid_idx, &gid_attr); + if (r) { + lderr(cct) << __func__ << " query gid attributes of port " << port_num << " index " << gid_idx << " failed " << cpp_strerror(errno) << dendl; + ceph_abort(); + } + + if (malformed) break; // stay with gid_idx=0 + if ( (gid_attr.type == cct->_conf->ms_async_rdma_roce_ver) && + (memcmp(&gid, &cgid, 16) == 0) ) { + ldout(cct, 1) << __func__ << " found at index " << gid_idx << dendl; + break; + } + } + + if (gid_idx == port_attr->gid_tbl_len) { + lderr(cct) << __func__ << " Requested local GID was not found in GID table" << dendl; + ceph_abort(); + } +#else + int r = ibv_query_port(ctxt, port_num, port_attr); + if (r == -1) { + lderr(cct) << __func__ << " query port failed " << cpp_strerror(errno) << dendl; + ceph_abort(); + } + + lid = port_attr->lid; + r = ibv_query_gid(ctxt, port_num, 0, &gid); + if (r) { + lderr(cct) << __func__ << " query gid failed " << cpp_strerror(errno) << dendl; + ceph_abort(); + } +#endif +} + + +Device::Device(CephContext *cct, ibv_device* d): device(d), device_attr(new ibv_device_attr), active_port(nullptr) +{ + if (device == NULL) { + lderr(cct) << __func__ << " device == NULL" << cpp_strerror(errno) << dendl; + ceph_abort(); + } + name = ibv_get_device_name(device); + ctxt = ibv_open_device(device); + if (ctxt == NULL) { + lderr(cct) << __func__ << " open rdma device failed. " << cpp_strerror(errno) << dendl; + ceph_abort(); + } + int r = ibv_query_device(ctxt, device_attr); + if (r == -1) { + lderr(cct) << __func__ << " failed to query rdma device. " << cpp_strerror(errno) << dendl; + ceph_abort(); + } +} + +void Device::binding_port(CephContext *cct, int port_num) { + port_cnt = device_attr->phys_port_cnt; + for (uint8_t i = 0; i < port_cnt; ++i) { + Port *port = new Port(cct, ctxt, i+1); + if (i + 1 == port_num && port->get_port_attr()->state == IBV_PORT_ACTIVE) { + active_port = port; + ldout(cct, 1) << __func__ << " found active port " << i+1 << dendl; + break; + } else { + ldout(cct, 10) << __func__ << " port " << i+1 << " is not what we want. state: " << port->get_port_attr()->state << ")"<< dendl; + } + delete port; + } + if (nullptr == active_port) { + lderr(cct) << __func__ << " port not found" << dendl; + assert(active_port); + } +} + Infiniband::QueuePair::QueuePair( - CephContext *c, Device &device, ibv_qp_type type, + CephContext *c, Infiniband& infiniband, ibv_qp_type type, int port, ibv_srq *srq, Infiniband::CompletionQueue* txcq, Infiniband::CompletionQueue* rxcq, uint32_t max_send_wr, uint32_t max_recv_wr, uint32_t q_key) -: cct(c), ibdev(device), +: cct(c), infiniband(infiniband), type(type), - ctxt(ibdev.ctxt), + ctxt(infiniband.device->ctxt), ib_physical_port(port), - pd(ibdev.pd->pd), + pd(infiniband.pd->pd), srq(srq), qp(NULL), txcq(txcq), @@ -52,6 +171,7 @@ Infiniband::QueuePair::QueuePair( lderr(cct) << __func__ << " invalid queue pair type" << cpp_strerror(errno) << dendl; ceph_abort(); } + pd = infiniband.pd->pd; } int Infiniband::QueuePair::init() @@ -226,8 +346,8 @@ bool Infiniband::QueuePair::is_error() const } -Infiniband::CompletionChannel::CompletionChannel(CephContext *c, Device &ibdev) - : cct(c), ibdev(ibdev), channel(NULL), cq(NULL), cq_events_that_need_ack(0) +Infiniband::CompletionChannel::CompletionChannel(CephContext *c, Infiniband &ib) + : cct(c), infiniband(ib), channel(NULL), cq(NULL), cq_events_that_need_ack(0) { } @@ -244,7 +364,7 @@ Infiniband::CompletionChannel::~CompletionChannel() int Infiniband::CompletionChannel::init() { ldout(cct, 20) << __func__ << " started." << dendl; - channel = ibv_create_comp_channel(ibdev.ctxt); + channel = ibv_create_comp_channel(infiniband.device->ctxt); if (!channel) { lderr(cct) << __func__ << " failed to create receive completion channel: " << cpp_strerror(errno) << dendl; @@ -300,7 +420,7 @@ Infiniband::CompletionQueue::~CompletionQueue() int Infiniband::CompletionQueue::init() { - cq = ibv_create_cq(ibdev.ctxt, queue_depth, this, channel->get_channel(), 0); + cq = ibv_create_cq(infiniband.device->ctxt, queue_depth, this, channel->get_channel(), 0); if (!cq) { lderr(cct) << __func__ << " failed to create receive completion queue: " << cpp_strerror(errno) << dendl; @@ -436,6 +556,11 @@ void Infiniband::MemoryManager::Chunk::clear() bound = 0; } +void Infiniband::MemoryManager::Chunk::post_srq(Infiniband *ib) +{ + ib->post_chunk(this); +} + Infiniband::MemoryManager::Cluster::Cluster(MemoryManager& m, uint32_t s) : manager(m), buffer_size(s), lock("cluster_lock") { @@ -584,19 +709,11 @@ int Infiniband::MemoryManager::get_channel_buffers(std::vector &chunks, } -Infiniband::Infiniband(CephContext *cct) - : cct(cct), lock("IB lock") +Infiniband::Infiniband(CephContext *cct, const std::string &device_name, uint8_t port_num) + : cct(cct), lock("IB lock"), device_name(device_name), port_num(port_num) { } -Infiniband::~Infiniband() -{ - if (dispatcher) - dispatcher->polling_stop(); - - delete device_list; -} - void Infiniband::init() { Mutex::Locker l(lock); @@ -604,12 +721,59 @@ void Infiniband::init() if (initialized) return; - device_list = new DeviceList(cct, this); + device_list = new DeviceList(cct); initialized = true; + device = device_list->get_device(device_name.c_str()); + device->binding_port(cct, port_num); + assert(device); + ib_physical_port = device->active_port->get_port_num(); + pd = new ProtectionDomain(cct, device); + assert(NetHandler(cct).set_nonblock(device->ctxt->async_fd) == 0); + + max_recv_wr = device->device_attr->max_srq_wr; + if (max_recv_wr > cct->_conf->ms_async_rdma_receive_buffers) { + max_recv_wr = cct->_conf->ms_async_rdma_receive_buffers; + ldout(cct, 1) << __func__ << " assigning: " << max_recv_wr << " receive buffers" << dendl; + } else { + ldout(cct, 1) << __func__ << " using the max allowed receive buffers: " << max_recv_wr << dendl; + } + + max_send_wr = device->device_attr->max_qp_wr; + if (max_send_wr > cct->_conf->ms_async_rdma_send_buffers) { + max_send_wr = cct->_conf->ms_async_rdma_send_buffers; + ldout(cct, 1) << __func__ << " assigning: " << max_send_wr << " send buffers" << dendl; + } else { + ldout(cct, 1) << __func__ << " using the max allowed send buffers: " << max_send_wr << dendl; + } + + ldout(cct, 1) << __func__ << " device allow " << device->device_attr->max_cqe + << " completion entries" << dendl; + + memory_manager = new MemoryManager(device, pd, + cct->_conf->ms_async_rdma_enable_hugepage); + memory_manager->register_rx_tx( + cct->_conf->ms_async_rdma_buffer_size, max_recv_wr, max_send_wr); + + srq = create_shared_receive_queue(max_recv_wr, MAX_SHARED_RX_SGE_COUNT); + post_channel_cluster(); + dispatcher->polling_start(); } +Infiniband::~Infiniband() +{ + if (!initialized) + return; + + if (dispatcher) + dispatcher->polling_stop(); + + ibv_destroy_srq(srq); + delete memory_manager; + delete pd; +} + void Infiniband::set_dispatcher(RDMADispatcher *d) { assert(!d ^ !dispatcher); @@ -617,14 +781,192 @@ void Infiniband::set_dispatcher(RDMADispatcher *d) dispatcher = d; } -Device* Infiniband::get_device(const char* device_name) +/** + * Create a shared receive queue. This basically wraps the verbs call. + * + * \param[in] max_wr + * The max number of outstanding work requests in the SRQ. + * \param[in] max_sge + * The max number of scatter elements per WR. + * \return + * A valid ibv_srq pointer, or NULL on error. + */ +ibv_srq* Infiniband::create_shared_receive_queue(uint32_t max_wr, uint32_t max_sge) +{ + ibv_srq_init_attr sia; + memset(&sia, 0, sizeof(sia)); + sia.srq_context = device->ctxt; + sia.attr.max_wr = max_wr; + sia.attr.max_sge = max_sge; + return ibv_create_srq(pd->pd, &sia); +} + +int Infiniband::get_tx_buffers(std::vector &c, size_t bytes) +{ + return memory_manager->get_send_buffers(c, bytes); +} + +/** + * Create a new QueuePair. This factory should be used in preference to + * the QueuePair constructor directly, since this lets derivatives of + * Infiniband, e.g. MockInfiniband (if it existed), + * return mocked out QueuePair derivatives. + * + * \return + * QueuePair on success or NULL if init fails + * See QueuePair::QueuePair for parameter documentation. + */ +Infiniband::QueuePair* Infiniband::create_queue_pair(CephContext *cct, CompletionQueue *tx, CompletionQueue* rx, ibv_qp_type type) +{ + Infiniband::QueuePair *qp = new QueuePair( + cct, *this, type, ib_physical_port, srq, tx, rx, max_send_wr, max_recv_wr); + if (qp->init()) { + delete qp; + return NULL; + } + return qp; +} + +int Infiniband::post_chunk(Chunk* chunk) +{ + ibv_sge isge; + isge.addr = reinterpret_cast(chunk->buffer); + isge.length = chunk->bytes; + isge.lkey = chunk->mr->lkey; + ibv_recv_wr rx_work_request; + + memset(&rx_work_request, 0, sizeof(rx_work_request)); + rx_work_request.wr_id = reinterpret_cast(chunk);// stash descriptor ptr + rx_work_request.next = NULL; + rx_work_request.sg_list = &isge; + rx_work_request.num_sge = 1; + + ibv_recv_wr *badWorkRequest; + int ret = ibv_post_srq_recv(srq, &rx_work_request, &badWorkRequest); + if (ret) + return -errno; + return 0; +} + +int Infiniband::post_channel_cluster() +{ + vector free_chunks; + int r = memory_manager->get_channel_buffers(free_chunks, 0); + assert(r > 0); + for (vector::iterator iter = free_chunks.begin(); iter != free_chunks.end(); ++iter) { + r = post_chunk(*iter); + assert(r == 0); + } + return 0; +} + +Infiniband::CompletionChannel* Infiniband::create_comp_channel(CephContext *c) { - return device_list->get_device(device_name); + Infiniband::CompletionChannel *cc = new Infiniband::CompletionChannel(c, *this); + if (cc->init()) { + delete cc; + return NULL; + } + return cc; } -Device *Infiniband::get_device(const struct ibv_context *ctxt) +Infiniband::CompletionQueue* Infiniband::create_comp_queue( + CephContext *cct, CompletionChannel *cc) { - return device_list->get_device(ctxt); + Infiniband::CompletionQueue *cq = new Infiniband::CompletionQueue( + cct, *this, CQ_DEPTH, cc); + if (cq->init()) { + delete cq; + return NULL; + } + return cq; +} + +// 1 means no valid buffer read, 0 means got enough buffer +// else return < 0 means error +int Infiniband::recv_msg(CephContext *cct, int sd, IBSYNMsg& im) +{ + char msg[TCP_MSG_LEN]; + char gid[33]; + ssize_t r = ::read(sd, &msg, sizeof(msg)); + // Drop incoming qpt + if (cct->_conf->ms_inject_socket_failures && sd >= 0) { + if (rand() % cct->_conf->ms_inject_socket_failures == 0) { + ldout(cct, 0) << __func__ << " injecting socket failure" << dendl; + return -EINVAL; + } + } + if (r < 0) { + r = -errno; + lderr(cct) << __func__ << " got error " << r << ": " + << cpp_strerror(r) << dendl; + } else if (r == 0) { // valid disconnect message of length 0 + ldout(cct, 10) << __func__ << " got disconnect message " << dendl; + } else if ((size_t)r != sizeof(msg)) { // invalid message + ldout(cct, 1) << __func__ << " got bad length (" << r << ") " << dendl; + r = -EINVAL; + } else { // valid message + sscanf(msg, "%hu:%x:%x:%x:%s", &(im.lid), &(im.qpn), &(im.psn), &(im.peer_qpn),gid); + wire_gid_to_gid(gid, &(im.gid)); + ldout(cct, 5) << __func__ << " recevd: " << im.lid << ", " << im.qpn << ", " << im.psn << ", " << im.peer_qpn << ", " << gid << dendl; + } + return r; +} + +int Infiniband::send_msg(CephContext *cct, int sd, IBSYNMsg& im) +{ + int retry = 0; + ssize_t r; + + char msg[TCP_MSG_LEN]; + char gid[33]; +retry: + gid_to_wire_gid(&(im.gid), gid); + sprintf(msg, "%04x:%08x:%08x:%08x:%s", im.lid, im.qpn, im.psn, im.peer_qpn, gid); + ldout(cct, 10) << __func__ << " sending: " << im.lid << ", " << im.qpn << ", " << im.psn + << ", " << im.peer_qpn << ", " << gid << dendl; + r = ::write(sd, msg, sizeof(msg)); + // Drop incoming qpt + if (cct->_conf->ms_inject_socket_failures && sd >= 0) { + if (rand() % cct->_conf->ms_inject_socket_failures == 0) { + ldout(cct, 0) << __func__ << " injecting socket failure" << dendl; + return -EINVAL; + } + } + + if ((size_t)r != sizeof(msg)) { + // FIXME need to handle EAGAIN instead of retry + if (r < 0 && (errno == EINTR || errno == EAGAIN) && retry < 3) { + retry++; + goto retry; + } + if (r < 0) + lderr(cct) << __func__ << " send returned error " << errno << ": " + << cpp_strerror(errno) << dendl; + else + lderr(cct) << __func__ << " send got bad length (" << r << ") " << cpp_strerror(errno) << dendl; + return -errno; + } + return 0; +} + +void Infiniband::wire_gid_to_gid(const char *wgid, union ibv_gid *gid) +{ + char tmp[9]; + uint32_t v32; + int i; + + for (tmp[8] = 0, i = 0; i < 4; ++i) { + memcpy(tmp, wgid + i * 8, 8); + sscanf(tmp, "%x", &v32); + *(uint32_t *)(&gid->raw[i * 4]) = ntohl(v32); + } +} + +void Infiniband::gid_to_wire_gid(const union ibv_gid *gid, char wgid[]) +{ + for (int i = 0; i < 4; ++i) + sprintf(&wgid[i * 8], "%08x", htonl(*(uint32_t *)(gid->raw + i * 4))); } Infiniband::QueuePair::~QueuePair() @@ -688,33 +1030,3 @@ const char* Infiniband::qp_state_string(int status) { default: return " out of range."; } } - -void Infiniband::handle_pre_fork() -{ - device_list->uninit(); -} - -int Infiniband::poll_tx(int n, Device **d, ibv_wc *wc) -{ - return device_list->poll_tx(n, d, wc); -} - -int Infiniband::poll_rx(int n, Device **d, ibv_wc *wc) -{ - return device_list->poll_rx(n, d, wc); -} - -int Infiniband::poll_blocking(bool &done) -{ - return device_list->poll_blocking(done); -} - -void Infiniband::rearm_notify() -{ - device_list->rearm_notify(); -} - -void Infiniband::handle_async_event() -{ - device_list->handle_async_event(); -} diff --git a/ceph/src/msg/async/rdma/Infiniband.h b/ceph/src/msg/async/rdma/Infiniband.h index 7394ca92b..e732f08e9 100644 --- a/ceph/src/msg/async/rdma/Infiniband.h +++ b/ceph/src/msg/async/rdma/Infiniband.h @@ -17,24 +17,18 @@ #ifndef CEPH_INFINIBAND_H #define CEPH_INFINIBAND_H -#include - #include #include +#include + #include "include/int_types.h" #include "include/page.h" #include "common/debug.h" #include "common/errno.h" +#include "common/Mutex.h" #include "msg/msg_types.h" #include "msg/async/net_handler.h" -#include "common/Mutex.h" - -#define RDMA_DEBUG 0 - -#if RDMA_DEBUG -#include "ib_dbg.h" -#endif #define HUGE_PAGE_SIZE (2 * 1024 * 1024) #define ALIGN_TO_PAGE_SIZE(x) \ @@ -50,9 +44,84 @@ struct IBSYNMsg { class RDMAStack; class CephContext; -class Port; -class Device; -class DeviceList; + +class Port { + struct ibv_context* ctxt; + int port_num; + struct ibv_port_attr* port_attr; + uint16_t lid; + int gid_idx; + union ibv_gid gid; + + public: + explicit Port(CephContext *cct, struct ibv_context* ictxt, uint8_t ipn); + uint16_t get_lid() { return lid; } + ibv_gid get_gid() { return gid; } + int get_port_num() { return port_num; } + ibv_port_attr* get_port_attr() { return port_attr; } + int get_gid_idx() { return gid_idx; } +}; + + +class Device { + ibv_device *device; + const char* name; + uint8_t port_cnt; + public: + explicit Device(CephContext *c, ibv_device* d); + ~Device() { + if (active_port) { + delete active_port; + assert(ibv_close_device(ctxt) == 0); + } + } + const char* get_name() { return name;} + uint16_t get_lid() { return active_port->get_lid(); } + ibv_gid get_gid() { return active_port->get_gid(); } + int get_gid_idx() { return active_port->get_gid_idx(); } + void binding_port(CephContext *c, int port_num); + struct ibv_context *ctxt; + ibv_device_attr *device_attr; + Port* active_port; +}; + + +class DeviceList { + struct ibv_device ** device_list; + int num; + Device** devices; + public: + DeviceList(CephContext *cct): device_list(ibv_get_device_list(&num)) { + if (device_list == NULL || num == 0) { + lderr(cct) << __func__ << " failed to get rdma device list. " << cpp_strerror(errno) << dendl; + ceph_abort(); + } + devices = new Device*[num]; + + for (int i = 0;i < num; ++i) { + devices[i] = new Device(cct, device_list[i]); + } + } + ~DeviceList() { + for (int i=0; i < num; ++i) { + delete devices[i]; + } + delete []devices; + ibv_free_device_list(device_list); + } + + Device* get_device(const char* device_name) { + assert(devices); + for (int i = 0; i < num; ++i) { + if (!strlen(device_name) || !strcmp(device_name, devices[i]->get_name())) { + return devices[i]; + } + } + return NULL; + } +}; + + class RDMADispatcher; class Infiniband { @@ -83,6 +152,7 @@ class Infiniband { bool full(); bool over(); void clear(); + void post_srq(Infiniband *ib); public: ibv_mr* mr; @@ -147,14 +217,26 @@ class Infiniband { }; private: + uint32_t max_send_wr; + uint32_t max_recv_wr; + uint32_t max_sge; + uint8_t ib_physical_port; + MemoryManager* memory_manager; + ibv_srq* srq; // shared receive work queue + Device *device; + ProtectionDomain *pd; + DeviceList *device_list = nullptr; + RDMADispatcher *dispatcher = nullptr; + void wire_gid_to_gid(const char *wgid, union ibv_gid *gid); + void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]); CephContext *cct; Mutex lock; bool initialized = false; - DeviceList *device_list = nullptr; - RDMADispatcher *dispatcher = nullptr; + const std::string &device_name; + uint8_t port_num; public: - explicit Infiniband(CephContext *c); + explicit Infiniband(CephContext *c, const std::string &device_name, uint8_t p); ~Infiniband(); void init(); @@ -163,13 +245,13 @@ class Infiniband { class CompletionChannel { static const uint32_t MAX_ACK_EVENT = 5000; CephContext *cct; - Device &ibdev; + Infiniband& infiniband; ibv_comp_channel *channel; ibv_cq *cq; uint32_t cq_events_that_need_ack; public: - CompletionChannel(CephContext *c, Device &ibdev); + CompletionChannel(CephContext *c, Infiniband &ib); ~CompletionChannel(); int init(); bool get_cq_event(); @@ -185,9 +267,9 @@ class Infiniband { // You need to call init and it will create a cq and associate to comp channel class CompletionQueue { public: - CompletionQueue(CephContext *c, Device &ibdev, + CompletionQueue(CephContext *c, Infiniband &ib, const uint32_t qd, CompletionChannel *cc) - : cct(c), ibdev(ibdev), channel(cc), cq(NULL), queue_depth(qd) {} + : cct(c), infiniband(ib), channel(cc), cq(NULL), queue_depth(qd) {} ~CompletionQueue(); int init(); int poll_cq(int num_entries, ibv_wc *ret_wc_array); @@ -197,7 +279,7 @@ class Infiniband { CompletionChannel* get_cc() const { return channel; } private: CephContext *cct; - Device &ibdev; + Infiniband& infiniband; // Infiniband to which this QP belongs CompletionChannel *channel; ibv_cq *cq; uint32_t queue_depth; @@ -211,7 +293,7 @@ class Infiniband { // must call plumb() to bring the queue pair to the RTS state. class QueuePair { public: - QueuePair(CephContext *c, Device &device, ibv_qp_type type, + QueuePair(CephContext *c, Infiniband& infiniband, ibv_qp_type type, int ib_physical_port, ibv_srq *srq, Infiniband::CompletionQueue* txcq, Infiniband::CompletionQueue* rxcq, @@ -258,7 +340,7 @@ class Infiniband { private: CephContext *cct; - Device &ibdev; // Infiniband to which this QP belongs + Infiniband& infiniband; // Infiniband to which this QP belongs ibv_qp_type type; // QP type (IBV_QPT_RC, etc.) ibv_context* ctxt; // device context of the HCA to use int ib_physical_port; @@ -275,25 +357,28 @@ class Infiniband { }; public: + typedef MemoryManager::Cluster Cluster; + typedef MemoryManager::Chunk Chunk; + QueuePair* create_queue_pair(CephContext *c, CompletionQueue*, CompletionQueue*, ibv_qp_type type); + ibv_srq* create_shared_receive_queue(uint32_t max_wr, uint32_t max_sge); + int post_chunk(Chunk* chunk); + int post_channel_cluster(); + int get_tx_buffers(std::vector &c, size_t bytes); + CompletionChannel *create_comp_channel(CephContext *c); + CompletionQueue *create_comp_queue(CephContext *c, CompletionChannel *cc=NULL); + uint8_t get_ib_physical_port() { return ib_physical_port; } + int send_msg(CephContext *cct, int sd, IBSYNMsg& msg); + int recv_msg(CephContext *cct, int sd, IBSYNMsg& msg); + uint16_t get_lid() { return device->get_lid(); } + ibv_gid get_gid() { return device->get_gid(); } + MemoryManager* get_memory_manager() { return memory_manager; } + Device* get_device() { return device; } + int get_async_fd() { return device->ctxt->async_fd; } + bool is_tx_buffer(const char* c) { return memory_manager->is_tx_buffer(c);} + bool is_rx_buffer(const char* c) { return memory_manager->is_rx_buffer(c);} + Chunk *get_tx_chunk_by_buffer(const char *c) { return memory_manager->get_tx_chunk_by_buffer(c); } static const char* wc_status_to_string(int status); static const char* qp_state_string(int status); - - void handle_pre_fork(); - - Device* get_device(const char* device_name); - Device* get_device(const struct ibv_context *ctxt); - - int poll_tx(int n, Device **d, ibv_wc *wc); - int poll_rx(int n, Device **d, ibv_wc *wc); - int poll_blocking(bool &done); - void rearm_notify(); - void handle_async_event(); - RDMADispatcher *get_dispatcher() { return dispatcher; } }; -inline ostream& operator<<(ostream& out, const Infiniband::QueuePair &qp) -{ - return out << qp.get_local_qp_number(); -} - #endif diff --git a/ceph/src/msg/async/rdma/RDMAConnTCP.cc b/ceph/src/msg/async/rdma/RDMAConnTCP.cc deleted file mode 100644 index f2c3c9a68..000000000 --- a/ceph/src/msg/async/rdma/RDMAConnTCP.cc +++ /dev/null @@ -1,117 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2016 XSKY - * - * Author: Haomai Wang - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#include "RDMAStack.h" -#include "Device.h" -#include "RDMAConnTCP.h" - -#define dout_subsys ceph_subsys_ms -#undef dout_prefix -#define dout_prefix *_dout << " RDMAConnTCP " - -static const uint32_t TCP_MSG_LEN = sizeof("0000:00000000:00000000:00000000:00000000000000000000000000000000"); - -// 1 means no valid buffer read, 0 means got enough buffer -// else return < 0 means error -int RDMAConnTCP::recv_msg(CephContext *cct, int sd, IBSYNMsg& im) -{ - char msg[TCP_MSG_LEN]; - char gid[33]; - ssize_t r = ::read(sd, &msg, sizeof(msg)); - // Drop incoming qpt - if (cct->_conf->ms_inject_socket_failures && sd >= 0) { - if (rand() % cct->_conf->ms_inject_socket_failures == 0) { - ldout(cct, 0) << __func__ << " injecting socket failure" << dendl; - return -EINVAL; - } - } - if (r < 0) { - r = -errno; - lderr(cct) << __func__ << " got error " << r << ": " - << cpp_strerror(r) << dendl; - } else if (r == 0) { // valid disconnect message of length 0 - ldout(cct, 10) << __func__ << " got disconnect message " << dendl; - } else if ((size_t)r != sizeof(msg)) { // invalid message - ldout(cct, 1) << __func__ << " got bad length (" << r << ") " << dendl; - r = -EINVAL; - } else { // valid message - sscanf(msg, "%hu:%x:%x:%x:%s", &(im.lid), &(im.qpn), &(im.psn), &(im.peer_qpn),gid); - wire_gid_to_gid(gid, &(im.gid)); - ldout(cct, 5) << __func__ << " recevd: " << im.lid << ", " << im.qpn << ", " << im.psn << ", " << im.peer_qpn << ", " << gid << dendl; - } - return r; -} - -int RDMAConnTCP::send_msg(CephContext *cct, int sd, IBSYNMsg& im) -{ - int retry = 0; - ssize_t r; - - char msg[TCP_MSG_LEN]; - char gid[33]; -retry: - gid_to_wire_gid(&(im.gid), gid); - sprintf(msg, "%04x:%08x:%08x:%08x:%s", im.lid, im.qpn, im.psn, im.peer_qpn, gid); - ldout(cct, 10) << __func__ << " sending: " << im.lid << ", " << im.qpn << ", " << im.psn - << ", " << im.peer_qpn << ", " << gid << dendl; - r = ::write(sd, msg, sizeof(msg)); - // Drop incoming qpt - if (cct->_conf->ms_inject_socket_failures && sd >= 0) { - if (rand() % cct->_conf->ms_inject_socket_failures == 0) { - ldout(cct, 0) << __func__ << " injecting socket failure" << dendl; - return -EINVAL; - } - } - - if ((size_t)r != sizeof(msg)) { - // FIXME need to handle EAGAIN instead of retry - if (r < 0 && (errno == EINTR || errno == EAGAIN) && retry < 3) { - retry++; - goto retry; - } - if (r < 0) - lderr(cct) << __func__ << " send returned error " << errno << ": " - << cpp_strerror(errno) << dendl; - else - lderr(cct) << __func__ << " send got bad length (" << r << ") " << cpp_strerror(errno) << dendl; - return -errno; - } - return 0; -} - -void RDMAConnTCP::wire_gid_to_gid(const char *wgid, union ibv_gid *gid) -{ - char tmp[9]; - uint32_t v32; - int i; - - for (tmp[8] = 0, i = 0; i < 4; ++i) { - memcpy(tmp, wgid + i * 8, 8); - sscanf(tmp, "%x", &v32); - *(uint32_t *)(&gid->raw[i * 4]) = ntohl(v32); - } -} - -void RDMAConnTCP::gid_to_wire_gid(const union ibv_gid *gid, char wgid[]) -{ - for (int i = 0; i < 4; ++i) - sprintf(&wgid[i * 8], "%08x", htonl(*(uint32_t *)(gid->raw + i * 4))); -} - -ostream &RDMAConnTCP::print(ostream &out) const -{ - return out << "TCP {tcp_fd: " << tcp_fd << "}"; -} diff --git a/ceph/src/msg/async/rdma/RDMAConnTCP.h b/ceph/src/msg/async/rdma/RDMAConnTCP.h deleted file mode 100644 index 928bb0bdf..000000000 --- a/ceph/src/msg/async/rdma/RDMAConnTCP.h +++ /dev/null @@ -1,89 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2016 XSKY - * - * Author: Haomai Wang - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#ifndef CEPH_MSG_RDMA_CONNECTED_SOCKET_TCP_H -#define CEPH_MSG_RDMA_CONNECTED_SOCKET_TCP_H - -#include "common/ceph_context.h" -#include "common/debug.h" -#include "common/errno.h" -#include "msg/async/Stack.h" -#include "Infiniband.h" -#include "RDMAConnectedSocketImpl.h" - -class RDMAWorker; -class RDMADispatcher; - -struct RDMAConnTCPInfo { - int sd; -}; - -class RDMAConnTCP : public RDMAConnMgr { - class C_handle_connection : public EventCallback { - RDMAConnTCP *cst; - bool active; - public: - C_handle_connection(RDMAConnTCP *w): cst(w), active(true) {}; - void do_request(int fd) { - if (active) - cst->handle_connection(); - }; - void close() { - active = false; - }; - }; - - IBSYNMsg peer_msg; - IBSYNMsg my_msg; - EventCallbackRef con_handler; - int tcp_fd = -1; - - private: - void handle_connection(); - int send_msg(CephContext *cct, int sd, IBSYNMsg& msg); - int recv_msg(CephContext *cct, int sd, IBSYNMsg& msg); - int activate(); - void wire_gid_to_gid(const char *wgid, union ibv_gid *gid); - void gid_to_wire_gid(const union ibv_gid *gid, char wgid[]); - - public: - RDMAConnTCP(CephContext *cct, RDMAConnectedSocketImpl *sock, - Infiniband* ib, RDMADispatcher* s, RDMAWorker *w, - void *info); - virtual ~RDMAConnTCP(); - - virtual ostream &print(ostream &out) const override; - - void set_accept_fd(int sd); - - virtual void cleanup() override; - virtual int try_connect(const entity_addr_t&, const SocketOptions &opt) override; -}; - -class RDMAServerConnTCP : public RDMAServerSocketImpl { - NetHandler net; - int server_setup_socket; - - public: - RDMAServerConnTCP(CephContext *cct, Infiniband* i, RDMADispatcher *s, RDMAWorker *w, entity_addr_t& a); - - int listen(entity_addr_t &sa, const SocketOptions &opt); - virtual int accept(ConnectedSocket *s, const SocketOptions &opts, entity_addr_t *out, Worker *w) override; - virtual void abort_accept() override; - virtual int fd() const override { return server_setup_socket; } -}; - -#endif diff --git a/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.cc b/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.cc index 3014bbbd4..7bd8a80fd 100644 --- a/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.cc +++ b/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.cc @@ -15,111 +15,53 @@ */ #include "RDMAStack.h" -#include "Device.h" -#include "RDMAConnectedSocketImpl.h" -#include "RDMAConnTCP.h" #define dout_subsys ceph_subsys_ms #undef dout_prefix #define dout_prefix *_dout << " RDMAConnectedSocketImpl " -RDMAConnMgr::RDMAConnMgr(CephContext *cct, RDMAConnectedSocketImpl *sock, - Infiniband* ib, RDMADispatcher* s, RDMAWorker *w) - : cct(cct), socket(sock), infiniband(ib), dispatcher(s), worker(w), - is_server(false), active(false), - connected(0) -{ -} - RDMAConnectedSocketImpl::RDMAConnectedSocketImpl(CephContext *cct, Infiniband* ib, RDMADispatcher* s, - RDMAWorker *w, void *info) - : cct(cct), infiniband(ib), dispatcher(s), worker(w), - error(0), lock("RDMAConnectedSocketImpl::lock") -{ - cmgr = new RDMAConnTCP(cct, this, ib, s, w, info); -} - -QueuePair *RDMAConnectedSocketImpl::create_queue_pair(Device *d, int p) + RDMAWorker *w) + : cct(cct), connected(0), error(0), infiniband(ib), + dispatcher(s), worker(w), lock("RDMAConnectedSocketImpl::lock"), + is_server(false), con_handler(new C_handle_connection(this)), + active(false) { - ibdev = d; - ibport = p; - - qp = ibdev->create_queue_pair(ibport, IBV_QPT_RC); - - local_qpn = qp->get_local_qp_number(); - - return qp; -} - -RDMAConnTCP::RDMAConnTCP(CephContext *cct, RDMAConnectedSocketImpl *sock, - Infiniband* ib, RDMADispatcher* s, RDMAWorker *w, - void *_info) - : RDMAConnMgr(cct, sock, ib, s, w), con_handler(new C_handle_connection(this)) -{ - Device *ibdev = ib->get_device(cct->_conf->ms_async_rdma_device_name.c_str()); - int ibport = cct->_conf->ms_async_rdma_port_num; - - assert(ibdev); - assert(ibport > 0); - - ibdev->init(ibport); - - QueuePair *qp = socket->create_queue_pair(ibdev, ibport); - - my_msg.qpn = socket->local_qpn; + qp = infiniband->create_queue_pair( + cct, s->get_tx_cq(), s->get_rx_cq(), IBV_QPT_RC); + my_msg.qpn = qp->get_local_qp_number(); my_msg.psn = qp->get_initial_psn(); - my_msg.lid = ibdev->get_lid(ibport); + my_msg.lid = infiniband->get_lid(); my_msg.peer_qpn = 0; - my_msg.gid = ibdev->get_gid(ibport); - socket->register_qp(qp); - - if (_info) { - RDMAConnTCPInfo *info = (struct RDMAConnTCPInfo *)_info; - - tcp_fd = info->sd; - is_server = true; - worker->center.submit_to(worker->center.get_id(), [this]() { - worker->center.create_file_event(tcp_fd, EVENT_READABLE, con_handler); - }, true); - } -} - -void RDMAConnectedSocketImpl::register_qp(QueuePair *qp) -{ + my_msg.gid = infiniband->get_gid(); notify_fd = dispatcher->register_qp(qp, this); dispatcher->perf_logger->inc(l_msgr_rdma_created_queue_pair); dispatcher->perf_logger->inc(l_msgr_rdma_active_queue_pair); } -RDMAConnTCP::~RDMAConnTCP() -{ - cleanup(); - if (tcp_fd >= 0) - ::close(tcp_fd); -} - RDMAConnectedSocketImpl::~RDMAConnectedSocketImpl() { ldout(cct, 20) << __func__ << " destruct." << dendl; + cleanup(); worker->remove_pending_conn(this); - dispatcher->erase_qpn(local_qpn); + dispatcher->erase_qpn(my_msg.qpn); Mutex::Locker l(lock); if (notify_fd >= 0) ::close(notify_fd); + if (tcp_fd >= 0) + ::close(tcp_fd); error = ECONNRESET; int ret = 0; for (unsigned i=0; i < wc.size(); ++i) { - ret = ibdev->post_chunk(reinterpret_cast(wc[i].wr_id)); + ret = infiniband->post_chunk(reinterpret_cast(wc[i].wr_id)); assert(ret == 0); dispatcher->perf_logger->dec(l_msgr_rdma_inqueue_rx_chunks); } for (unsigned i=0; i < buffers.size(); ++i) { - ret = ibdev->post_chunk(buffers[i]); + ret = infiniband->post_chunk(buffers[i]); assert(ret == 0); dispatcher->perf_logger->dec(l_msgr_rdma_inqueue_rx_chunks); } - - delete cmgr; } void RDMAConnectedSocketImpl::pass_wc(std::vector &&v) @@ -140,16 +82,11 @@ void RDMAConnectedSocketImpl::get_wc(std::vector &w) w.swap(wc); } -int RDMAConnTCP::activate() +int RDMAConnectedSocketImpl::activate() { ibv_qp_attr qpa; int r; - Device *ibdev = socket->get_device(); - int ibport = socket->get_ibport(); - - socket->remote_qpn = peer_msg.qpn; - // now connect up the qps and switch to RTR memset(&qpa, 0, sizeof(qpa)); qpa.qp_state = IBV_QPS_RTR; @@ -163,17 +100,16 @@ int RDMAConnTCP::activate() qpa.ah_attr.grh.hop_limit = 6; qpa.ah_attr.grh.dgid = peer_msg.gid; - qpa.ah_attr.grh.sgid_index = ibdev->get_gid_idx(ibport); + qpa.ah_attr.grh.sgid_index = infiniband->get_device()->get_gid_idx(); qpa.ah_attr.dlid = peer_msg.lid; qpa.ah_attr.sl = cct->_conf->ms_async_rdma_sl; + qpa.ah_attr.grh.traffic_class = cct->_conf->ms_async_rdma_dscp; qpa.ah_attr.src_path_bits = 0; - qpa.ah_attr.port_num = (uint8_t)ibport; + qpa.ah_attr.port_num = (uint8_t)(infiniband->get_ib_physical_port()); ldout(cct, 20) << __func__ << " Choosing gid_index " << (int)qpa.ah_attr.grh.sgid_index << ", sl " << (int)qpa.ah_attr.sl << dendl; - QueuePair *qp = socket->get_qp(); - r = ibv_modify_qp(qp->get_qp(), &qpa, IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU | @@ -227,15 +163,15 @@ int RDMAConnTCP::activate() if (!is_server) { connected = 1; //indicate successfully - ldout(cct, 20) << __func__ << " handle fake send, wake it up. QP: " << *qp << dendl; - socket->submit(false); + ldout(cct, 20) << __func__ << " handle fake send, wake it up. QP: " << my_msg.qpn << dendl; + submit(false); } active = true; return 0; } -int RDMAConnTCP::try_connect(const entity_addr_t& peer_addr, const SocketOptions &opts) { +int RDMAConnectedSocketImpl::try_connect(const entity_addr_t& peer_addr, const SocketOptions &opts) { ldout(cct, 20) << __func__ << " nonblock:" << opts.nonblock << ", nodelay:" << opts.nodelay << ", rbuf_size: " << opts.rcbuf_size << dendl; NetHandler net(cct); @@ -256,7 +192,7 @@ int RDMAConnTCP::try_connect(const entity_addr_t& peer_addr, const SocketOptions ldout(cct, 20) << __func__ << " tcp_fd: " << tcp_fd << dendl; net.set_priority(tcp_fd, opts.priority, peer_addr.get_family()); my_msg.peer_qpn = 0; - r = send_msg(cct, tcp_fd, my_msg); + r = infiniband->send_msg(cct, tcp_fd, my_msg); if (r < 0) return r; @@ -264,14 +200,14 @@ int RDMAConnTCP::try_connect(const entity_addr_t& peer_addr, const SocketOptions return 0; } -void RDMAConnTCP::handle_connection() { - ldout(cct, 20) << __func__ << " " << *socket << dendl; - int r = recv_msg(cct, tcp_fd, peer_msg); +void RDMAConnectedSocketImpl::handle_connection() { + ldout(cct, 20) << __func__ << " QP: " << my_msg.qpn << " tcp_fd: " << tcp_fd << " notify_fd: " << notify_fd << dendl; + int r = infiniband->recv_msg(cct, tcp_fd, peer_msg); if (r < 0) { if (r != -EAGAIN) { dispatcher->perf_logger->inc(l_msgr_rdma_handshake_errors); ldout(cct, 1) << __func__ << " recv handshake msg failed." << dendl; - socket->fault(); + fault(); } return; } @@ -284,12 +220,12 @@ void RDMAConnTCP::handle_connection() { r = activate(); assert(!r); } - socket->notify(); - r = send_msg(cct, tcp_fd, my_msg); + notify(); + r = infiniband->send_msg(cct, tcp_fd, my_msg); if (r < 0) { ldout(cct, 1) << __func__ << " send client ack failed." << dendl; dispatcher->perf_logger->inc(l_msgr_rdma_handshake_errors); - socket->fault(); + fault(); } } else { if (peer_msg.peer_qpn == 0) {// syn from client @@ -297,11 +233,11 @@ void RDMAConnTCP::handle_connection() { ldout(cct, 10) << __func__ << " server is already active." << dendl; return ; } - r = send_msg(cct, tcp_fd, my_msg); + r = infiniband->send_msg(cct, tcp_fd, my_msg); if (r < 0) { ldout(cct, 1) << __func__ << " server ack failed." << dendl; dispatcher->perf_logger->inc(l_msgr_rdma_handshake_errors); - socket->fault(); + fault(); return ; } r = activate(); @@ -309,40 +245,38 @@ void RDMAConnTCP::handle_connection() { } else { // ack from client connected = 1; cleanup(); - socket->submit(false); - socket->notify(); + submit(false); + notify(); } } } -void RDMAConnMgr::post_read() -{ - if (!is_server || connected) - return; - - ldout(cct, 20) << __func__ << " we do not need last handshake, " << *socket << dendl; - connected = 1; //if so, we don't need the last handshake - cleanup(); - socket->submit(false); -} - ssize_t RDMAConnectedSocketImpl::read(char* buf, size_t len) { uint64_t i = 0; int r = ::read(notify_fd, &i, sizeof(i)); - ldout(cct, 20) << __func__ << " notify_fd : " << i << " in " << *qp << " r = " << r << dendl; - if (error) - return -error; + ldout(cct, 20) << __func__ << " notify_fd : " << i << " in " << my_msg.qpn << " r = " << r << dendl; ssize_t read = 0; if (!buffers.empty()) read = read_buffers(buf,len); std::vector cqe; get_wc(cqe); - if (cqe.empty()) - return read == 0 ? -EAGAIN : read; + if (cqe.empty()) { + if (!buffers.empty()) { + notify(); + } + if (read > 0) { + return read; + } + if (error) { + return -error; + } else { + return -EAGAIN; + } + } - ldout(cct, 20) << __func__ << " poll queue got " << cqe.size() << " responses. QP: " << *qp << dendl; + ldout(cct, 20) << __func__ << " poll queue got " << cqe.size() << " responses. QP: " << my_msg.qpn << dendl; for (size_t i = 0; i < cqe.size(); ++i) { ibv_wc* response = &cqe[i]; assert(response->status == IBV_WC_SUCCESS); @@ -352,11 +286,11 @@ ssize_t RDMAConnectedSocketImpl::read(char* buf, size_t len) worker->perf_logger->inc(l_msgr_rdma_rx_bytes, response->byte_len); if (response->byte_len == 0) { dispatcher->perf_logger->inc(l_msgr_rdma_rx_fin); - if (cmgr->connected) { + if (connected) { error = ECONNRESET; ldout(cct, 20) << __func__ << " got remote close msg..." << dendl; } - assert(ibdev->post_chunk(chunk) == 0); + assert(infiniband->post_chunk(chunk) == 0); dispatcher->perf_logger->dec(l_msgr_rdma_inqueue_rx_chunks); } else { if (read == (ssize_t)len) { @@ -368,14 +302,23 @@ ssize_t RDMAConnectedSocketImpl::read(char* buf, size_t len) ldout(cct, 25) << __func__ << " buffers add a chunk: " << chunk->get_offset() << ":" << chunk->get_bound() << dendl; } else { read += chunk->read(buf+read, response->byte_len); - assert(ibdev->post_chunk(chunk) == 0); + assert(infiniband->post_chunk(chunk) == 0); dispatcher->perf_logger->dec(l_msgr_rdma_inqueue_rx_chunks); } } } worker->perf_logger->inc(l_msgr_rdma_rx_chunks, cqe.size()); - cmgr->post_read(); + if (is_server && connected == 0) { + ldout(cct, 20) << __func__ << " we do not need last handshake, QP: " << my_msg.qpn << " peer QP: " << peer_msg.qpn << dendl; + connected = 1; //if so, we don't need the last handshake + cleanup(); + submit(false); + } + + if (!buffers.empty()) { + notify(); + } if (read == 0 && error) return -error; @@ -391,7 +334,7 @@ ssize_t RDMAConnectedSocketImpl::read_buffers(char* buf, size_t len) read += tmp; ldout(cct, 25) << __func__ << " this iter read: " << tmp << " bytes." << " offset: " << (*c)->get_offset() << " ,bound: " << (*c)->get_bound() << ". Chunk:" << *c << dendl; if ((*c)->over()) { - assert(ibdev->post_chunk(*c) == 0); + assert(infiniband->post_chunk(*c) == 0); dispatcher->perf_logger->dec(l_msgr_rdma_inqueue_rx_chunks); ldout(cct, 25) << __func__ << " one chunk over." << dendl; } @@ -457,7 +400,7 @@ ssize_t RDMAConnectedSocketImpl::zero_copy_read(bufferptr &data) ssize_t RDMAConnectedSocketImpl::send(bufferlist &bl, bool more) { if (error) { - if (!cmgr->active) + if (!active) return -EPIPE; return -error; } @@ -467,12 +410,12 @@ ssize_t RDMAConnectedSocketImpl::send(bufferlist &bl, bool more) { Mutex::Locker l(lock); pending_bl.claim_append(bl); - if (!cmgr->connected) { - ldout(cct, 20) << __func__ << " fake send to upper, QP: " << *qp << dendl; + if (!connected) { + ldout(cct, 20) << __func__ << " fake send to upper, QP: " << my_msg.qpn << dendl; return bytes; } } - ldout(cct, 20) << __func__ << " QP: " << *qp << dendl; + ldout(cct, 20) << __func__ << " QP: " << my_msg.qpn << dendl; ssize_t r = submit(more); if (r < 0 && r != -EAGAIN) return r; @@ -530,7 +473,7 @@ ssize_t RDMAConnectedSocketImpl::submit(bool more) unsigned total = 0; unsigned need_reserve_bytes = 0; while (it != pending_bl.buffers().end()) { - if (ibdev->is_tx_buffer(it->raw_c_str())) { + if (infiniband->is_tx_buffer(it->raw_c_str())) { if (need_reserve_bytes) { unsigned copied = fill_tx_via_copy(tx_buffers, need_reserve_bytes, copy_it, it); total += copied; @@ -539,7 +482,7 @@ ssize_t RDMAConnectedSocketImpl::submit(bool more) need_reserve_bytes = 0; } assert(copy_it == it); - tx_buffers.push_back(ibdev->get_tx_chunk_by_buffer(it->raw_c_str())); + tx_buffers.push_back(infiniband->get_tx_chunk_by_buffer(it->raw_c_str())); total += it->length(); ++copy_it; } else { @@ -576,7 +519,7 @@ ssize_t RDMAConnectedSocketImpl::submit(bool more) int RDMAConnectedSocketImpl::post_work_request(std::vector &tx_buffers) { - ldout(cct, 20) << __func__ << " QP: " << *qp << " " << tx_buffers[0] << dendl; + ldout(cct, 20) << __func__ << " QP: " << my_msg.qpn << " " << tx_buffers[0] << dendl; vector::iterator current_buffer = tx_buffers.begin(); ibv_sge isge[tx_buffers.size()]; uint32_t current_sge = 0; @@ -643,7 +586,7 @@ void RDMAConnectedSocketImpl::fin() { } } -void RDMAConnTCP::cleanup() { +void RDMAConnectedSocketImpl::cleanup() { if (con_handler && tcp_fd >= 0) { (static_cast(con_handler))->close(); worker->center.submit_to(worker->center.get_id(), [this]() { @@ -663,27 +606,39 @@ void RDMAConnectedSocketImpl::notify() assert(ret = sizeof(i)); } -void RDMAConnMgr::shutdown() +void RDMAConnectedSocketImpl::shutdown() { - if (!socket->error) - socket->fin(); - socket->error = ECONNRESET; + if (!error) + fin(); + error = ECONNRESET; active = false; } -void RDMAConnMgr::close() +void RDMAConnectedSocketImpl::close() { - shutdown(); + if (!error) + fin(); + error = ECONNRESET; + active = false; } void RDMAConnectedSocketImpl::fault() { - ldout(cct, 1) << __func__ << dendl; + ldout(cct, 1) << __func__ << " tcp fd " << tcp_fd << dendl; /*if (qp) { qp->to_dead(); qp = NULL; }*/ error = ECONNRESET; - cmgr->connected = 1; + connected = 1; notify(); } + +void RDMAConnectedSocketImpl::set_accept_fd(int sd) +{ + tcp_fd = sd; + is_server = true; + worker->center.submit_to(worker->center.get_id(), [this]() { + worker->center.create_file_event(tcp_fd, EVENT_READABLE, con_handler); + }, true); +} diff --git a/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.h b/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.h deleted file mode 100644 index 857bef5c4..000000000 --- a/ceph/src/msg/async/rdma/RDMAConnectedSocketImpl.h +++ /dev/null @@ -1,158 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2016 XSKY - * - * Author: Haomai Wang - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#ifndef CEPH_MSG_RDMA_CONNECTED_SOCKET_IMPL_H -#define CEPH_MSG_RDMA_CONNECTED_SOCKET_IMPL_H - -#include "common/ceph_context.h" -#include "common/debug.h" -#include "common/errno.h" -#include "msg/async/Stack.h" -#include "Infiniband.h" - -class RDMAWorker; -class RDMADispatcher; -class RDMAConnectedSocketImpl; - -typedef Infiniband::QueuePair QueuePair; - -class RDMAConnMgr { - friend class RDMAConnectedSocketImpl; - - protected: - CephContext *cct; - RDMAConnectedSocketImpl *socket; - Infiniband* infiniband; - RDMADispatcher* dispatcher; - RDMAWorker* worker; - - bool is_server; - bool active;// qp is active ? - int connected; - - public: - RDMAConnMgr(CephContext *cct, RDMAConnectedSocketImpl *sock, - Infiniband* ib, RDMADispatcher* s, RDMAWorker *w); - virtual ~RDMAConnMgr() { }; - - virtual ostream &print(ostream &out) const = 0; - - virtual void cleanup() = 0; - virtual int try_connect(const entity_addr_t&, const SocketOptions &opt) = 0; - - void post_read(); - - void shutdown(); - void close(); -}; -inline ostream& operator<<(ostream& out, const RDMAConnMgr &m) -{ - return m.print(out); -} - -class RDMAConnectedSocketImpl : public ConnectedSocketImpl { - friend class RDMAConnMgr; - - protected: - CephContext *cct; - Infiniband* infiniband; - RDMADispatcher* dispatcher; - RDMAWorker* worker; - Device *ibdev = nullptr; - int ibport = -1; - QueuePair *qp = nullptr; - - public: - typedef Infiniband::MemoryManager::Chunk Chunk; - typedef Infiniband::CompletionChannel CompletionChannel; - typedef Infiniband::CompletionQueue CompletionQueue; - - private: - RDMAConnMgr *cmgr; - int error; - std::vector buffers; - int notify_fd = -1; - bufferlist pending_bl; - - Mutex lock; - std::vector wc; - - ssize_t read_buffers(char* buf, size_t len); - int post_work_request(std::vector&); - - public: - uint32_t local_qpn = 0; - uint32_t remote_qpn = 0; - - RDMAConnectedSocketImpl(CephContext *cct, Infiniband* ib, RDMADispatcher* s, - RDMAWorker *w, void *info = nullptr); - virtual ~RDMAConnectedSocketImpl(); - - ostream &print(ostream &out) const { - return out << "socket {lqpn: " << local_qpn << " rqpn: " << remote_qpn << " " << *cmgr << "}"; - }; - - Device *get_device() { return ibdev; }; - int get_ibport() { return ibport; }; - - void pass_wc(std::vector &&v); - void get_wc(std::vector &w); - virtual int is_connected() override { return cmgr->connected; } - - virtual ssize_t read(char* buf, size_t len) override; - virtual ssize_t zero_copy_read(bufferptr &data) override; - virtual ssize_t send(bufferlist &bl, bool more) override; - virtual void shutdown() override { cmgr->shutdown(); }; - virtual void close() override { cmgr->close(); }; - virtual int fd() const override { return notify_fd; } - void fault(); - const char* get_qp_state() { return Infiniband::qp_state_string(qp->get_state()); } - QueuePair *get_qp() { return qp; }; - ssize_t submit(bool more); - void fin(); - void register_qp(QueuePair *qp); - void notify(); - - QueuePair *create_queue_pair(Device *d, int p); - int try_connect(const entity_addr_t &sa, const SocketOptions &opt) { return cmgr->try_connect(sa, opt); }; -}; -inline ostream& operator<<(ostream& out, const RDMAConnectedSocketImpl &s) -{ - return s.print(out); -} - - -class RDMAServerSocketImpl : public ServerSocketImpl { - protected: - CephContext *cct; - Device *ibdev; - int ibport; - Infiniband* infiniband; - RDMADispatcher *dispatcher; - RDMAWorker *worker; - entity_addr_t sa; - - public: - RDMAServerSocketImpl(CephContext *cct, Infiniband* i, RDMADispatcher *s, RDMAWorker *w, entity_addr_t& a); - - virtual int listen(entity_addr_t &sa, const SocketOptions &opt) = 0; - virtual int accept(ConnectedSocket *s, const SocketOptions &opts, entity_addr_t *out, Worker *w) = 0; - virtual void abort_accept() = 0; - virtual int fd() const = 0; -}; - -#endif - diff --git a/ceph/src/msg/async/rdma/RDMAServerSocketImpl.cc b/ceph/src/msg/async/rdma/RDMAServerSocketImpl.cc index a9665d96e..8f5fd81d3 100644 --- a/ceph/src/msg/async/rdma/RDMAServerSocketImpl.cc +++ b/ceph/src/msg/async/rdma/RDMAServerSocketImpl.cc @@ -16,31 +16,17 @@ #include "msg/async/net_handler.h" #include "RDMAStack.h" -#include "Device.h" -#include "RDMAConnTCP.h" #define dout_subsys ceph_subsys_ms #undef dout_prefix #define dout_prefix *_dout << " RDMAServerSocketImpl " RDMAServerSocketImpl::RDMAServerSocketImpl(CephContext *cct, Infiniband* i, RDMADispatcher *s, RDMAWorker *w, entity_addr_t& a) - : cct(cct), infiniband(i), dispatcher(s), worker(w), sa(a) + : cct(cct), net(cct), server_setup_socket(-1), infiniband(i), dispatcher(s), worker(w), sa(a) { } -RDMAServerConnTCP::RDMAServerConnTCP(CephContext *cct, Infiniband* i, RDMADispatcher *s, RDMAWorker *w, entity_addr_t& a) - : RDMAServerSocketImpl(cct, i, s, w, a), net(cct), server_setup_socket(-1) -{ - ibdev = infiniband->get_device(cct->_conf->ms_async_rdma_device_name.c_str()); - ibport = cct->_conf->ms_async_rdma_port_num; - - assert(ibdev); - assert(ibport > 0); - - ibdev->init(ibport); -} - -int RDMAServerConnTCP::listen(entity_addr_t &sa, const SocketOptions &opt) +int RDMAServerSocketImpl::listen(entity_addr_t &sa, const SocketOptions &opt) { int rc = 0; server_setup_socket = net.create_socket(sa.get_family(), true); @@ -86,7 +72,7 @@ err: return -errno; } -int RDMAServerConnTCP::accept(ConnectedSocket *sock, const SocketOptions &opt, entity_addr_t *out, Worker *w) +int RDMAServerSocketImpl::accept(ConnectedSocket *sock, const SocketOptions &opt, entity_addr_t *out, Worker *w) { ldout(cct, 15) << __func__ << dendl; @@ -116,10 +102,10 @@ int RDMAServerConnTCP::accept(ConnectedSocket *sock, const SocketOptions &opt, e out->set_sockaddr((sockaddr*)&ss); net.set_priority(sd, opt.priority, out->get_family()); - RDMAConnectedSocketImpl *server; + RDMAConnectedSocketImpl* server; //Worker* w = dispatcher->get_stack()->get_worker(); - RDMAConnTCPInfo conn_info = { sd }; - server = new RDMAConnectedSocketImpl(cct, infiniband, dispatcher, dynamic_cast(w), &conn_info); + server = new RDMAConnectedSocketImpl(cct, infiniband, dispatcher, dynamic_cast(w)); + server->set_accept_fd(sd); ldout(cct, 20) << __func__ << " accepted a new QP, tcp_fd: " << sd << dendl; std::unique_ptr csi(server); *sock = ConnectedSocket(std::move(csi)); @@ -127,7 +113,7 @@ int RDMAServerConnTCP::accept(ConnectedSocket *sock, const SocketOptions &opt, e return 0; } -void RDMAServerConnTCP::abort_accept() +void RDMAServerSocketImpl::abort_accept() { if (server_setup_socket >= 0) ::close(server_setup_socket); diff --git a/ceph/src/msg/async/rdma/RDMAStack.cc b/ceph/src/msg/async/rdma/RDMAStack.cc index b1dae3bcf..020dd9853 100644 --- a/ceph/src/msg/async/rdma/RDMAStack.cc +++ b/ceph/src/msg/async/rdma/RDMAStack.cc @@ -14,6 +14,7 @@ * */ +#include #include #include @@ -21,8 +22,6 @@ #include "common/deleter.h" #include "common/Tub.h" #include "RDMAStack.h" -#include "RDMAConnTCP.h" -#include "Device.h" #define dout_subsys ceph_subsys_ms #undef dout_prefix @@ -32,20 +31,28 @@ static Tub global_infiniband; RDMADispatcher::~RDMADispatcher() { + done = true; polling_stop(); - ldout(cct, 20) << __func__ << " destructing rdma dispatcher" << dendl; - global_infiniband->set_dispatcher(nullptr); - assert(qp_conns.empty()); assert(num_qp_conn == 0); assert(dead_queue_pairs.empty()); assert(num_dead_queue_pair == 0); + + tx_cc->ack_events(); + rx_cc->ack_events(); + delete tx_cq; + delete rx_cq; + delete tx_cc; + delete rx_cc; + delete async_handler; + + global_infiniband->set_dispatcher(nullptr); } RDMADispatcher::RDMADispatcher(CephContext* c, RDMAStack* s) - : cct(c), lock("RDMADispatcher::lock"), + : cct(c), async_handler(new C_handle_cq_async(this)), lock("RDMADispatcher::lock"), w_lock("RDMADispatcher::for worker pending list"), stack(s) { PerfCountersBuilder plb(cct, "AsyncMessenger::RDMADispatcher", l_msgr_rdma_dispatcher_first, l_msgr_rdma_dispatcher_last); @@ -78,41 +85,58 @@ RDMADispatcher::RDMADispatcher(CephContext* c, RDMAStack* s) void RDMADispatcher::polling_start() { + tx_cc = global_infiniband->create_comp_channel(cct); + assert(tx_cc); + rx_cc = global_infiniband->create_comp_channel(cct); + assert(rx_cc); + tx_cq = global_infiniband->create_comp_queue(cct, tx_cc); + assert(tx_cq); + rx_cq = global_infiniband->create_comp_queue(cct, rx_cc); + assert(rx_cq); + t = std::thread(&RDMADispatcher::polling, this); } void RDMADispatcher::polling_stop() { - if (!t.joinable()) - return; - - done = true; - t.join(); + if (t.joinable()) + t.join(); } -void RDMADispatcher::process_async_event(Device *ibdev, ibv_async_event &async_event) +void RDMADispatcher::handle_async_event() { - perf_logger->inc(l_msgr_rdma_total_async_events); - // FIXME: Currently we must ensure no other factor make QP in ERROR state, - // otherwise this qp can't be deleted in current cleanup flow. - if (async_event.event_type == IBV_EVENT_QP_LAST_WQE_REACHED) { - perf_logger->inc(l_msgr_rdma_async_last_wqe_events); - uint64_t qpn = async_event.element.qp->qp_num; - ldout(cct, 10) << __func__ << " event associated qp=" << async_event.element.qp - << " evt: " << ibv_event_type_str(async_event.event_type) << dendl; - Mutex::Locker l(lock); - RDMAConnectedSocketImpl *conn = get_conn_lockless(qpn); - if (!conn) { - ldout(cct, 1) << __func__ << " missing qp_num=" << qpn << " discard event" << dendl; + ldout(cct, 30) << __func__ << dendl; + while (1) { + ibv_async_event async_event; + if (ibv_get_async_event(global_infiniband->get_device()->ctxt, &async_event)) { + if (errno != EAGAIN) + lderr(cct) << __func__ << " ibv_get_async_event failed. (errno=" << errno + << " " << cpp_strerror(errno) << ")" << dendl; + return; + } + perf_logger->inc(l_msgr_rdma_total_async_events); + // FIXME: Currently we must ensure no other factor make QP in ERROR state, + // otherwise this qp can't be deleted in current cleanup flow. + if (async_event.event_type == IBV_EVENT_QP_LAST_WQE_REACHED) { + perf_logger->inc(l_msgr_rdma_async_last_wqe_events); + uint64_t qpn = async_event.element.qp->qp_num; + ldout(cct, 10) << __func__ << " event associated qp=" << async_event.element.qp + << " evt: " << ibv_event_type_str(async_event.event_type) << dendl; + Mutex::Locker l(lock); + RDMAConnectedSocketImpl *conn = get_conn_lockless(qpn); + if (!conn) { + ldout(cct, 1) << __func__ << " missing qp_num=" << qpn << " discard event" << dendl; + } else { + ldout(cct, 1) << __func__ << " it's not forwardly stopped by us, reenable=" << conn << dendl; + conn->fault(); + erase_qpn_lockless(qpn); + } } else { - ldout(cct, 1) << __func__ << " it's not forwardly stopped by us, reenable=" << conn << dendl; - conn->fault(); - erase_qpn_lockless(qpn); + ldout(cct, 1) << __func__ << " ibv_get_async_event: dev=" << global_infiniband->get_device()->ctxt + << " evt: " << ibv_event_type_str(async_event.event_type) + << dendl; } - } else { - ldout(cct, 1) << __func__ << " ibv_get_async_event: dev=" << *ibdev - << " evt: " << ibv_event_type_str(async_event.event_type) - << dendl; + ibv_ack_async_event(&async_event); } } @@ -123,24 +147,23 @@ void RDMADispatcher::polling() std::map > polled; std::vector tx_cqe; + ldout(cct, 20) << __func__ << " going to poll tx cq: " << tx_cq << " rx cq: " << rx_cq << dendl; RDMAConnectedSocketImpl *conn = nullptr; utime_t last_inactive = ceph_clock_now(); bool rearmed = false; int r = 0; while (true) { - Device *ibdev; - - int tx_ret = global_infiniband->poll_tx(MAX_COMPLETIONS, &ibdev, wc); + int tx_ret = tx_cq->poll_cq(MAX_COMPLETIONS, wc); if (tx_ret > 0) { ldout(cct, 20) << __func__ << " tx completion queue got " << tx_ret << " responses."<< dendl; - handle_tx_event(ibdev, wc, tx_ret); + handle_tx_event(wc, tx_ret); } - int rx_ret = global_infiniband->poll_rx(MAX_COMPLETIONS, &ibdev, wc); + int rx_ret = rx_cq->poll_cq(MAX_COMPLETIONS, wc); if (rx_ret > 0) { - ldout(cct, 20) << __func__ << " rx completion queue got " << rx_ret + ldout(cct, 20) << __func__ << " rt completion queue got " << rx_ret << " responses."<< dendl; perf_logger->inc(l_msgr_rdma_rx_total_wc, rx_ret); @@ -155,8 +178,8 @@ void RDMADispatcher::polling() if (response->status == IBV_WC_SUCCESS) { conn = get_conn_lockless(response->qp_num); if (!conn) { - assert(ibdev->is_rx_buffer(chunk->buffer)); - r = ibdev->post_chunk(chunk); + assert(global_infiniband->is_rx_buffer(chunk->buffer)); + r = global_infiniband->post_chunk(chunk); ldout(cct, 1) << __func__ << " csi with qpn " << response->qp_num << " may be dead. chunk " << chunk << " will be back ? " << r << dendl; assert(r == 0); } else { @@ -166,9 +189,9 @@ void RDMADispatcher::polling() perf_logger->inc(l_msgr_rdma_rx_total_wc_errors); ldout(cct, 1) << __func__ << " work request returned error for buffer(" << chunk << ") status(" << response->status << ":" - << Infiniband::wc_status_to_string(response->status) << ")" << dendl; - assert(ibdev->is_rx_buffer(chunk->buffer)); - r = ibdev->post_chunk(chunk); + << global_infiniband->wc_status_to_string(response->status) << ")" << dendl; + assert(global_infiniband->is_rx_buffer(chunk->buffer)); + r = global_infiniband->post_chunk(chunk); if (r) { ldout(cct, 0) << __func__ << " post chunk failed, error: " << cpp_strerror(r) << dendl; assert(r == 0); @@ -208,20 +231,37 @@ void RDMADispatcher::polling() break; if ((ceph_clock_now() - last_inactive).to_nsec() / 1000 > cct->_conf->ms_async_rdma_polling_us) { + handle_async_event(); if (!rearmed) { // Clean up cq events after rearm notify ensure no new incoming event // arrived between polling and rearm - global_infiniband->rearm_notify(); + tx_cq->rearm_notify(); + rx_cq->rearm_notify(); rearmed = true; continue; } + struct pollfd channel_poll[2]; + channel_poll[0].fd = tx_cc->get_fd(); + channel_poll[0].events = POLLIN | POLLERR | POLLNVAL | POLLHUP; + channel_poll[0].revents = 0; + channel_poll[1].fd = rx_cc->get_fd(); + channel_poll[1].events = POLLIN | POLLERR | POLLNVAL | POLLHUP; + channel_poll[1].revents = 0; + r = 0; perf_logger->set(l_msgr_rdma_polling, 0); - - r = global_infiniband->poll_blocking(done); - if (r > 0) - ldout(cct, 20) << __func__ << " got a cq event." << dendl; - + while (!done && r == 0) { + r = poll(channel_poll, 2, 100); + if (r < 0) { + r = -errno; + lderr(cct) << __func__ << " poll failed " << r << dendl; + ceph_abort(); + } + } + if (r > 0 && tx_cc->get_cq_event()) + ldout(cct, 20) << __func__ << " got tx cq event." << dendl; + if (r > 0 && rx_cc->get_cq_event()) + ldout(cct, 20) << __func__ << " got rx cq event." << dendl; last_inactive = ceph_clock_now(); perf_logger->set(l_msgr_rdma_polling, 1); rearmed = false; @@ -284,7 +324,7 @@ void RDMADispatcher::erase_qpn(uint32_t qpn) erase_qpn_lockless(qpn); } -void RDMADispatcher::handle_tx_event(Device *ibdev, ibv_wc *cqe, int n) +void RDMADispatcher::handle_tx_event(ibv_wc *cqe, int n) { std::vector tx_chunks; @@ -322,15 +362,20 @@ void RDMADispatcher::handle_tx_event(Device *ibdev, ibv_wc *cqe, int n) } } - // FIXME: why not tx? - if (ibdev->get_memory_manager()->is_tx_buffer(chunk->buffer)) + //TX completion may come either from regular send message or from 'fin' message. + //In the case of 'fin' wr_id points to the QueuePair. + if (global_infiniband->get_memory_manager()->is_tx_buffer(chunk->buffer)) { tx_chunks.push_back(chunk); - else + } else if (reinterpret_cast(response->wr_id)->get_local_qp_number() == response->qp_num ) { + ldout(cct, 1) << __func__ << " sending of the disconnect msg completed" << dendl; + } else { ldout(cct, 1) << __func__ << " not tx buffer, chunk " << chunk << dendl; + ceph_abort(); + } } perf_logger->inc(l_msgr_rdma_tx_total_wc, n); - post_tx_buffer(ibdev, tx_chunks); + post_tx_buffer(tx_chunks); } /** @@ -341,13 +386,13 @@ void RDMADispatcher::handle_tx_event(Device *ibdev, ibv_wc *cqe, int n) * \return * 0 if success or -1 for failure */ -void RDMADispatcher::post_tx_buffer(Device *ibdev, std::vector &chunks) +void RDMADispatcher::post_tx_buffer(std::vector &chunks) { if (chunks.empty()) return ; inflight -= chunks.size(); - ibdev->get_memory_manager()->return_tx(chunks); + global_infiniband->get_memory_manager()->return_tx(chunks); ldout(cct, 30) << __func__ << " release " << chunks.size() << " chunks, inflight " << inflight << dendl; notify_pending_workers(); @@ -393,7 +438,7 @@ int RDMAWorker::listen(entity_addr_t &sa, const SocketOptions &opt,ServerSocket { global_infiniband->init(); - auto p = new RDMAServerConnTCP(cct, global_infiniband.get(), get_stack()->get_dispatcher(), this, sa); + auto p = new RDMAServerSocketImpl(cct, global_infiniband.get(), get_stack()->get_dispatcher(), this, sa); int r = p->listen(sa, opt); if (r < 0) { delete p; @@ -423,12 +468,10 @@ int RDMAWorker::connect(const entity_addr_t &addr, const SocketOptions &opts, Co int RDMAWorker::get_reged_mem(RDMAConnectedSocketImpl *o, std::vector &c, size_t bytes) { - Device *ibdev = o->get_device(); - assert(center.in_thread()); - int r = ibdev->get_tx_buffers(c, bytes); + int r = global_infiniband->get_tx_buffers(c, bytes); assert(r >= 0); - size_t got = ibdev->get_memory_manager()->get_tx_buffer_size() * r; + size_t got = global_infiniband->get_memory_manager()->get_tx_buffer_size() * r; ldout(cct, 30) << __func__ << " need " << bytes << " bytes, reserve " << got << " registered bytes, inflight " << dispatcher->inflight << dendl; stack->get_dispatcher()->inflight += r; if (got == bytes) @@ -473,12 +516,23 @@ RDMAStack::RDMAStack(CephContext *cct, const string &t): NetworkStack(cct, t) // //On RDMA MUST be called before fork // + int rc = ibv_fork_init(); if (rc) { lderr(cct) << __func__ << " failed to call ibv_for_init(). On RDMA must be called before fork. Application aborts." << dendl; ceph_abort(); } + ldout(cct, 1) << __func__ << " ms_async_rdma_enable_hugepage value is: " << cct->_conf->ms_async_rdma_enable_hugepage << dendl; + if (cct->_conf->ms_async_rdma_enable_hugepage) { + rc = setenv("RDMAV_HUGEPAGES_SAFE","1",1); + ldout(cct, 1) << __func__ << " RDMAV_HUGEPAGES_SAFE is set as: " << getenv("RDMAV_HUGEPAGES_SAFE") << dendl; + if (rc) { + lderr(cct) << __func__ << " failed to export RDMA_HUGEPAGES_SAFE. On RDMA must be exported before using huge pages. Application aborts." << dendl; + ceph_abort(); + } + } + //Check ulimit struct rlimit limit; getrlimit(RLIMIT_MEMLOCK, &limit); @@ -488,7 +542,8 @@ RDMAStack::RDMAStack(CephContext *cct, const string &t): NetworkStack(cct, t) } if (!global_infiniband) - global_infiniband.construct(cct); + global_infiniband.construct( + cct, cct->_conf->ms_async_rdma_device_name, cct->_conf->ms_async_rdma_port_num); ldout(cct, 20) << __func__ << " constructing RDMAStack..." << dendl; dispatcher = new RDMADispatcher(cct, this); global_infiniband->set_dispatcher(dispatcher); @@ -504,6 +559,10 @@ RDMAStack::RDMAStack(CephContext *cct, const string &t): NetworkStack(cct, t) RDMAStack::~RDMAStack() { + if (cct->_conf->ms_async_rdma_enable_hugepage) { + unsetenv("RDMAV_HUGEPAGES_SAFE"); //remove env variable on destruction + } + delete dispatcher; } diff --git a/ceph/src/msg/async/rdma/RDMAStack.h b/ceph/src/msg/async/rdma/RDMAStack.h index ef1188b80..4f93c157f 100644 --- a/ceph/src/msg/async/rdma/RDMAStack.h +++ b/ceph/src/msg/async/rdma/RDMAStack.h @@ -28,7 +28,6 @@ #include "common/errno.h" #include "msg/async/Stack.h" #include "Infiniband.h" -#include "RDMAConnectedSocketImpl.h" class RDMAConnectedSocketImpl; class RDMAServerSocketImpl; @@ -69,6 +68,10 @@ class RDMADispatcher { std::thread t; CephContext *cct; + Infiniband::CompletionQueue* tx_cq; + Infiniband::CompletionQueue* rx_cq; + Infiniband::CompletionChannel *tx_cc, *rx_cc; + EventCallbackRef async_handler; bool done = false; std::atomic num_dead_queue_pair = {0}; std::atomic num_qp_conn = {0}; @@ -101,18 +104,26 @@ class RDMADispatcher { std::list pending_workers; RDMAStack* stack; + class C_handle_cq_async : public EventCallback { + RDMADispatcher *dispatcher; + public: + C_handle_cq_async(RDMADispatcher *w): dispatcher(w) {} + void do_request(int fd) { + // worker->handle_tx_event(); + dispatcher->handle_async_event(); + } + }; + public: PerfCounters *perf_logger; explicit RDMADispatcher(CephContext* c, RDMAStack* s); virtual ~RDMADispatcher(); - - void process_async_event(Device *ibdev, ibv_async_event &async_event); + void handle_async_event(); void polling_start(); void polling_stop(); void polling(); - int register_qp(QueuePair *qp, RDMAConnectedSocketImpl* csi); void make_pending_worker(RDMAWorker* w) { Mutex::Locker l(w_lock); @@ -125,9 +136,11 @@ class RDMADispatcher { RDMAConnectedSocketImpl* get_conn_lockless(uint32_t qp); void erase_qpn_lockless(uint32_t qpn); void erase_qpn(uint32_t qpn); + Infiniband::CompletionQueue* get_tx_cq() const { return tx_cq; } + Infiniband::CompletionQueue* get_rx_cq() const { return rx_cq; } void notify_pending_workers(); - void handle_tx_event(Device *ibdev, ibv_wc *cqe, int n); - void post_tx_buffer(Device *ibdev, std::vector &chunks); + void handle_tx_event(ibv_wc *cqe, int n); + void post_tx_buffer(std::vector &chunks); std::atomic inflight = {0}; }; @@ -190,6 +203,95 @@ class RDMAWorker : public Worker { } }; +class RDMAConnectedSocketImpl : public ConnectedSocketImpl { + public: + typedef Infiniband::MemoryManager::Chunk Chunk; + typedef Infiniband::CompletionChannel CompletionChannel; + typedef Infiniband::CompletionQueue CompletionQueue; + + private: + CephContext *cct; + Infiniband::QueuePair *qp; + IBSYNMsg peer_msg; + IBSYNMsg my_msg; + int connected; + int error; + Infiniband* infiniband; + RDMADispatcher* dispatcher; + RDMAWorker* worker; + std::vector buffers; + int notify_fd = -1; + bufferlist pending_bl; + + Mutex lock; + std::vector wc; + bool is_server; + EventCallbackRef con_handler; + int tcp_fd = -1; + bool active;// qp is active ? + + void notify(); + ssize_t read_buffers(char* buf, size_t len); + int post_work_request(std::vector&); + + public: + RDMAConnectedSocketImpl(CephContext *cct, Infiniband* ib, RDMADispatcher* s, + RDMAWorker *w); + virtual ~RDMAConnectedSocketImpl(); + + void pass_wc(std::vector &&v); + void get_wc(std::vector &w); + virtual int is_connected() override { return connected; } + + virtual ssize_t read(char* buf, size_t len) override; + virtual ssize_t zero_copy_read(bufferptr &data) override; + virtual ssize_t send(bufferlist &bl, bool more) override; + virtual void shutdown() override; + virtual void close() override; + virtual int fd() const override { return notify_fd; } + void fault(); + const char* get_qp_state() { return Infiniband::qp_state_string(qp->get_state()); } + ssize_t submit(bool more); + int activate(); + void fin(); + void handle_connection(); + void cleanup(); + void set_accept_fd(int sd); + int try_connect(const entity_addr_t&, const SocketOptions &opt); + + class C_handle_connection : public EventCallback { + RDMAConnectedSocketImpl *csi; + bool active; + public: + C_handle_connection(RDMAConnectedSocketImpl *w): csi(w), active(true) {} + void do_request(int fd) { + if (active) + csi->handle_connection(); + } + void close() { + active = false; + } + }; +}; + +class RDMAServerSocketImpl : public ServerSocketImpl { + CephContext *cct; + NetHandler net; + int server_setup_socket; + Infiniband* infiniband; + RDMADispatcher *dispatcher; + RDMAWorker *worker; + entity_addr_t sa; + + public: + RDMAServerSocketImpl(CephContext *cct, Infiniband* i, RDMADispatcher *s, RDMAWorker *w, entity_addr_t& a); + + int listen(entity_addr_t &sa, const SocketOptions &opt); + virtual int accept(ConnectedSocket *s, const SocketOptions &opts, entity_addr_t *out, Worker *w) override; + virtual void abort_accept() override; + virtual int fd() const override { return server_setup_socket; } + int get_fd() { return server_setup_socket; } +}; class RDMAStack : public NetworkStack { vector threads; @@ -211,4 +313,5 @@ class RDMAStack : public NetworkStack { virtual bool is_ready() override { return fork_finished.load(); }; virtual void ready() override { fork_finished = true; }; }; + #endif diff --git a/ceph/src/msg/async/rdma/ib_dbg.h b/ceph/src/msg/async/rdma/ib_dbg.h deleted file mode 100644 index aac698d26..000000000 --- a/ceph/src/msg/async/rdma/ib_dbg.h +++ /dev/null @@ -1,387 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#ifndef __IB_DBG_H__ -#define __IB_DBG_H__ - -#define dout_subsys ceph_subsys_ms -#undef dout_prefix -#define dout_prefix *_dout << "ib_dbg " - -#define ibdbg_ldout \ - if (g_ceph_context && g_ceph_context->_log) \ - ldout(g_ceph_context,1) << f << ":" << l << " ib command: " << __func__ - -static inline struct ibv_srq *_ibv_create_srq(const char *f, int l, - struct ibv_pd *pd, - struct ibv_srq_init_attr *srq_init_attr) -{ - auto ret = ibv_create_srq(pd, srq_init_attr); - - ibdbg_ldout << " pd: " << pd << - " | srq: " << ret << dendl; - - return ret; -} -#define ibv_create_srq(...) _ibv_create_srq(__func__, __LINE__, __VA_ARGS__) - -static inline void _ibv_ack_cq_events(const char *f, int l, - struct ibv_cq *cq, unsigned int nevents) -{ - ibdbg_ldout << " cq: " << cq << " nevents: " << nevents << dendl; - - ibv_ack_cq_events(cq, nevents); -} -#define ibv_ack_cq_events(...) _ibv_ack_cq_events(__func__, __LINE__, __VA_ARGS__) - -static inline struct ibv_pd *_ibv_alloc_pd(const char *f, int l, - struct ibv_context *context) -{ - auto ret = ibv_alloc_pd(context); - - - ibdbg_ldout << " ctxt: " << context << - " | pd: " << ret << dendl; - - return ret; -} -#define ibv_alloc_pd(...) _ibv_alloc_pd(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_close_device(const char *f, int l, - struct ibv_context *context) -{ - auto ret = ibv_close_device(context); - - ibdbg_ldout << " ctxt: " << context << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_close_device(...) _ibv_close_device(__func__, __LINE__, __VA_ARGS__) - -static inline struct ibv_comp_channel *_ibv_create_comp_channel(const char *f, int l, - struct ibv_context *context) -{ - auto ret = ibv_create_comp_channel(context); - - ibdbg_ldout << " ctxt: " << context << - " | channel: " << ret << " fd: " << ( ret ? ret->fd : -1 ) << dendl; - - return ret; -} -#define ibv_create_comp_channel(...) _ibv_create_comp_channel(__func__, __LINE__, __VA_ARGS__) - -static inline struct ibv_cq *_ibv_create_cq(const char *f, int l, - struct ibv_context *context, int cqe, - void *cq_context, - struct ibv_comp_channel *channel, - int comp_vector) -{ - auto ret = ibv_create_cq(context, cqe, cq_context, channel, comp_vector); - - ibdbg_ldout << " context: " << context << " channel: " << channel << - " | cq: " << ret << dendl; - - return ret; -} -#define ibv_create_cq(...) _ibv_create_cq(__func__, __LINE__, __VA_ARGS__) - -static inline struct ibv_qp *_ibv_create_qp(const char *f, int l, - struct ibv_pd *pd, - struct ibv_qp_init_attr *qp_init_attr) -{ - auto ret = ibv_create_qp(pd, qp_init_attr); - - ibdbg_ldout << " pd: " << pd << - " send_cq: " << qp_init_attr->send_cq << - " recv_cq: " << qp_init_attr->recv_cq << - " srq: " << qp_init_attr->srq << - " | qp: " << ret << dendl; - - return ret; -} -#define ibv_create_qp(...) _ibv_create_qp(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_dealloc_pd(const char *f, int l, - struct ibv_pd *pd) -{ - auto ret = ibv_dealloc_pd(pd); - - ibdbg_ldout << " pd: " << pd << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_dealloc_pd(...) _ibv_dealloc_pd(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_destroy_comp_channel(const char *f, int l, - struct ibv_comp_channel *channel) -{ - auto ret = ibv_destroy_comp_channel(channel); - - ibdbg_ldout << " channel: " << channel << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_destroy_comp_channel(...) _ibv_destroy_comp_channel(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_destroy_cq(const char *f, int l, - struct ibv_cq *cq) -{ - auto ret = ibv_destroy_cq(cq); - - if (ret) { - ibdbg_ldout << " cq: " << cq << - " | ret: " << cpp_strerror(ret) << dendl; - } else { - ibdbg_ldout << " cq: " << cq << - " | ret: " << ret << dendl; - } - - return ret; -} -#define ibv_destroy_cq(...) _ibv_destroy_cq(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_destroy_qp(const char *f, int l, - struct ibv_qp *qp) -{ - auto ret = ibv_destroy_qp(qp); - - ibdbg_ldout << " qp: " << qp << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_destroy_qp(...) _ibv_destroy_qp(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_destroy_srq(const char *f, int l, - struct ibv_srq *srq) -{ - auto ret = ibv_destroy_srq(srq); - - ibdbg_ldout << " srq: " << srq << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_destroy_srq(...) _ibv_destroy_srq(__func__, __LINE__, __VA_ARGS__) - -//#define ibv_exp_query_gid_attr(...) _ibv_exp_query_gid_attr(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_fork_init(const char *f, int l) -{ - auto ret = ibv_fork_init(); - - ibdbg_ldout << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_fork_init() _ibv_fork_init(__func__, __LINE__) - -static inline void _ibv_free_device_list(const char *f, int l, - struct ibv_device **list) -{ - ibdbg_ldout << " list: " << list << dendl; - - ibv_free_device_list(list); -} -#define ibv_free_device_list(...) _ibv_free_device_list(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_get_cq_event(const char *f, int l, - struct ibv_comp_channel *channel, - struct ibv_cq **cq, void **cq_context) -{ - auto ret = ibv_get_cq_event(channel, cq, cq_context); - - ibdbg_ldout << " channel: " << channel << " cq: " << cq << " cq_context:" << cq_context << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_get_cq_event(...) _ibv_get_cq_event(__func__, __LINE__, __VA_ARGS__) - -static inline struct ibv_device **_ibv_get_device_list(const char *f, int l, - int *num_devices) -{ - auto ret = ibv_get_device_list(num_devices); - - ibdbg_ldout << - " | num: " << *num_devices << " list: " << ret << dendl; - - return ret; -} -#define ibv_get_device_list(...) _ibv_get_device_list(__func__, __LINE__, __VA_ARGS__) - -static inline const char *_ibv_get_device_name(const char *f, int l, - struct ibv_device *device) -{ - auto ret = ibv_get_device_name(device); - - ibdbg_ldout << " device: " << device << - " | name: " << ret << dendl; - - return ret; -} -#define ibv_get_device_name(...) _ibv_get_device_name(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_modify_qp(const char *f, int l, - struct ibv_qp *qp, struct ibv_qp_attr *attr, - int attr_mask) -{ - auto ret = ibv_modify_qp(qp, attr, attr_mask); - - ibdbg_ldout << " qp: " << qp << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_modify_qp(...) _ibv_modify_qp(__func__, __LINE__, __VA_ARGS__) - -static inline struct ibv_context *_ibv_open_device(const char *f, int l, - struct ibv_device *device) -{ - auto ret = ibv_open_device(device); - - ibdbg_ldout << " device: " << device << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_open_device(...) _ibv_open_device(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_poll_cq(const char *f, int l, - struct ibv_cq *cq, int num_entries, struct ibv_wc *wc) -{ - auto ret = ibv_poll_cq(cq, num_entries, wc); - static utime_t last_print = ceph_clock_now(); - static int suppressed_counter = 0; - - if ((ceph_clock_now() - last_print).to_msec() < 100) { - suppressed_counter++; - return ret; - } - - if (suppressed_counter > 0) { - ibdbg_ldout << " cq: " << cq << " num_entries: " << num_entries << - " | ret: " << ret << - " {suppressed " << suppressed_counter << " prints}" << dendl; - suppressed_counter = 0; - } else { - ibdbg_ldout << " cq: " << cq << " num_entries: " << num_entries << - " | ret: " << ret << dendl; - } - - last_print = ceph_clock_now(); - - return ret; -} -#define ibv_poll_cq(...) _ibv_poll_cq(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_post_send(const char *f, int l, - struct ibv_qp *qp, struct ibv_send_wr *wr, - struct ibv_send_wr **bad_wr) -{ - auto ret = ibv_post_send(qp, wr, bad_wr); - - ibdbg_ldout << " qp: " << qp << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_post_send(...) _ibv_post_send(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_post_srq_recv(const char *f, int l, - struct ibv_srq *srq, - struct ibv_recv_wr *recv_wr, - struct ibv_recv_wr **bad_recv_wr) -{ - auto ret = ibv_post_srq_recv(srq, recv_wr, bad_recv_wr); - - static struct ibv_srq *last_srq = nullptr; - if (last_srq != srq) { - ibdbg_ldout << " srq: " << srq << - " | ret: " << ret << dendl; - last_srq = srq; - } - - return ret; -} -#define ibv_post_srq_recv(...) _ibv_post_srq_recv(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_query_device(const char *f, int l, - struct ibv_context *context, - struct ibv_device_attr *device_attr) -{ - auto ret = ibv_query_device(context, device_attr); - - ibdbg_ldout << " context: " << context << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_query_device(...) _ibv_query_device(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_query_gid(const char *f, int l, - struct ibv_context *context, int port_num, - int index, union ibv_gid *gid) -{ - auto ret = ibv_query_gid(context, port_num, index, gid); - - ibdbg_ldout << " context: " << context << " port_num: " << port_num << " index: " << index << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_query_gid(...) _ibv_query_gid(__func__, __LINE__, __VA_ARGS__) - -static inline int ____ibv_query_port(const char *f, int l, - struct ibv_context *context, - int port_num, - struct ibv_port_attr *port_attr) -{ - auto ret = ___ibv_query_port(context, port_num, port_attr); - - ibdbg_ldout << " context: " << context << " port_num: " << port_num << - " | ret: " << ret << dendl; - - return ret; -} -#define ___ibv_query_port(...) ____ibv_query_port(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_req_notify_cq(const char *f, int l, - struct ibv_cq *cq, int solicited_only) -{ - auto ret = ibv_req_notify_cq(cq, solicited_only); - - ibdbg_ldout << " cq: " << cq << " solicited_only: " << solicited_only << - " | ret: " << ret << dendl; - - return ret; -} -#define ibv_req_notify_cq(...) _ibv_req_notify_cq(__func__, __LINE__, __VA_ARGS__) - -static inline int _ibv_get_async_event(const char *f, int l, - struct ibv_context *context, - struct ibv_async_event *event) -{ - auto ret = ibv_get_async_event(context, event); - - ibdbg_ldout << " context: " << context << - " | event: " << event << " ret: " << ret << dendl; - - return ret; -} -#define ibv_get_async_event(...) _ibv_get_async_event(__func__, __LINE__, __VA_ARGS__) - -static inline void _ibv_ack_async_event(const char *f, int l, - struct ibv_async_event *event) -{ - ibdbg_ldout << " event: " << event << dendl; - - ibv_ack_async_event(event); -} -#define ibv_ack_async_event(...) _ibv_ack_async_event(__func__, __LINE__, __VA_ARGS__) - -#endif // __IB_DBG_H__ diff --git a/ceph/src/msg/simple/Pipe.cc b/ceph/src/msg/simple/Pipe.cc index cece32f0b..fc415df8a 100644 --- a/ceph/src/msg/simple/Pipe.cc +++ b/ceph/src/msg/simple/Pipe.cc @@ -858,7 +858,7 @@ int Pipe::accept() state = STATE_STANDBY; } else { state = STATE_CLOSED; - state_closed.set(1); + state_closed = true; } fault(); if (queued || replaced) @@ -879,7 +879,7 @@ int Pipe::accept() } state = STATE_CLOSED; - state_closed.set(1); + state_closed = true; fault(); return -1; } @@ -1583,7 +1583,7 @@ void Pipe::stop() ldout(msgr->cct,10) << "stop" << dendl; assert(pipe_lock.is_locked()); state = STATE_CLOSED; - state_closed.set(1); + state_closed = true; cond.Signal(); shutdown_socket(); } @@ -1793,7 +1793,7 @@ void Pipe::reader() pipe_lock.Lock(); if (state == STATE_CLOSING) { state = STATE_CLOSED; - state_closed.set(1); + state_closed = true; } else { state = STATE_CLOSING; } @@ -1841,7 +1841,7 @@ void Pipe::writer() ldout(msgr->cct,20) << "writer writing CLOSE tag" << dendl; char tag = CEPH_MSGR_TAG_CLOSE; state = STATE_CLOSED; - state_closed.set(1); + state_closed = true; pipe_lock.Unlock(); if (sd >= 0) { // we can ignore return value, actually; we don't care if this succeeds. diff --git a/ceph/src/msg/simple/Pipe.h b/ceph/src/msg/simple/Pipe.h index 5324c108d..9dd00d1b4 100644 --- a/ceph/src/msg/simple/Pipe.h +++ b/ceph/src/msg/simple/Pipe.h @@ -129,7 +129,7 @@ static const int SM_IOV_MAX = (IOV_MAX >= 1024 ? IOV_MAX / 4 : IOV_MAX); Mutex pipe_lock; int state; - atomic_t state_closed; // non-zero iff state = STATE_CLOSED + std::atomic state_closed = { false }; // true iff state = STATE_CLOSED // session_security handles any signatures or encryptions required for this pipe's msgs. PLR diff --git a/ceph/src/msg/simple/SimpleMessenger.cc b/ceph/src/msg/simple/SimpleMessenger.cc index efd8ede13..84b6a253e 100644 --- a/ceph/src/msg/simple/SimpleMessenger.cc +++ b/ceph/src/msg/simple/SimpleMessenger.cc @@ -309,6 +309,8 @@ int SimpleMessenger::rebind(const set& avoid_ports) int SimpleMessenger::client_bind(const entity_addr_t &bind_addr) { + if (!cct->_conf->ms_bind_before_connect) + return 0; Mutex::Locker l(lock); if (did_bind) { assert(my_inst.addr == bind_addr); diff --git a/ceph/src/msg/simple/SimpleMessenger.h b/ceph/src/msg/simple/SimpleMessenger.h index 9c5f43e89..4ddc9767c 100644 --- a/ceph/src/msg/simple/SimpleMessenger.h +++ b/ceph/src/msg/simple/SimpleMessenger.h @@ -25,7 +25,6 @@ using namespace std; #include "include/unordered_set.h" #include "common/Mutex.h" -#include "include/atomic.h" #include "include/Spinlock.h" #include "common/Cond.h" #include "common/Thread.h" @@ -322,7 +321,7 @@ private: if (p == rank_pipe.end()) return NULL; // see lock cribbing in Pipe::fault() - if (p->second->state_closed.read()) + if (p->second->state_closed) return NULL; return p->second; } diff --git a/ceph/src/msg/xio/XioConnection.cc b/ceph/src/msg/xio/XioConnection.cc index 107a489a4..36b946de0 100644 --- a/ceph/src/msg/xio/XioConnection.cc +++ b/ceph/src/msg/xio/XioConnection.cc @@ -433,7 +433,7 @@ int XioConnection::handle_data_msg(struct xio_session *session, } /* update connection timestamp */ - recv.set(tmsg->timestamp); + recv = tmsg->timestamp; Message *m = decode_message(msgr->cct, msgr->crcflags, header, footer, payload, middle, data, this); @@ -786,8 +786,8 @@ int XioConnection::CState::state_up_ready(uint32_t flags) xcon->flush_out_queues(flags|CState::OP_FLAG_LOCKED); - session_state.set(UP); - startup_state.set(READY); + session_state = session_states::UP; + startup_state = session_startup_states::READY; if (! (flags & CState::OP_FLAG_LOCKED)) pthread_spin_unlock(&xcon->sp); @@ -797,8 +797,8 @@ int XioConnection::CState::state_up_ready(uint32_t flags) int XioConnection::CState::state_discon() { - session_state.set(DISCONNECTED); - startup_state.set(IDLE); + session_state = session_states::DISCONNECTED; + startup_state = session_startup_states::IDLE; return 0; } @@ -808,7 +808,7 @@ int XioConnection::CState::state_flow_controlled(uint32_t flags) if (! (flags & OP_FLAG_LOCKED)) pthread_spin_lock(&xcon->sp); - session_state.set(FLOW_CONTROLLED); + session_state = session_states::FLOW_CONTROLLED; if (! (flags & OP_FLAG_LOCKED)) pthread_spin_unlock(&xcon->sp); @@ -822,8 +822,8 @@ int XioConnection::CState::state_fail(Message* m, uint32_t flags) pthread_spin_lock(&xcon->sp); // advance to state FAIL, drop queued, msgs, adjust LRU - session_state.set(DISCONNECTED); - startup_state.set(FAIL); + session_state = session_states::DISCONNECTED); + startup_state = session_startup_states::FAIL); xcon->discard_out_queues(flags|OP_FLAG_LOCKED); xcon->adjust_clru(flags|OP_FLAG_LOCKED|OP_FLAG_LRU); diff --git a/ceph/src/msg/xio/XioConnection.h b/ceph/src/msg/xio/XioConnection.h index ce1667940..1ed88b995 100644 --- a/ceph/src/msg/xio/XioConnection.h +++ b/ceph/src/msg/xio/XioConnection.h @@ -16,16 +16,19 @@ #ifndef XIO_CONNECTION_H #define XIO_CONNECTION_H +#include + #include #include + extern "C" { #include "libxio.h" } + #include "XioInSeq.h" #include "XioSubmit.h" #include "msg/Connection.h" #include "msg/Messenger.h" -#include "include/atomic.h" #include "auth/AuthSessionHandler.h" #define XIO_ALL_FEATURES (CEPH_FEATURES_ALL) @@ -44,7 +47,7 @@ class XioConnection : public Connection public: enum type { ACTIVE, PASSIVE }; - enum session_states { + enum class session_states : unsigned { INIT = 0, START, UP, @@ -54,7 +57,7 @@ public: BARRIER }; - enum session_startup_states { + enum class session_startup_states : unsigned { IDLE = 0, CONNECTING, ACCEPTING, @@ -65,13 +68,13 @@ public: private: XioConnection::type xio_conn_type; XioPortal *portal; - atomic_t connected; + std::atomic connected = { false }; entity_inst_t peer; struct xio_session *session; struct xio_connection *conn; pthread_spinlock_t sp; - atomic_t send; - atomic_t recv; + std::atomic send = { 0 }; + std::atomic recv = { 0 }; uint32_t n_reqs; // Accelio-initiated reqs in progress (!counting partials) uint32_t magic; uint32_t special_handling; @@ -94,18 +97,18 @@ private: uint32_t reconnects; uint32_t connect_seq, peer_global_seq; uint64_t in_seq, out_seq_acked; // atomic, got receipt - atomic64_t out_seq; // atomic + std::atomic out_seq = { 0 }; lifecycle() : state(lifecycle::INIT), reconnects(0), connect_seq(0), - peer_global_seq(0), in_seq(0), out_seq_acked(0), - out_seq(0) {} + peer_global_seq(0), in_seq(0), out_seq_acked(0) + {} void set_in_seq(uint64_t seq) { in_seq = seq; } uint64_t next_out_seq() { - return out_seq.inc(); + return ++out_seq; } } state; @@ -134,13 +137,13 @@ private: XioConnection *xcon; uint32_t protocol_version; - atomic_t session_state; - atomic_t startup_state; + std::atomic session_state = { 0 }; + std::atomic startup_state = { 0 }; uint32_t reconnects; uint32_t connect_seq, global_seq, peer_global_seq; uint64_t in_seq, out_seq_acked; // atomic, got receipt - atomic64_t out_seq; // atomic + std::atomic out_seq = { 0 }; uint32_t flags; @@ -157,15 +160,14 @@ private: peer_global_seq(0), in_seq(0), out_seq_acked(0), - out_seq(0), flags(FLAG_NONE) {} uint64_t get_session_state() { - return session_state.read(); + return session_state; } uint64_t get_startup_state() { - return startup_state.read(); + return startup_state; } void set_in_seq(uint64_t seq) { @@ -173,7 +175,7 @@ private: } uint64_t next_out_seq() { - return out_seq.inc(); + return ++out_seq; }; // state machine @@ -239,7 +241,7 @@ private: friend class XioSend; int on_disconnect_event() { - connected.set(false); + connected = false; pthread_spin_lock(&sp); discard_out_queues(CState::OP_FLAG_LOCKED); pthread_spin_unlock(&sp); @@ -274,7 +276,7 @@ public: } ostream& conn_prefix(std::ostream *_dout); - bool is_connected() override { return connected.read(); } + bool is_connected() override { return connected; } int send_message(Message *m) override; void send_keepalive() override {send_keepalive_or_ack();} @@ -288,8 +290,7 @@ public: XioConnection* get() { #if 0 - int refs = nref.read(); - cout << "XioConnection::get " << this << " " << refs << std::endl; + cout << "XioConnection::get " << this << " " << nref.load() << std::endl; #endif RefCountedObject::get(); return this; @@ -298,14 +299,13 @@ public: void put() { RefCountedObject::put(); #if 0 - int refs = nref.read(); - cout << "XioConnection::put " << this << " " << refs << std::endl; + cout << "XioConnection::put " << this << " " << nref.load() << std::endl; #endif } void disconnect() { if (is_connected()) { - connected.set(false); + connected = false; xio_disconnect(conn); // normal teardown will clean up conn } } @@ -340,9 +340,9 @@ typedef boost::intrusive_ptr XioConnectionRef; class XioLoopbackConnection : public Connection { private: - atomic64_t seq; + std::atomic seq = { 0 }; public: - explicit XioLoopbackConnection(Messenger *m) : Connection(m->cct, m), seq(0) + explicit XioLoopbackConnection(Messenger *m) : Connection(m->cct, m) { const entity_inst_t& m_inst = m->get_myinst(); peer_addr = m_inst.addr; @@ -362,11 +362,11 @@ public: void mark_disposable() override {} uint64_t get_seq() { - return seq.read(); + return seq; } uint64_t next_seq() { - return seq.inc(); + return ++seq; } }; diff --git a/ceph/src/msg/xio/XioMessenger.cc b/ceph/src/msg/xio/XioMessenger.cc index a63f5ffb3..6bf4d52c7 100644 --- a/ceph/src/msg/xio/XioMessenger.cc +++ b/ceph/src/msg/xio/XioMessenger.cc @@ -30,9 +30,9 @@ #define dout_prefix *_dout << "xio." Mutex mtx("XioMessenger Package Lock"); -atomic_t initialized; +std::atomic initialized = { false }; -atomic_t XioMessenger::nInstances; +std::atomic XioMessenger::nInstances = { 0 }; struct xio_mempool *xio_msgr_noreg_mpool; @@ -235,10 +235,10 @@ static string xio_uri_from_entity(const string &type, } /* xio_uri_from_entity */ void XioInit::package_init(CephContext *cct) { - if (! initialized.read()) { + if (! initialized) { mtx.Lock(); - if (! initialized.read()) { + if (! initialized) { xio_init(); @@ -334,7 +334,7 @@ void XioInit::package_init(CephContext *cct) { xio_msgr_ops.on_cancel_request = on_cancel_request; /* mark initialized */ - initialized.set(1); + initialized = true; } mtx.Unlock(); } @@ -352,8 +352,6 @@ XioMessenger::XioMessenger(CephContext *cct, entity_name_t name, uint64_t cflags, DispatchStrategy *ds) : SimplePolicyMessenger(cct, name, mname, _nonce), XioInit(cct), - nsessions(0), - shutdown_called(false), portals(this, get_nportals(cflags), get_nconns_per_portal(cflags)), dispatch_strategy(ds), loop_con(new XioLoopbackConnection(this)), @@ -374,12 +372,12 @@ XioMessenger::XioMessenger(CephContext *cct, entity_name_t name, dispatch_strategy->set_messenger(this); /* update class instance count */ - nInstances.inc(); + nInstances++; loop_con->set_features(CEPH_FEATURES_ALL); ldout(cct,2) << "Create msgr: " << this << " instance: " - << nInstances.read() << " type: " << name.type_str() + << nInstances << " type: " << name.type_str() << " subtype: " << mname << " nportals: " << get_nportals(cflags) << " nconns_per_portal: " << get_nconns_per_portal(cflags) << dendl; @@ -447,13 +445,13 @@ int XioMessenger::new_session(struct xio_session *session, struct xio_new_session_req *req, void *cb_user_context) { - if (shutdown_called.read()) { + if (shutdown_called) { return xio_reject( session, XIO_E_SESSION_REFUSED, NULL /* udata */, 0 /* udata len */); } int code = portals.accept(session, req, cb_user_context); if (! code) - nsessions.inc(); + nsessions++; return code; } /* new_session */ @@ -518,7 +516,7 @@ int XioMessenger::session_event(struct xio_session *session, xcona.user_context = xcon; (void) xio_modify_connection(conn, &xcona, XIO_CONNECTION_ATTR_USER_CTX); - xcon->connected.set(true); + xcon->connected = true; /* sentinel ref */ xcon->get(); /* xcon->nref == 1 */ @@ -566,9 +564,9 @@ int XioMessenger::session_event(struct xio_session *session, xp_stats.dump("xio session dtor", reinterpret_cast(session)); } xio_session_destroy(session); - if (nsessions.dec() == 0) { + if (--nsessions == 0) { Mutex::Locker lck(sh_mtx); - if (nsessions.read() == 0) + if (nsessions == 0) sh_cond.Signal(); } break; @@ -943,7 +941,7 @@ assert(req->out.pdata_iov.nents || !nbuffers); int XioMessenger::shutdown() { - shutdown_called.set(true); + shutdown_called = true; conns_sp.lock(); XioConnection::ConnList::iterator iter; iter = conns_list.begin(); @@ -951,9 +949,9 @@ int XioMessenger::shutdown() (void) iter->disconnect(); // XXX mark down? } conns_sp.unlock(); - while(nsessions.read() > 0) { + while(nsessions > 0) { Mutex::Locker lck(sh_mtx); - if (nsessions.read() > 0) + if (nsessions > 0) sh_cond.Wait(sh_mtx); } portals.shutdown(); @@ -965,7 +963,7 @@ int XioMessenger::shutdown() ConnectionRef XioMessenger::get_connection(const entity_inst_t& dest) { - if (shutdown_called.read()) + if (shutdown_called) return NULL; const entity_inst_t& self_inst = get_myinst(); @@ -1020,8 +1018,8 @@ ConnectionRef XioMessenger::get_connection(const entity_inst_t& dest) return NULL; } - nsessions.inc(); - xcon->connected.set(true); + nsessions++; + xcon->connected = true; /* sentinel ref */ xcon->get(); /* xcon->nref == 1 */ @@ -1115,7 +1113,7 @@ void XioMessenger::mark_down_on_empty(Connection* con) m->tag = XIO_NOP_TAG_MARKDOWN; m->set_completion_hook(pool_alloc_markdown_hook(xcon, m)); // stall new messages - xcon->cstate.session_state.set(XioConnection::BARRIER); + xcon->cstate.session_state = XioConnection::session_states::BARRIER; (void) _send_message_impl(m, xcon); } @@ -1135,5 +1133,5 @@ void XioMessenger::try_insert(XioConnection *xcon) XioMessenger::~XioMessenger() { delete dispatch_strategy; - nInstances.dec(); + nInstances--; } /* dtor */ diff --git a/ceph/src/msg/xio/XioMessenger.h b/ceph/src/msg/xio/XioMessenger.h index 0bfdd6e78..9a81fb247 100644 --- a/ceph/src/msg/xio/XioMessenger.h +++ b/ceph/src/msg/xio/XioMessenger.h @@ -17,13 +17,16 @@ #define XIO_MESSENGER_H #include "msg/SimplePolicyMessenger.h" + +#include + extern "C" { #include "libxio.h" } + #include "XioConnection.h" #include "XioPortal.h" #include "QueueStrategy.h" -#include "include/atomic.h" #include "common/Thread.h" #include "common/Mutex.h" #include "include/Spinlock.h" @@ -41,9 +44,9 @@ protected: class XioMessenger : public SimplePolicyMessenger, XioInit { private: - static atomic_t nInstances; - atomic_t nsessions; - atomic_t shutdown_called; + static std::atomic nInstances = { 0 }; + std::atomic nsessions = { 0 }; + std::atomic shutdown_called = { false }; Spinlock conns_sp; XioConnection::ConnList conns_list; XioConnection::EntitySet conns_entity_map; diff --git a/ceph/src/msg/xio/XioMsg.h b/ceph/src/msg/xio/XioMsg.h index 73d210df2..f85950ebc 100644 --- a/ceph/src/msg/xio/XioMsg.h +++ b/ceph/src/msg/xio/XioMsg.h @@ -201,10 +201,10 @@ public: xcon->get(); } - XioSend* get() { nrefs.inc(); return this; }; + XioSend* get() { nrefs++; return this; }; void put(int n) { - int refs = nrefs.sub(n); + int refs = nrefs -= n; if (refs == 0) { struct xio_reg_mem *mp = &this->mp_this; this->~XioSend(); @@ -228,7 +228,7 @@ public: private: xio_msg_ex req_0; struct xio_reg_mem mp_this; - atomic_t nrefs; + std::atomic nrefs = { 0 }; }; class XioCommand : public XioSend @@ -316,7 +316,7 @@ private: XioConnection *xcon; XioInSeq msg_seq; XioPool rsp_pool; - atomic_t nrefs; + std::atomic nrefs { 1 }; bool cl_flag; friend class XioConnection; friend class XioMessenger; @@ -329,7 +329,6 @@ public: xcon(_xcon->get()), msg_seq(_msg_seq), rsp_pool(xio_msgr_noreg_mpool), - nrefs(1), cl_flag(false), mp_this(_mp) { @@ -348,11 +347,11 @@ public: int release_msgs(); XioDispatchHook* get() { - nrefs.inc(); return this; + nrefs++; return this; } void put(int n = 1) { - int refs = nrefs.sub(n); + int refs = nrefs -= n; if (refs == 0) { /* in Marcus' new system, refs reaches 0 twice: once in * Message lifecycle, and again after xio_release_msg. diff --git a/ceph/src/msg/xio/XioPool.h b/ceph/src/msg/xio/XioPool.h index f7c950fb4..6084ce856 100644 --- a/ceph/src/msg/xio/XioPool.h +++ b/ceph/src/msg/xio/XioPool.h @@ -14,23 +14,22 @@ #ifndef XIO_POOL_H #define XIO_POOL_H +#include +#include +#include +#include +#include + extern "C" { -#include -#include -#include #include "libxio.h" } -#include -#include "include/atomic.h" -#include "common/likely.h" +#include "common/likely.h" static inline int xpool_alloc(struct xio_mempool *pool, uint64_t size, struct xio_reg_mem* mp); static inline void xpool_free(uint64_t size, struct xio_reg_mem* mp); -using ceph::atomic_t; - class XioPool { private: @@ -95,84 +94,77 @@ private: NUM_SLABS, }; - atomic_t ctr_set[NUM_SLABS]; - - atomic_t msg_cnt; // send msgs - atomic_t hook_cnt; // recv msgs + std::atomic ctr_set[NUM_SLABS] = {}; + std::atomic msg_cnt = { 0 }; // send msgs + std::atomic hook_cnt = { 0 }; // recv msgs public: - XioPoolStats() : msg_cnt(0), hook_cnt(0) { - for (int ix = 0; ix < NUM_SLABS; ++ix) { - ctr_set[ix].set(0); - } - } - void dump(const char* tag, uint64_t serial); void inc(uint64_t size) { if (size <= 64) { - (ctr_set[SLAB_64]).inc(); + (ctr_set[SLAB_64])++; return; } if (size <= 256) { - (ctr_set[SLAB_256]).inc(); + (ctr_set[SLAB_256])++; return; } if (size <= 1024) { - (ctr_set[SLAB_1024]).inc(); + (ctr_set[SLAB_1024])++; return; } if (size <= 8192) { - (ctr_set[SLAB_PAGE]).inc(); + (ctr_set[SLAB_PAGE])++; return; } - (ctr_set[SLAB_MAX]).inc(); + (ctr_set[SLAB_MAX])++; } void dec(uint64_t size) { if (size <= 64) { - (ctr_set[SLAB_64]).dec(); + (ctr_set[SLAB_64])--; return; } if (size <= 256) { - (ctr_set[SLAB_256]).dec(); + (ctr_set[SLAB_256])--; return; } if (size <= 1024) { - (ctr_set[SLAB_1024]).dec(); + (ctr_set[SLAB_1024])--; return; } if (size <= 8192) { - (ctr_set[SLAB_PAGE]).dec(); + (ctr_set[SLAB_PAGE])--; return; } - (ctr_set[SLAB_MAX]).dec(); + (ctr_set[SLAB_MAX])--; } - void inc_overflow() { ctr_set[SLAB_OVERFLOW].inc(); } - void dec_overflow() { ctr_set[SLAB_OVERFLOW].dec(); } + void inc_overflow() { ctr_set[SLAB_OVERFLOW]++; } + void dec_overflow() { ctr_set[SLAB_OVERFLOW]--; } void inc_msgcnt() { if (unlikely(XioPool::trace_msgcnt)) { - msg_cnt.inc(); + msg_cnt++; } } void dec_msgcnt() { if (unlikely(XioPool::trace_msgcnt)) { - msg_cnt.dec(); + msg_cnt--; } } void inc_hookcnt() { if (unlikely(XioPool::trace_msgcnt)) { - hook_cnt.inc(); + hook_cnt++; } } void dec_hookcnt() { if (unlikely(XioPool::trace_msgcnt)) { - hook_cnt.dec(); + hook_cnt--; } } }; @@ -186,7 +178,7 @@ static inline int xpool_alloc(struct xio_mempool *pool, uint64_t size, int r = xio_mempool_alloc(pool, size, mp); if (r == 0) { if (unlikely(XioPool::trace_mempool)) - xp_stats.inc(size); + xp_stats += size; return 0; } // fall back to malloc on errors @@ -202,7 +194,7 @@ static inline void xpool_free(uint64_t size, struct xio_reg_mem* mp) { if (mp->length) { if (unlikely(XioPool::trace_mempool)) - xp_stats.dec(size); + xp_stats -= size; xio_mempool_free(mp); } else { // from malloc if (unlikely(XioPool::trace_mempool)) diff --git a/ceph/src/os/CMakeLists.txt b/ceph/src/os/CMakeLists.txt index b24686d81..feda6a23b 100644 --- a/ceph/src/os/CMakeLists.txt +++ b/ceph/src/os/CMakeLists.txt @@ -50,6 +50,11 @@ if(WITH_FUSE) FuseStore.cc) endif(WITH_FUSE) +if(WITH_PMEM) + list(APPEND libos_srcs + bluestore/PMEMDevice.cc) +endif(WITH_PMEM) + if(WITH_SPDK) list(APPEND libos_srcs bluestore/NVMEDevice.cc) @@ -67,6 +72,10 @@ if(WITH_FUSE) target_link_libraries(os ${FUSE_LIBRARIES}) endif() +if(WITH_PMEM) + target_link_libraries(os ${PMEM_LIBRARY}) +endif() + if(WITH_SPDK) target_link_libraries(os ${SPDK_LIBRARIES} diff --git a/ceph/src/os/FuseStore.cc b/ceph/src/os/FuseStore.cc index fc47eb98a..3ae0638f5 100644 --- a/ceph/src/os/FuseStore.cc +++ b/ceph/src/os/FuseStore.cc @@ -1,6 +1,7 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include "include/compat.h" #include "FuseStore.h" #include "os/ObjectStore.h" #include "include/stringify.h" diff --git a/ceph/src/os/ObjectStore.cc b/ceph/src/os/ObjectStore.cc index 207472e34..93c79667d 100644 --- a/ceph/src/os/ObjectStore.cc +++ b/ceph/src/os/ObjectStore.cc @@ -73,12 +73,10 @@ ObjectStore *ObjectStore::create(CephContext *cct, return new MemStore(cct, data); } #if defined(HAVE_LIBAIO) - if (type == "bluestore" && - cct->check_experimental_feature_enabled("bluestore")) { + if (type == "bluestore") { return new BlueStore(cct, data); } - if (type == "random" && - cct->check_experimental_feature_enabled("bluestore")) { + if (type == "random") { if (rand() % 2) { return new FileStore(cct, data, journal, flags); } else { diff --git a/ceph/src/os/ObjectStore.h b/ceph/src/os/ObjectStore.h index 9c760a91c..71f5e80b1 100644 --- a/ceph/src/os/ObjectStore.h +++ b/ceph/src/os/ObjectStore.h @@ -1561,6 +1561,20 @@ public: virtual bool wants_journal() = 0; //< prefers a journal virtual bool allows_journal() = 0; //< allows a journal + /** + * is_rotational + * + * Check whether store is backed by a rotational (HDD) or non-rotational + * (SSD) device. + * + * This must be usable *before* the store is mounted. + * + * @return true for HDD, false for SSD + */ + virtual bool is_rotational() { + return true; + } + virtual bool can_sort_nibblewise() { return false; // assume a backend cannot, unless it says otherwise } diff --git a/ceph/src/os/bluestore/BitAllocator.cc b/ceph/src/os/bluestore/BitAllocator.cc index d6fc8a22b..aeec038dc 100644 --- a/ceph/src/os/bluestore/BitAllocator.cc +++ b/ceph/src/os/bluestore/BitAllocator.cc @@ -11,8 +11,8 @@ * at a time single thread can be active as well as single biggest * contiguous allocation that can be requested. * - * Rest of the nodes are classified into three catagories: - * root note or Allocator + * Rest of the nodes are classified into three categories: + * root node or Allocator * internal nodes or BitMapAreaIN * final nodes that contains Zones called BitMapAreaLeaf * This classification is according to their own implmentation of some diff --git a/ceph/src/os/bluestore/BitMapAllocator.cc b/ceph/src/os/bluestore/BitMapAllocator.cc index 54e986e3c..f2a16d8c9 100644 --- a/ceph/src/os/bluestore/BitMapAllocator.cc +++ b/ceph/src/os/bluestore/BitMapAllocator.cc @@ -22,38 +22,39 @@ BitMapAllocator::BitMapAllocator(CephContext* cct, int64_t device_size, int64_t block_size) : cct(cct) { - assert(ISP2(block_size)); if (!ISP2(block_size)) { derr << __func__ << " block_size " << block_size << " not power of 2 aligned!" << dendl; + assert(ISP2(block_size)); return; } int64_t zone_size_blks = cct->_conf->bluestore_bitmapallocator_blocks_per_zone; - assert(ISP2(zone_size_blks)); if (!ISP2(zone_size_blks)) { derr << __func__ << " zone_size " << zone_size_blks << " not power of 2 aligned!" << dendl; + assert(ISP2(zone_size_blks)); return; } int64_t span_size = cct->_conf->bluestore_bitmapallocator_span_size; - assert(ISP2(span_size)); if (!ISP2(span_size)) { derr << __func__ << " span_size " << span_size << " not power of 2 aligned!" << dendl; + assert(ISP2(span_size)); return; } m_block_size = block_size; + m_total_size = P2ALIGN(device_size, block_size); m_bit_alloc = new BitAllocator(cct, device_size / block_size, zone_size_blks, CONCURRENT, true); - assert(m_bit_alloc); if (!m_bit_alloc) { derr << __func__ << " Unable to intialize Bit Allocator" << dendl; + assert(m_bit_alloc); } dout(10) << __func__ << " instance " << (uint64_t) this << " size 0x" << std::hex << device_size << std::dec @@ -123,7 +124,7 @@ int64_t BitMapAllocator::allocate( << " alloc_unit " << alloc_unit << " hint " << hint << dendl; - + hint = hint % m_total_size; // make hint error-tolerant return allocate_dis(want_size, alloc_unit / m_block_size, max_alloc_size, hint / m_block_size, extents); } diff --git a/ceph/src/os/bluestore/BitMapAllocator.h b/ceph/src/os/bluestore/BitMapAllocator.h index 21d10f33b..a39751d4c 100644 --- a/ceph/src/os/bluestore/BitMapAllocator.h +++ b/ceph/src/os/bluestore/BitMapAllocator.h @@ -14,6 +14,7 @@ class BitMapAllocator : public Allocator { CephContext* cct; int64_t m_block_size; + int64_t m_total_size; BitAllocator *m_bit_alloc; // Bit allocator instance diff --git a/ceph/src/os/bluestore/BlockDevice.cc b/ceph/src/os/bluestore/BlockDevice.cc index cdc13ff36..ca8195229 100644 --- a/ceph/src/os/bluestore/BlockDevice.cc +++ b/ceph/src/os/bluestore/BlockDevice.cc @@ -22,8 +22,15 @@ #include "NVMEDevice.h" #endif +#if defined(HAVE_PMEM) +#include "PMEMDevice.h" +#include +#endif + #include "common/debug.h" #include "common/EventTrace.h" +#include "common/errno.h" +#include "include/compat.h" #define dout_context cct #define dout_subsys ceph_subsys_bdev @@ -55,8 +62,27 @@ BlockDevice *BlockDevice::create(CephContext* cct, const string& path, if (strncmp(bname, SPDK_PREFIX, sizeof(SPDK_PREFIX)-1) == 0) type = "ust-nvme"; } + +#if defined(HAVE_PMEM) + if (type == "kernel") { + int is_pmem = 0; + void *addr = pmem_map_file(path.c_str(), 1024*1024, PMEM_FILE_EXCL, O_RDONLY, NULL, &is_pmem); + if (addr != NULL) { + if (is_pmem) + type = "pmem"; + pmem_unmap(addr, 1024*1024); + } + } +#endif + dout(1) << __func__ << " path " << path << " type " << type << dendl; +#if defined(HAVE_PMEM) + if (type == "pmem") { + return new PMEMDevice(cct, cb, cbpriv); + } +#endif + if (type == "kernel") { return new KernelDevice(cct, cb, cbpriv); } @@ -66,6 +92,7 @@ BlockDevice *BlockDevice::create(CephContext* cct, const string& path, } #endif + derr << __func__ << " unknown backend " << type << dendl; ceph_abort(); return NULL; diff --git a/ceph/src/os/bluestore/BlockDevice.h b/ceph/src/os/bluestore/BlockDevice.h index 4448b2ef6..f2b48f05a 100644 --- a/ceph/src/os/bluestore/BlockDevice.h +++ b/ceph/src/os/bluestore/BlockDevice.h @@ -29,6 +29,11 @@ /// track in-flight io struct IOContext { +private: + std::mutex lock; + std::condition_variable cond; + +public: CephContext* cct; void *priv; #ifdef HAVE_SPDK @@ -36,8 +41,6 @@ struct IOContext { void *nvme_task_last = nullptr; #endif - std::mutex lock; - std::condition_variable cond; std::list pending_aios; ///< not yet submitted std::list running_aios; ///< submitting or submitted @@ -58,11 +61,20 @@ struct IOContext { void aio_wait(); - void aio_wake() { - std::lock_guard l(lock); - cond.notify_all(); - --num_running; - assert(num_running == 0); + void try_aio_wake() { + if (num_running == 1) { + + // we might have some pending IOs submitted after the check + // as there is no lock protection for aio_submit. + // Hence we might have false conditional trigger. + // aio_wait has to handle that hence do not care here. + std::lock_guard l(lock); + cond.notify_all(); + --num_running; + assert(num_running >= 0); + } else { + --num_running; + } } }; diff --git a/ceph/src/os/bluestore/BlueFS.cc b/ceph/src/os/bluestore/BlueFS.cc index db1dad554..f73e27cf6 100644 --- a/ceph/src/os/bluestore/BlueFS.cc +++ b/ceph/src/os/bluestore/BlueFS.cc @@ -1554,7 +1554,7 @@ int BlueFS::_flush_range(FileWriter *h, uint64_t offset, uint64_t length) dout(20) << __func__ << " using partial tail 0x" << std::hex << partial << std::dec << dendl; assert(h->tail_block.length() == partial); - bl.claim_append(h->tail_block); + bl.claim_append_piecewise(h->tail_block); x_off -= partial; offset -= partial; length += partial; @@ -1566,11 +1566,11 @@ int BlueFS::_flush_range(FileWriter *h, uint64_t offset, uint64_t length) } } if (length == partial + h->buffer.length()) { - bl.claim_append(h->buffer); + bl.claim_append_piecewise(h->buffer); } else { bufferlist t; - t.substr_of(h->buffer, 0, length); - bl.claim_append(t); + h->buffer.splice(0, length, &t); + bl.claim_append_piecewise(t); t.substr_of(h->buffer, length, h->buffer.length() - length); h->buffer.swap(t); dout(20) << " leaving 0x" << std::hex << h->buffer.length() << std::dec @@ -1833,7 +1833,8 @@ int BlueFS::_allocate(uint8_t id, uint64_t len, &extents); if (alloc_len < (int64_t)left) { derr << __func__ << " allocate failed on 0x" << std::hex << left - << " min_alloc_size 0x" << min_alloc_size << std::dec << dendl; + << " min_alloc_size 0x" << min_alloc_size + << " hint 0x" << hint << std::dec << dendl; alloc[id]->dump(); assert(0 == "allocate failed... wtf"); return -ENOSPC; @@ -1969,7 +1970,7 @@ int BlueFS::open_for_write( // match up with bluestore. the slow device is always the second // one (when a dedicated block.db device is present and used at // bdev 0). the wal device is always last. - if (boost::algorithm::ends_with(filename, ".slow")) { + if (boost::algorithm::ends_with(dirname, ".slow")) { file->fnode.prefer_bdev = BlueFS::BDEV_SLOW; } else if (boost::algorithm::ends_with(dirname, ".wal")) { file->fnode.prefer_bdev = BlueFS::BDEV_WAL; diff --git a/ceph/src/os/bluestore/BlueRocksEnv.cc b/ceph/src/os/bluestore/BlueRocksEnv.cc index 3fcccc861..1b1e2e903 100644 --- a/ceph/src/os/bluestore/BlueRocksEnv.cc +++ b/ceph/src/os/bluestore/BlueRocksEnv.cc @@ -97,16 +97,6 @@ class BlueRocksRandomAccessFile : public rocksdb::RandomAccessFile { return rocksdb::Status::OK(); } - // Used by the file_reader_writer to decide if the ReadAhead wrapper - // should simply forward the call and do not enact buffering or locking. - bool ShouldForwardRawRequest() const override { - return false; - } - - // For cases when read-ahead is implemented in the platform dependent - // layer - void EnableReadAhead() override {} - // Tries to get an unique ID for this file that will be the same each time // the file is opened (and will stay the same while the file is open). // Furthermore, it tries to make this ID at most "max_size" bytes. If such an diff --git a/ceph/src/os/bluestore/BlueStore.cc b/ceph/src/os/bluestore/BlueStore.cc index 789c05f0a..38d1e272e 100644 --- a/ceph/src/os/bluestore/BlueStore.cc +++ b/ceph/src/os/bluestore/BlueStore.cc @@ -17,6 +17,8 @@ #include #include +#include "include/cpp-btree/btree_set.h" + #include "BlueStore.h" #include "os/kv.h" #include "include/compat.h" @@ -34,19 +36,26 @@ #define dout_context cct #define dout_subsys ceph_subsys_bluestore -// bluestore_meta_onode +using bid_t = decltype(BlueStore::Blob::id); + +// bluestore_cache_onode MEMPOOL_DEFINE_OBJECT_FACTORY(BlueStore::Onode, bluestore_onode, - bluestore_meta_onode); + bluestore_cache_onode); -// bluestore_meta_other +// bluestore_cache_other MEMPOOL_DEFINE_OBJECT_FACTORY(BlueStore::Buffer, bluestore_buffer, - bluestore_meta_other); + bluestore_cache_other); MEMPOOL_DEFINE_OBJECT_FACTORY(BlueStore::Extent, bluestore_extent, - bluestore_meta_other); + bluestore_cache_other); MEMPOOL_DEFINE_OBJECT_FACTORY(BlueStore::Blob, bluestore_blob, - bluestore_meta_other); + bluestore_cache_other); MEMPOOL_DEFINE_OBJECT_FACTORY(BlueStore::SharedBlob, bluestore_shared_blob, - bluestore_meta_other); + bluestore_cache_other); + +// bluestore_txc +MEMPOOL_DEFINE_OBJECT_FACTORY(BlueStore::TransContext, bluestore_transcontext, + bluestore_txc); + // kv store prefixes const string PREFIX_SUPER = "S"; // field -> value @@ -654,7 +663,7 @@ void BlueStore::GarbageCollector::process_protrusive_extents( } bExit = it == bi.last_lextent; ++it; - } while(!bExit); + } while (!bExit); } expected_for_release += blob_expected_for_release; expected_allocations += bi.expected_allocations; @@ -740,13 +749,12 @@ void BlueStore::Cache::trim_all() { std::lock_guard l(lock); _trim(0, 0); - assert(_get_num_onodes() == 0); - assert(_get_buffer_bytes() == 0); } void BlueStore::Cache::trim( uint64_t target_bytes, float target_meta_ratio, + float target_data_ratio, float bytes_per_onode) { std::lock_guard l(lock); @@ -754,23 +762,18 @@ void BlueStore::Cache::trim( uint64_t current_buffer = _get_buffer_bytes(); uint64_t current = current_meta + current_buffer; - uint64_t target_meta = target_bytes * (double)target_meta_ratio; //need to cast to double - //since float(1) might produce inaccurate value - // for target_meta (a bit greater than target_bytes) - // that causes overflow in target_buffer below. - //Consider the following code: - //uint64_t i =(uint64_t)227*1024*1024*1024 + 1; - //float f = 1; - //uint64_t i2 = i*f; - //assert(i == i2); + uint64_t target_meta = target_bytes * target_meta_ratio; + uint64_t target_buffer = target_bytes * target_data_ratio; - target_meta = min(target_bytes, target_meta); //and just in case that ratio is > 1 - uint64_t target_buffer = target_bytes - target_meta; + // correct for overflow or float imprecision + target_meta = min(target_bytes, target_meta); + target_buffer = min(target_bytes - target_meta, target_buffer); if (current <= target_bytes) { dout(10) << __func__ << " shard target " << pretty_si_t(target_bytes) - << " ratio " << target_meta_ratio << " (" + << " meta/data ratios " << target_meta_ratio + << " + " << target_data_ratio << " (" << pretty_si_t(target_meta) << " + " << pretty_si_t(target_buffer) << "), " << " current " << pretty_si_t(current) << " (" @@ -1270,14 +1273,18 @@ int BlueStore::BufferSpace::_discard(Cache* cache, uint32_t offset, uint32_t len if (b->data.length()) { bufferlist bl; bl.substr_of(b->data, b->length - tail, tail); - _add_buffer(cache, new Buffer(this, b->state, b->seq, end, bl), 0, b); + Buffer *nb = new Buffer(this, b->state, b->seq, end, bl); + nb->maybe_rebuild(); + _add_buffer(cache, nb, 0, b); } else { - _add_buffer(cache, new Buffer(this, b->state, b->seq, end, tail), 0, b); + _add_buffer(cache, new Buffer(this, b->state, b->seq, end, tail), + 0, b); } if (!b->is_writing()) { cache->_adjust_buffer_size(b, front - (int64_t)b->length); } b->truncate(front); + b->maybe_rebuild(); cache->_audit("discard end 1"); break; } else { @@ -1286,6 +1293,7 @@ int BlueStore::BufferSpace::_discard(Cache* cache, uint32_t offset, uint32_t len cache->_adjust_buffer_size(b, front - (int64_t)b->length); } b->truncate(front); + b->maybe_rebuild(); ++i; continue; } @@ -1300,7 +1308,9 @@ int BlueStore::BufferSpace::_discard(Cache* cache, uint32_t offset, uint32_t len if (b->data.length()) { bufferlist bl; bl.substr_of(b->data, b->length - keep, keep); - _add_buffer(cache, new Buffer(this, b->state, b->seq, end, bl), 0, b); + Buffer *nb = new Buffer(this, b->state, b->seq, end, bl); + nb->maybe_rebuild(); + _add_buffer(cache, nb, 0, b); } else { _add_buffer(cache, new Buffer(this, b->state, b->seq, end, keep), 0, b); } @@ -1397,6 +1407,8 @@ void BlueStore::BufferSpace::finish_write(Cache* cache, uint64_t seq) } else { b->state = Buffer::STATE_CLEAN; writing.erase(i++); + b->maybe_rebuild(); + b->data.reassign_to_mempool(mempool::mempool_bluestore_cache_data); cache->_add_buffer(b, 1, nullptr); ldout(cache->cct, 20) << __func__ << " added " << *b << dendl; } @@ -1513,7 +1525,7 @@ void BlueStore::OnodeSpace::rename( OnodeRef& oldo, const ghobject_t& old_oid, const ghobject_t& new_oid, - const mempool::bluestore_meta_other::string& new_okey) + const mempool::bluestore_cache_other::string& new_okey) { std::lock_guard l(cache->lock); ldout(cache->cct, 30) << __func__ << " " << old_oid << " -> " << new_oid @@ -1622,10 +1634,15 @@ void BlueStore::SharedBlob::get_ref(uint64_t offset, uint32_t length) } void BlueStore::SharedBlob::put_ref(uint64_t offset, uint32_t length, - PExtentVector *r) + PExtentVector *r, + set *maybe_unshared) { assert(persistent); - persistent->ref_map.put(offset, length, r); + bool maybe = false; + persistent->ref_map.put(offset, length, r, maybe_unshared ? &maybe : nullptr); + if (maybe_unshared && maybe) { + maybe_unshared->insert(this); + } } // Blob @@ -1924,6 +1941,7 @@ void BlueStore::ExtentMap::update(KeyValueDB::Transaction t, auto p = shards.begin(); auto prev_p = p; while (p != shards.end()) { + assert(p->shard_info->offset >= prev_p->shard_info->offset); auto n = p; ++n; if (p->dirty) { @@ -1957,20 +1975,13 @@ void BlueStore::ExtentMap::update(KeyValueDB::Transaction t, // avoid resharding the trailing shard, even if it is small else if (n != shards.end() && len < g_conf->bluestore_extent_map_shard_min_size) { - // we are small; combine with a neighbor - if (p == shards.begin() && endoff == OBJECT_MAX_SIZE) { - // we are an only shard - request_reshard(0, OBJECT_MAX_SIZE); - return; - } else if (p == shards.begin()) { - // combine with next shard + assert(endoff != OBJECT_MAX_SIZE); + if (p == shards.begin()) { + // we are the first shard, combine with next shard request_reshard(p->shard_info->offset, endoff + 1); - } else if (endoff == OBJECT_MAX_SIZE) { - // combine with previous shard - request_reshard(prev_p->shard_info->offset, endoff); - return; } else { - // combine with the smaller of the two + // combine either with the previous shard or the next, + // whichever is smaller if (prev_p->shard_info->bytes > n->shard_info->bytes) { request_reshard(p->shard_info->offset, endoff + 1); } else { @@ -2004,6 +2015,28 @@ void BlueStore::ExtentMap::update(KeyValueDB::Transaction t, } } +bid_t BlueStore::ExtentMap::allocate_spanning_blob_id() +{ + if (spanning_blob_map.empty()) + return 0; + bid_t bid = spanning_blob_map.rbegin()->first + 1; + // bid is valid and available. + if (bid >= 0) + return bid; + // Find next unused bid; + bid = rand() % (numeric_limits::max() + 1); + const auto begin_bid = bid; + do { + if (!spanning_blob_map.count(bid)) + return bid; + else { + bid++; + if (bid < 0) bid = 0; + } + } while (bid != begin_bid); + assert(0 == "no available blob id"); +} + void BlueStore::ExtentMap::reshard( KeyValueDB *db, KeyValueDB::Transaction t) @@ -2080,7 +2113,7 @@ void BlueStore::ExtentMap::reshard( // reshard unsigned estimate = 0; - unsigned offset = 0; + unsigned offset = needs_reshard_begin; vector new_shard_info; unsigned max_blob_end = 0; Extent dummy(needs_reshard_begin); @@ -2097,11 +2130,11 @@ void BlueStore::ExtentMap::reshard( if (estimate && estimate + extent_avg > target + (would_span ? slop : 0)) { // new shard - if (offset == 0) { + if (offset == needs_reshard_begin) { new_shard_info.emplace_back(bluestore_onode_t::shard_info()); new_shard_info.back().offset = offset; dout(20) << __func__ << " new shard 0x" << std::hex << offset - << std::dec << dendl; + << std::dec << dendl; } offset = e->logical_offset; new_shard_info.emplace_back(bluestore_onode_t::shard_info()); @@ -2111,9 +2144,9 @@ void BlueStore::ExtentMap::reshard( estimate = 0; } estimate += extent_avg; - unsigned bb = e->blob_start(); - if (bb < spanning_scan_begin) { - spanning_scan_begin = bb; + unsigned bs = e->blob_start(); + if (bs < spanning_scan_begin) { + spanning_scan_begin = bs; } uint32_t be = e->blob_end(); if (be > max_blob_end) { @@ -2149,16 +2182,21 @@ void BlueStore::ExtentMap::reshard( new_shard_info.begin(), new_shard_info.end()); shards.insert(shards.begin() + si_begin, new_shard_info.size(), Shard()); - unsigned n = sv.size(); si_end = si_begin + new_shard_info.size(); - for (unsigned i = si_begin; i < si_end; ++i) { + + assert(sv.size() == shards.size()); + + // note that we need to update every shard_info of shards here, + // as sv might have been totally re-allocated above + for (unsigned i = 0; i < shards.size(); i++) { shards[i].shard_info = &sv[i]; + } + + // mark newly added shards as dirty + for (unsigned i = si_begin; i < si_end; ++i) { shards[i].loaded = true; shards[i].dirty = true; } - for (unsigned i = si_end; i < n; ++i) { - shards[i].shard_info = &sv[i]; - } } dout(20) << __func__ << " fin " << sv << dendl; inline_bl.clear(); @@ -2181,7 +2219,7 @@ void BlueStore::ExtentMap::reshard( } if (spanning_scan_end > needs_reshard_end) { fault_range(db, needs_reshard_end, - spanning_scan_end - needs_reshard_begin); + spanning_scan_end - needs_reshard_end); } auto sp = sv.begin() + si_begin; auto esp = sv.end(); @@ -2193,12 +2231,6 @@ void BlueStore::ExtentMap::reshard( } else { shard_end = sp->offset; } - int bid; - if (spanning_blob_map.empty()) { - bid = 0; - } else { - bid = spanning_blob_map.rbegin()->first + 1; - } Extent dummy(needs_reshard_begin); for (auto e = extent_map.lower_bound(dummy); e != extent_map.end(); ++e) { if (e->logical_offset >= needs_reshard_end) { @@ -2252,7 +2284,8 @@ void BlueStore::ExtentMap::reshard( must_span = true; } if (must_span) { - b->id = bid++; + auto bid = allocate_spanning_blob_id(); + b->id = bid; spanning_blob_map[b->id] = b; dout(20) << __func__ << " adding spanning " << *b << dendl; } @@ -2287,8 +2320,6 @@ bool BlueStore::ExtentMap::encode_some( unsigned n = 0; size_t bound = 0; - denc(struct_v, bound); - denc_varint(0, bound); bool must_reshard = false; for (auto p = start; p != extent_map.end() && p->logical_offset < end; @@ -2301,21 +2332,26 @@ bool BlueStore::ExtentMap::encode_some( request_reshard(p->blob_start(), p->blob_end()); must_reshard = true; } - denc_varint(0, bound); // blobid - denc_varint(0, bound); // logical_offset - denc_varint(0, bound); // len - denc_varint(0, bound); // blob_offset + if (!must_reshard) { + denc_varint(0, bound); // blobid + denc_varint(0, bound); // logical_offset + denc_varint(0, bound); // len + denc_varint(0, bound); // blob_offset - p->blob->bound_encode( - bound, - struct_v, - p->blob->shared_blob->get_sbid(), - false); + p->blob->bound_encode( + bound, + struct_v, + p->blob->shared_blob->get_sbid(), + false); + } } if (must_reshard) { return true; } + denc(struct_v, bound); + denc_varint(0, bound); // number of extents + { auto app = bl.get_contiguous_appender(bound); denc(struct_v, app); @@ -2572,7 +2608,6 @@ void BlueStore::ExtentMap::fault_range( } void BlueStore::ExtentMap::dirty_range( - KeyValueDB::Transaction t, uint32_t offset, uint32_t length) { @@ -2614,15 +2649,6 @@ BlueStore::extent_map_t::iterator BlueStore::ExtentMap::find( return extent_map.find(dummy); } -BlueStore::extent_map_t::iterator BlueStore::ExtentMap::find_lextent( - uint64_t offset) -{ - auto fp = seek_lextent(offset); - if (fp != extent_map.end() && fp->logical_offset > offset) - return extent_map.end(); // extent is past offset - return fp; -} - BlueStore::extent_map_t::iterator BlueStore::ExtentMap::seek_lextent( uint64_t offset) { @@ -2905,6 +2931,8 @@ void BlueStore::DeferredBatch::prepare_write( assert(i.second); // this should be a new insertion i.first->second.seq = seq; blp.copy(length, i.first->second.bl); + i.first->second.bl.reassign_to_mempool( + mempool::mempool_bluestore_writing_deferred); dout(20) << __func__ << " seq " << seq << " 0x" << std::hex << offset << "~" << length << " crc " << i.first->second.bl.crc32c(-1) @@ -3057,14 +3085,12 @@ void BlueStore::Collection::load_shared_blob(SharedBlobRef sb) void BlueStore::Collection::make_blob_shared(uint64_t sbid, BlobRef b) { - assert(!b->shared_blob->is_loaded()); - ldout(store->cct, 10) << __func__ << " " << *b << dendl; - bluestore_blob_t& blob = b->dirty_blob(); + assert(!b->shared_blob->is_loaded()); // update blob + bluestore_blob_t& blob = b->dirty_blob(); blob.set_flag(bluestore_blob_t::FLAG_SHARED); - blob.clear_flag(bluestore_blob_t::FLAG_MUTABLE); // update shared blob b->shared_blob->loaded = true; @@ -3080,6 +3106,20 @@ void BlueStore::Collection::make_blob_shared(uint64_t sbid, BlobRef b) ldout(store->cct, 20) << __func__ << " now " << *b << dendl; } +uint64_t BlueStore::Collection::make_blob_unshared(SharedBlob *sb) +{ + ldout(store->cct, 10) << __func__ << " " << *sb << dendl; + assert(sb->is_loaded()); + + uint64_t sbid = sb->get_sbid(); + shared_blob_set.remove(sb); + sb->loaded = false; + delete sb->persistent; + sb->sbid_unloaded = 0; + ldout(store->cct, 20) << __func__ << " now " << *sb << dendl; + return sbid; +} + BlueStore::OnodeRef BlueStore::Collection::get_onode( const ghobject_t& oid, bool create) @@ -3099,7 +3139,7 @@ BlueStore::OnodeRef BlueStore::Collection::get_onode( if (o) return o; - mempool::bluestore_meta_other::string key; + mempool::bluestore_cache_other::string key; get_object_key(store->cct, oid, &key); ldout(store->cct, 20) << __func__ << " oid " << oid << " key " @@ -3122,7 +3162,7 @@ BlueStore::OnodeRef BlueStore::Collection::get_onode( assert(r >= 0); on = new Onode(this, oid, key); on->exists = true; - bufferptr::iterator p = v.front().begin(); + bufferptr::iterator p = v.front().begin_deep(); on->onode.decode(p); // initialize extent_map @@ -3189,12 +3229,13 @@ void BlueStore::Collection::split_cache( } ldout(store->cct, 20) << __func__ << " moving " << *sb << dendl; sb->coll = dest; + if (sb->get_sbid()) { + ldout(store->cct, 20) << __func__ + << " moving registration " << *sb << dendl; + shared_blob_set.remove(sb); + dest->shared_blob_set.add(dest, sb); + } if (dest->cache != cache) { - if (sb->get_sbid()) { - ldout(store->cct, 20) << __func__ << " moving registration " << *sb << dendl; - shared_blob_set.remove(sb); - dest->shared_blob_set.add(dest, sb); - } for (auto& i : sb->bc.buffer_map) { if (!i.second->is_writing()) { ldout(store->cct, 20) << __func__ << " moving " << *i.second @@ -3204,54 +3245,41 @@ void BlueStore::Collection::split_cache( } } } - - } } } -void BlueStore::Collection::trim_cache() -{ - // see if mempool stats have updated - uint64_t total_bytes; - uint64_t total_onodes; - size_t seq; - store->get_mempool_stats(&seq, &total_bytes, &total_onodes); - if (seq == cache->last_trim_seq) { - ldout(store->cct, 30) << __func__ << " no new mempool stats; nothing to do" - << dendl; - return; - } - cache->last_trim_seq = seq; - - // trim - if (total_onodes < 2) { - total_onodes = 2; - } - float bytes_per_onode = (float)total_bytes / (float)total_onodes; - size_t num_shards = store->cache_shards.size(); - uint64_t shard_target = store->cct->_conf->bluestore_cache_size / num_shards; - ldout(store->cct, 30) << __func__ - << " total meta bytes " << total_bytes - << ", total onodes " << total_onodes - << ", bytes_per_onode " << bytes_per_onode - << dendl; - cache->trim(shard_target, store->cct->_conf->bluestore_cache_meta_ratio, - bytes_per_onode); - - store->_update_cache_logger(); -} - // ======================================================= void *BlueStore::MempoolThread::entry() { Mutex::Locker l(lock); while (!stop) { - store->mempool_bytes = mempool::bluestore_meta_other::allocated_bytes() + - mempool::bluestore_meta_onode::allocated_bytes(); - store->mempool_onodes = mempool::bluestore_meta_onode::allocated_items(); - ++store->mempool_seq; + uint64_t meta_bytes = + mempool::bluestore_cache_other::allocated_bytes() + + mempool::bluestore_cache_onode::allocated_bytes(); + uint64_t onode_num = + mempool::bluestore_cache_onode::allocated_items(); + + if (onode_num < 2) { + onode_num = 2; + } + + float bytes_per_onode = (float)meta_bytes / (float)onode_num; + size_t num_shards = store->cache_shards.size(); + float target_ratio = store->cache_meta_ratio + store->cache_data_ratio; + // A little sloppy but should be close enough + uint64_t shard_target = target_ratio * (store->cct->_conf->bluestore_cache_size / num_shards); + + for (auto i : store->cache_shards) { + i->trim(shard_target, + store->cache_meta_ratio, + store->cache_data_ratio, + bytes_per_onode); + } + + store->_update_cache_logger(); + utime_t wait; wait += store->cct->_conf->bluestore_cache_trim_interval; cond.WaitInterval(lock, wait); @@ -3262,6 +3290,108 @@ void *BlueStore::MempoolThread::entry() // ======================================================= +// OmapIteratorImpl + +#undef dout_prefix +#define dout_prefix *_dout << "bluestore.OmapIteratorImpl(" << this << ") " + +BlueStore::OmapIteratorImpl::OmapIteratorImpl( + CollectionRef c, OnodeRef o, KeyValueDB::Iterator it) + : c(c), o(o), it(it) +{ + RWLock::RLocker l(c->lock); + if (o->onode.has_omap()) { + get_omap_key(o->onode.nid, string(), &head); + get_omap_tail(o->onode.nid, &tail); + it->lower_bound(head); + } +} + +int BlueStore::OmapIteratorImpl::seek_to_first() +{ + RWLock::RLocker l(c->lock); + if (o->onode.has_omap()) { + it->lower_bound(head); + } else { + it = KeyValueDB::Iterator(); + } + return 0; +} + +int BlueStore::OmapIteratorImpl::upper_bound(const string& after) +{ + RWLock::RLocker l(c->lock); + if (o->onode.has_omap()) { + string key; + get_omap_key(o->onode.nid, after, &key); + ldout(c->store->cct,20) << __func__ << " after " << after << " key " + << pretty_binary_string(key) << dendl; + it->upper_bound(key); + } else { + it = KeyValueDB::Iterator(); + } + return 0; +} + +int BlueStore::OmapIteratorImpl::lower_bound(const string& to) +{ + RWLock::RLocker l(c->lock); + if (o->onode.has_omap()) { + string key; + get_omap_key(o->onode.nid, to, &key); + ldout(c->store->cct,20) << __func__ << " to " << to << " key " + << pretty_binary_string(key) << dendl; + it->lower_bound(key); + } else { + it = KeyValueDB::Iterator(); + } + return 0; +} + +bool BlueStore::OmapIteratorImpl::valid() +{ + RWLock::RLocker l(c->lock); + bool r = o->onode.has_omap() && it && it->valid() && + it->raw_key().second <= tail; + if (it && it->valid()) { + ldout(c->store->cct,20) << __func__ << " is at " + << pretty_binary_string(it->raw_key().second) + << dendl; + } + return r; +} + +int BlueStore::OmapIteratorImpl::next(bool validate) +{ + RWLock::RLocker l(c->lock); + if (o->onode.has_omap()) { + it->next(); + return 0; + } else { + return -1; + } +} + +string BlueStore::OmapIteratorImpl::key() +{ + RWLock::RLocker l(c->lock); + assert(it->valid()); + string db_key = it->raw_key().second; + string user_key; + decode_omap_key(db_key, &user_key); + return user_key; +} + +bufferlist BlueStore::OmapIteratorImpl::value() +{ + RWLock::RLocker l(c->lock); + assert(it->valid()); + return it->value(); +} + + +// ===================================== + #undef dout_prefix #define dout_prefix *_dout << "bluestore(" << path << ") " @@ -3281,22 +3411,12 @@ BlueStore::BlueStore(CephContext *cct, const string& path) cct->_conf->bluestore_throttle_bytes + cct->_conf->bluestore_throttle_deferred_bytes), kv_sync_thread(this), + kv_finalize_thread(this), mempool_thread(this) { _init_logger(); cct->_conf->add_observer(this); set_cache_shards(1); - - if (cct->_conf->bluestore_shard_finishers) { - m_finisher_num = cct->_conf->osd_op_num_shards; - } - - for (int i = 0; i < m_finisher_num; ++i) { - ostringstream oss; - oss << "finisher-" << i; - Finisher *f = new Finisher(cct, oss.str(), "finisher"); - finishers.push_back(f); - } } BlueStore::BlueStore(CephContext *cct, @@ -3309,6 +3429,7 @@ BlueStore::BlueStore(CephContext *cct, cct->_conf->bluestore_throttle_bytes + cct->_conf->bluestore_throttle_deferred_bytes), kv_sync_thread(this), + kv_finalize_thread(this), min_alloc_size(_min_alloc_size), min_alloc_size_order(ctz(_min_alloc_size)), mempool_thread(this) @@ -3363,9 +3484,9 @@ const char **BlueStore::get_tracked_conf_keys() const "bluestore_compression_max_blob_size_hdd", "bluestore_max_alloc_size", "bluestore_prefer_deferred_size", - "bleustore_deferred_batch_ops", - "bleustore_deferred_batch_ops_hdd", - "bleustore_deferred_batch_ops_ssd", + "bluestore_deferred_batch_ops", + "bluestore_deferred_batch_ops_hdd", + "bluestore_deferred_batch_ops_ssd", "bluestore_throttle_bytes", "bluestore_throttle_deferred_bytes", "bluestore_throttle_cost_per_io_hdd", @@ -3524,6 +3645,41 @@ void BlueStore::_set_blob_size() << std::dec << dendl; } +int BlueStore::_set_cache_sizes() +{ + cache_meta_ratio = cct->_conf->bluestore_cache_meta_ratio; + cache_kv_ratio = cct->_conf->bluestore_cache_kv_ratio; + cache_data_ratio = + (double)1.0 - (double)cache_meta_ratio - (double)cache_kv_ratio; + + if (cache_meta_ratio <= 0 || cache_meta_ratio > 1.0) { + derr << __func__ << "bluestore_cache_meta_ratio (" << cache_meta_ratio + << ") must be in range (0,1.0]" << dendl; + return -EINVAL; + } + if (cache_kv_ratio <= 0 || cache_kv_ratio > 1.0) { + derr << __func__ << "bluestore_cache_kv_ratio (" << cache_kv_ratio + << ") must be in range (0,1.0]" << dendl; + return -EINVAL; + } + if (cache_meta_ratio + cache_kv_ratio > 1.0) { + derr << __func__ << "bluestore_cache_meta_ratio (" << cache_meta_ratio + << ") + bluestore_cache_kv_ratio (" << cache_kv_ratio + << ") = " << cache_meta_ratio + cache_kv_ratio << "; must be <= 1.0" + << dendl; + return -EINVAL; + } + if (cache_data_ratio < 0) { + // deal with floating point imprecision + cache_data_ratio = 0; + } + dout(1) << __func__ << " meta " << cache_meta_ratio + << " kv " << cache_kv_ratio + << " data " << cache_data_ratio + << dendl; + return 0; +} + void BlueStore::_init_logger() { PerfCountersBuilder b(cct, "bluestore", @@ -3699,6 +3855,12 @@ int BlueStore::get_block_device_fsid(CephContext* cct, const string& path, int BlueStore::_open_path() { + // initial sanity check + int r = _set_cache_sizes(); + if (r < 0) { + return r; + } + assert(path_fd < 0); path_fd = ::open(path.c_str(), O_DIRECTORY); if (path_fd < 0) { @@ -3804,7 +3966,11 @@ int BlueStore::_check_or_set_bdev_label( int r = _read_bdev_label(cct, path, &label); if (r < 0) return r; - if (label.osd_uuid != fsid) { + if (cct->_conf->bluestore_debug_permit_any_bdev_label) { + dout(20) << __func__ << " bdev " << path << " fsid " << label.osd_uuid + << " and fsid " << fsid << " check bypassed" << dendl; + } + else if (label.osd_uuid != fsid) { derr << __func__ << " bdev " << path << " fsid " << label.osd_uuid << " does not match our fsid " << fsid << dendl; return -EIO; @@ -4117,6 +4283,38 @@ int BlueStore::_lock_fsid() return 0; } +bool BlueStore::is_rotational() +{ + if (bdev) { + return bdev->is_rotational(); + } + + bool rotational = true; + int r = _open_path(); + if (r < 0) + goto out; + r = _open_fsid(false); + if (r < 0) + goto out_path; + r = _read_fsid(&fsid); + if (r < 0) + goto out_fsid; + r = _lock_fsid(); + if (r < 0) + goto out_fsid; + r = _open_bdev(false); + if (r < 0) + goto out_fsid; + rotational = bdev->is_rotational(); + _close_bdev(); + out_fsid: + _close_fsid(); + out_path: + _close_path(); + out: + return rotational; +} + bool BlueStore::test_mount_in_use() { // most error conditions mean the mount is not in use (e.g., because @@ -4222,8 +4420,13 @@ int BlueStore::_open_db(bool create) } bluefs_shared_bdev = BlueFS::BDEV_SLOW; bluefs_single_shared_device = false; - } else { + } else if (::lstat(bfn.c_str(), &st) == -1) { bluefs_shared_bdev = BlueFS::BDEV_DB; + } else { + //symlink exist is bug + derr << __func__ << " " << bfn << " link target doesn't exist" << dendl; + r = -errno; + goto free_bluefs; } // shared device @@ -4242,9 +4445,11 @@ int BlueStore::_open_db(bool create) initial = MAX(initial, cct->_conf->bluestore_bluefs_min); // align to bluefs's alloc_size initial = P2ROUNDUP(initial, cct->_conf->bluefs_alloc_size); - initial += cct->_conf->bluefs_alloc_size - SUPER_RESERVED; - bluefs->add_block_extent(bluefs_shared_bdev, SUPER_RESERVED, initial); - bluefs_extents.insert(SUPER_RESERVED, initial); + // put bluefs in the middle of the device in case it is an HDD + uint64_t start = P2ALIGN((bdev->get_size() - initial) / 2, + cct->_conf->bluefs_alloc_size); + bluefs->add_block_extent(bluefs_shared_bdev, start, initial); + bluefs_extents.insert(start, initial); } bfn = path + "/block.wal"; @@ -4276,8 +4481,13 @@ int BlueStore::_open_db(bool create) } cct->_conf->set_val("rocksdb_separate_wal_dir", "true"); bluefs_single_shared_device = false; - } else { + } else if (::lstat(bfn.c_str(), &st) == -1) { cct->_conf->set_val("rocksdb_separate_wal_dir", "false"); + } else { + //symlink exist is bug + derr << __func__ << " " << bfn << " link target doesn't exist" << dendl; + r = -errno; + goto free_bluefs; } if (create) { @@ -4374,6 +4584,8 @@ int BlueStore::_open_db(bool create) FreelistManager::setup_merge_operators(db); db->set_merge_operator(PREFIX_STAT, merge_op); + db->set_cache_size(cct->_conf->bluestore_cache_size * cache_kv_ratio); + if (kv_backend == "rocksdb") options = cct->_conf->bluestore_rocksdb_options; db->init(options); @@ -4625,6 +4837,24 @@ int BlueStore::_open_collections(int *errors) return 0; } +void BlueStore::open_statfs() +{ + bufferlist bl; + int r = db->get(PREFIX_STAT, "bluestore_statfs", &bl); + if (r >= 0) { + if (size_t(bl.length()) >= sizeof(vstatfs.values)) { + auto it = bl.begin(); + vstatfs.decode(it); + } + else { + dout(10) << __func__ << " store_statfs is corrupt, using empty" << dendl; + } + } + else { + dout(10) << __func__ << " store_statfs missed, using empty" << dendl; + } +} + int BlueStore::_setup_block_symlink_or_file( string name, string epath, @@ -4878,12 +5108,6 @@ int BlueStore::mkfs() } } - // indicate success by writing the 'mkfs_done' file - r = write_meta("mkfs_done", "yes"); - if (r < 0) - goto out_close_alloc; - dout(10) << __func__ << " success" << dendl; - out_close_alloc: _close_alloc(); out_close_fm: @@ -4907,8 +5131,16 @@ int BlueStore::mkfs() r = -EIO; } } + + if (r == 0) { + // indicate success by writing the 'mkfs_done' file + r = write_meta("mkfs_done", "yes"); + } + if (r < 0) { derr << __func__ << " failed, " << cpp_strerror(r) << dendl; + } else { + dout(0) << __func__ << " success" << dendl; } return r; } @@ -5006,10 +5238,7 @@ int BlueStore::_mount(bool kv_only) goto out_coll; } - for (auto f : finishers) { - f->start(); - } - kv_sync_thread.create("bstore_kv_sync"); + _kv_start(); r = _deferred_replay(); if (r < 0) @@ -5023,12 +5252,8 @@ int BlueStore::_mount(bool kv_only) out_stop: _kv_stop(); - for (auto f : finishers) { - f->wait_for_empty(); - f->stop(); - } out_coll: - flush_cache(); + _flush_cache(); out_alloc: _close_alloc(); out_fm: @@ -5056,14 +5281,8 @@ int BlueStore::umount() dout(20) << __func__ << " stopping kv thread" << dendl; _kv_stop(); - for (auto f : finishers) { - dout(20) << __func__ << " draining finisher" << dendl; - f->wait_for_empty(); - dout(20) << __func__ << " stopping finisher" << dendl; - f->stop(); - } _reap_collections(); - flush_cache(); + _flush_cache(); dout(20) << __func__ << " closing" << dendl; mounted = false; @@ -5144,10 +5363,15 @@ int BlueStore::fsck(bool deep) { dout(1) << __func__ << (deep ? " (deep)" : " (shallow)") << " start" << dendl; int errors = 0; - mempool::bluestore_fsck::set used_nids; - mempool::bluestore_fsck::set used_omap_head; + + typedef btree::btree_set< + uint64_t,std::less, + mempool::bluestore_fsck::pool_allocator> uint64_t_btree_t; + uint64_t_btree_t used_nids; + uint64_t_btree_t used_omap_head; + uint64_t_btree_t used_sbids; + mempool_dynamic_bitset used_blocks; - mempool::bluestore_fsck::set used_sbids; KeyValueDB::Iterator it; store_statfs_t expected_statfs, actual_statfs; struct sb_info_t { @@ -5209,7 +5433,10 @@ int BlueStore::fsck(bool deep) mempool_thread.init(); + // we need finishers and kv_{sync,finalize}_thread *just* for replay + _kv_start(); r = _deferred_replay(); + _kv_stop(); if (r < 0) goto out_scan; @@ -5252,6 +5479,9 @@ int BlueStore::fsck(bool deep) spg_t pgid; mempool::bluestore_fsck::list expecting_shards; for (it->lower_bound(string()); it->valid(); it->next()) { + if (g_conf->bluestore_debug_fsck_abort) { + goto out_scan; + } dout(30) << " key " << pretty_binary_string(it->key()) << dendl; if (is_extent_shard_key(it->key())) { while (!expecting_shards.empty() && @@ -5530,7 +5760,6 @@ int BlueStore::fsck(bool deep) used_omap_head.insert(o->onode.nid); } } - c->trim_cache(); } } dout(1) << __func__ << " checking shared_blobs" << dendl; @@ -5675,7 +5904,7 @@ int BlueStore::fsck(bool deep) out_scan: mempool_thread.shutdown(); - flush_cache(); + _flush_cache(); out_alloc: _close_alloc(); out_fm: @@ -5740,27 +5969,16 @@ int BlueStore::statfs(struct store_statfs_t *buf) } } - bufferlist bl; - int r = db->get(PREFIX_STAT, "bluestore_statfs", &bl); - if (r >= 0) { - TransContext::volatile_statfs vstatfs; - if (size_t(bl.length()) >= sizeof(vstatfs.values)) { - auto it = bl.begin(); - vstatfs.decode(it); - - buf->allocated = vstatfs.allocated(); - buf->stored = vstatfs.stored(); - buf->compressed = vstatfs.compressed(); - buf->compressed_original = vstatfs.compressed_original(); - buf->compressed_allocated = vstatfs.compressed_allocated(); - } else { - dout(10) << __func__ << " store_statfs is corrupt, using empty" << dendl; - } - } else { - dout(10) << __func__ << " store_statfs missed, using empty" << dendl; + { + std::lock_guard l(vstatfs_lock); + + buf->allocated = vstatfs.allocated(); + buf->stored = vstatfs.stored(); + buf->compressed = vstatfs.compressed(); + buf->compressed_original = vstatfs.compressed_original(); + buf->compressed_allocated = vstatfs.compressed_allocated(); } - dout(20) << __func__ << *buf << dendl; return 0; } @@ -5870,7 +6088,6 @@ bool BlueStore::exists(CollectionHandle &c_, const ghobject_t& oid) r = false; } - c->trim_cache(); return r; } @@ -5908,7 +6125,6 @@ int BlueStore::stat( st->st_nlink = 1; } - c->trim_cache(); int r = 0; if (_debug_mdata_eio(oid)) { r = -EIO; @@ -5985,7 +6201,6 @@ int BlueStore::read( out: assert(allow_eio || r != -EIO); - c->trim_cache(); if (r == 0 && _debug_data_eio(oid)) { r = -EIO; derr << __func__ << " " << c->cid << " " << oid << " INJECT EIO" << dendl; @@ -6036,7 +6251,6 @@ int BlueStore::_do_read( uint32_t op_flags) { FUNCTRACE(); - boost::intrusive::set::iterator ep, eend; int r = 0; dout(20) << __func__ << " 0x" << std::hex << offset << "~" << length @@ -6425,7 +6639,6 @@ int BlueStore::_fiemap( } out: - c->trim_cache(); dout(20) << __func__ << " 0x" << std::hex << offset << "~" << length << " size = 0x(" << destset << ")" << std::dec << dendl; return 0; @@ -6513,7 +6726,7 @@ int BlueStore::getattr( int r; { RWLock::RLocker l(c->lock); - mempool::bluestore_meta_other::string k(name); + mempool::bluestore_cache_other::string k(name); OnodeRef o = c->get_onode(oid, false); if (!o || !o->exists) { @@ -6529,7 +6742,6 @@ int BlueStore::getattr( r = 0; } out: - c->trim_cache(); if (r == 0 && _debug_mdata_eio(oid)) { r = -EIO; derr << __func__ << " " << c->cid << " " << oid << " INJECT EIO" << dendl; @@ -6577,7 +6789,6 @@ int BlueStore::getattrs( } out: - c->trim_cache(); if (r == 0 && _debug_mdata_eio(oid)) { r = -EIO; derr << __func__ << " " << c->cid << " " << oid << " INJECT EIO" << dendl; @@ -6654,7 +6865,6 @@ int BlueStore::collection_list( r = _collection_list(c, start, end, max, ls, pnext); } - c->trim_cache(); dout(10) << __func__ << " " << c->cid << " start " << start << " end " << end << " max " << max << " = " << r << ", ls.size() = " << ls->size() @@ -6774,91 +6984,6 @@ out: return r; } -// omap reads - -BlueStore::OmapIteratorImpl::OmapIteratorImpl( - CollectionRef c, OnodeRef o, KeyValueDB::Iterator it) - : c(c), o(o), it(it) -{ - RWLock::RLocker l(c->lock); - if (o->onode.has_omap()) { - get_omap_key(o->onode.nid, string(), &head); - get_omap_tail(o->onode.nid, &tail); - it->lower_bound(head); - } -} - -int BlueStore::OmapIteratorImpl::seek_to_first() -{ - RWLock::RLocker l(c->lock); - if (o->onode.has_omap()) { - it->lower_bound(head); - } else { - it = KeyValueDB::Iterator(); - } - return 0; -} - -int BlueStore::OmapIteratorImpl::upper_bound(const string& after) -{ - RWLock::RLocker l(c->lock); - if (o->onode.has_omap()) { - string key; - get_omap_key(o->onode.nid, after, &key); - it->upper_bound(key); - } else { - it = KeyValueDB::Iterator(); - } - return 0; -} - -int BlueStore::OmapIteratorImpl::lower_bound(const string& to) -{ - RWLock::RLocker l(c->lock); - if (o->onode.has_omap()) { - string key; - get_omap_key(o->onode.nid, to, &key); - it->lower_bound(key); - } else { - it = KeyValueDB::Iterator(); - } - return 0; -} - -bool BlueStore::OmapIteratorImpl::valid() -{ - RWLock::RLocker l(c->lock); - return o->onode.has_omap() && it && it->valid() && it->raw_key().second <= tail; -} - -int BlueStore::OmapIteratorImpl::next(bool validate) -{ - RWLock::RLocker l(c->lock); - if (o->onode.has_omap()) { - it->next(); - return 0; - } else { - return -1; - } -} - -string BlueStore::OmapIteratorImpl::key() -{ - RWLock::RLocker l(c->lock); - assert(it->valid()); - string db_key = it->raw_key().second; - string user_key; - decode_omap_key(db_key, &user_key); - return user_key; -} - -bufferlist BlueStore::OmapIteratorImpl::value() -{ - RWLock::RLocker l(c->lock); - assert(it->valid()); - return it->value(); -} - int BlueStore::omap_get( const coll_t& cid, ///< [in] Collection containing oid const ghobject_t &oid, ///< [in] Object containing omap @@ -7325,6 +7450,7 @@ int BlueStore::_open_super_meta() dout(10) << __func__ << " min_alloc_size 0x" << std::hex << min_alloc_size << std::dec << dendl; } + open_statfs(); _set_alloc_sizes(); _set_throttle_params(); @@ -7438,6 +7564,11 @@ void BlueStore::_txc_update_store_statfs(TransContext *txc) logger->inc(l_bluestore_compressed_allocated, txc->statfs_delta.compressed_allocated()); logger->inc(l_bluestore_compressed_original, txc->statfs_delta.compressed_original()); + { + std::lock_guard l(vstatfs_lock); + vstatfs += txc->statfs_delta; + } + bufferlist bl; txc->statfs_delta.encode(bl); @@ -7496,7 +7627,7 @@ void BlueStore::_txc_state_proc(TransContext *txc) << dendl; } else { txc->state = TransContext::STATE_KV_SUBMITTED; - int r = db->submit_transaction(txc->t); + int r = cct->_conf->bluestore_debug_omit_kv_commit ? 0 : db->submit_transaction(txc->t); assert(r == 0); _txc_applied_kv(txc); } @@ -7509,6 +7640,9 @@ void BlueStore::_txc_state_proc(TransContext *txc) kv_queue_unsubmitted.push_back(txc); ++txc->osr->kv_committing_serially; } + if (txc->had_ios) + kv_ios++; + kv_throttle_costs += txc->cost; } return; case TransContext::STATE_KV_SUBMITTED: @@ -7559,6 +7693,9 @@ void BlueStore::_txc_finish_io(TransContext *txc) std::lock_guard l(osr->qlock); txc->state = TransContext::STATE_IO_DONE; + // release aio contexts (including pinned buffers). + txc->ioc.running_aios.clear(); + OpSequencer::q_list_t::iterator p = osr->q.iterator_to(*txc); while (p != osr->q.begin()) { --p; @@ -7662,7 +7799,7 @@ void BlueStore::_txc_write_nodes(TransContext *txc, KeyValueDB::Transaction t) bufferlist bl; ::encode(*(sb->persistent), bl); dout(20) << " shared_blob 0x" << std::hex << sbid << std::dec - << " is " << bl.length() << dendl; + << " is " << bl.length() << " " << *sb << dendl; t->set(PREFIX_SHARED_BLOB, key, bl); } } @@ -7784,6 +7921,7 @@ void BlueStore::_txc_finish(TransContext *txc) OpSequencerRef osr = txc->osr; CollectionRef c; bool empty = false; + bool submit_deferred = false; OpSequencer::q_list_t releasing_txc; { std::lock_guard l(osr->qlock); @@ -7799,6 +7937,10 @@ void BlueStore::_txc_finish(TransContext *txc) // for _osr_drain_preceding() notify = true; } + if (txc->state == TransContext::STATE_DEFERRED_QUEUED && + osr->q.size() > g_conf->bluestore_max_deferred_txc) { + submit_deferred = true; + } break; } @@ -7828,11 +7970,12 @@ void BlueStore::_txc_finish(TransContext *txc) delete txc; } - if (c) { - c->trim_cache(); + if (submit_deferred) { + // we're pinning memory; flush! we could be more fine-grained here but + // i'm not sure it's worth the bother. + deferred_try_submit(); } - if (empty && osr->zombie) { dout(10) << __func__ << " reaping empty zombie osr " << osr << dendl; osr->_unregister(); @@ -7899,6 +8042,10 @@ void BlueStore::_osr_drain_all() std::lock_guard l(kv_lock); kv_cond.notify_one(); } + { + std::lock_guard l(kv_finalize_lock); + kv_finalize_cond.notify_one(); + } for (auto osr : s) { dout(20) << __func__ << " drain " << osr << dendl; osr->drain(); @@ -7934,10 +8081,83 @@ void BlueStore::_osr_unregister_all() } } +void BlueStore::_kv_start() +{ + dout(10) << __func__ << dendl; + + if (cct->_conf->bluestore_shard_finishers) { + if (cct->_conf->osd_op_num_shards) { + m_finisher_num = cct->_conf->osd_op_num_shards; + } else { + assert(bdev); + if (bdev->is_rotational()) { + m_finisher_num = cct->_conf->osd_op_num_shards_hdd; + } else { + m_finisher_num = cct->_conf->osd_op_num_shards_ssd; + } + } + } + + assert(m_finisher_num != 0); + + for (int i = 0; i < m_finisher_num; ++i) { + ostringstream oss; + oss << "finisher-" << i; + Finisher *f = new Finisher(cct, oss.str(), "finisher"); + finishers.push_back(f); + } + + for (auto f : finishers) { + f->start(); + } + kv_sync_thread.create("bstore_kv_sync"); + kv_finalize_thread.create("bstore_kv_final"); +} + +void BlueStore::_kv_stop() +{ + dout(10) << __func__ << dendl; + { + std::unique_lock l(kv_lock); + while (!kv_sync_started) { + kv_cond.wait(l); + } + kv_stop = true; + kv_cond.notify_all(); + } + { + std::unique_lock l(kv_finalize_lock); + while (!kv_finalize_started) { + kv_finalize_cond.wait(l); + } + kv_finalize_stop = true; + kv_finalize_cond.notify_all(); + } + kv_sync_thread.join(); + kv_finalize_thread.join(); + { + std::lock_guard l(kv_lock); + kv_stop = false; + } + { + std::lock_guard l(kv_finalize_lock); + kv_finalize_stop = false; + } + dout(10) << __func__ << " stopping finishers" << dendl; + for (auto f : finishers) { + f->wait_for_empty(); + f->stop(); + } + dout(10) << __func__ << " stopped" << dendl; +} + void BlueStore::_kv_sync_thread() { dout(10) << __func__ << " start" << dendl; std::unique_lock l(kv_lock); + assert(!kv_sync_started); + kv_sync_started = true; + kv_cond.notify_all(); while (true) { assert(kv_committing.empty()); if (kv_queue.empty() && @@ -7951,6 +8171,8 @@ void BlueStore::_kv_sync_thread() } else { deque kv_submitting; deque deferred_done, deferred_stable; + uint64_t aios = 0, costs = 0; + dout(20) << __func__ << " committing " << kv_queue.size() << " submitting " << kv_queue_unsubmitted.size() << " deferred done " << deferred_done_queue.size() @@ -7960,6 +8182,10 @@ void BlueStore::_kv_sync_thread() kv_submitting.swap(kv_queue_unsubmitted); deferred_done.swap(deferred_done_queue); deferred_stable.swap(deferred_stable_queue); + aios = kv_ios; + costs = kv_throttle_costs; + kv_ios = 0; + kv_throttle_costs = 0; utime_t start = ceph_clock_now(); l.unlock(); @@ -7968,20 +8194,13 @@ void BlueStore::_kv_sync_thread() dout(30) << __func__ << " deferred_done " << deferred_done << dendl; dout(30) << __func__ << " deferred_stable " << deferred_stable << dendl; - int num_aios = 0; - for (auto txc : kv_committing) { - if (txc->had_ios) { - ++num_aios; - } - } - bool force_flush = false; // if bluefs is sharing the same device as data (only), then we // can rely on the bluefs commit to flush the device and make // deferred aios stable. that means that if we do have done deferred // txcs AND we are not on a single device, we need to force a flush. if (bluefs_single_shared_device && bluefs) { - if (num_aios) { + if (aios) { force_flush = true; } else if (kv_committing.empty() && kv_submitting.empty() && deferred_stable.empty()) { @@ -7993,7 +8212,7 @@ void BlueStore::_kv_sync_thread() force_flush = true; if (force_flush) { - dout(20) << __func__ << " num_aios=" << num_aios + dout(20) << __func__ << " num_aios=" << aios << " force_flush=" << (int)force_flush << ", flushing, deferred done->stable" << dendl; // flush/barrier on block device @@ -8035,7 +8254,7 @@ void BlueStore::_kv_sync_thread() for (auto txc : kv_submitting) { assert(txc->state == TransContext::STATE_KV_QUEUED); txc->log_state_latency(logger, l_bluestore_state_kv_queued_lat); - int r = db->submit_transaction(txc->t); + int r = cct->_conf->bluestore_debug_omit_kv_commit ? 0 : db->submit_transaction(txc->t); assert(r == 0); _txc_applied_kv(txc); --txc->osr->kv_committing_serially; @@ -8052,15 +8271,16 @@ void BlueStore::_kv_sync_thread() --txc->osr->txc_with_unstable_io; } txc->log_state_latency(logger, l_bluestore_state_kv_queued_lat); - // release throttle *before* we commit. this allows new ops - // to be prepared and enter pipeline while we are waiting on - // the kv commit sync/flush. then hopefully on the next - // iteration there will already be ops awake. otherwise, we - // end up going to sleep, and then wake up when the very first - // transaction is ready for commit. - throttle_bytes.put(txc->cost); } + // release throttle *before* we commit. this allows new ops + // to be prepared and enter pipeline while we are waiting on + // the kv commit sync/flush. then hopefully on the next + // iteration there will already be ops awake. otherwise, we + // end up going to sleep, and then wake up when the very first + // transaction is ready for commit. + throttle_bytes.put(costs); + PExtentVector bluefs_gift_extents; if (bluefs && after_flush - bluefs_last_balance > @@ -8100,7 +8320,7 @@ void BlueStore::_kv_sync_thread() } // submit synct synchronously (block and wait for it to commit) - int r = db->submit_transaction_sync(synct); + int r = cct->_conf->bluestore_debug_omit_kv_commit ? 0 : db->submit_transaction_sync(synct); assert(r == 0); if (new_nid_max) { @@ -8126,12 +8346,88 @@ void BlueStore::_kv_sync_thread() logger->tinc(l_bluestore_kv_commit_lat, dur_kv); logger->tinc(l_bluestore_kv_lat, dur); } - while (!kv_committing.empty()) { - TransContext *txc = kv_committing.front(); + + if (bluefs) { + if (!bluefs_gift_extents.empty()) { + _commit_bluefs_freespace(bluefs_gift_extents); + } + for (auto p = bluefs_extents_reclaiming.begin(); + p != bluefs_extents_reclaiming.end(); + ++p) { + dout(20) << __func__ << " releasing old bluefs 0x" << std::hex + << p.get_start() << "~" << p.get_len() << std::dec + << dendl; + alloc->release(p.get_start(), p.get_len()); + } + bluefs_extents_reclaiming.clear(); + } + + { + std::unique_lock m(kv_finalize_lock); + if (kv_committing_to_finalize.empty()) { + kv_committing_to_finalize.swap(kv_committing); + } else { + kv_committing_to_finalize.insert( + kv_committing_to_finalize.end(), + kv_committing.begin(), + kv_committing.end()); + kv_committing.clear(); + } + if (deferred_stable_to_finalize.empty()) { + deferred_stable_to_finalize.swap(deferred_stable); + } else { + deferred_stable_to_finalize.insert( + deferred_stable_to_finalize.end(), + deferred_stable.begin(), + deferred_stable.end()); + deferred_stable.clear(); + } + kv_finalize_cond.notify_one(); + } + + l.lock(); + // previously deferred "done" are now "stable" by virtue of this + // commit cycle. + deferred_stable_queue.swap(deferred_done); + } + } + dout(10) << __func__ << " finish" << dendl; + kv_sync_started = false; +} + +void BlueStore::_kv_finalize_thread() +{ + deque kv_committed; + deque deferred_stable; + dout(10) << __func__ << " start" << dendl; + std::unique_lock l(kv_finalize_lock); + assert(!kv_finalize_started); + kv_finalize_started = true; + kv_finalize_cond.notify_all(); + while (true) { + assert(kv_committed.empty()); + assert(deferred_stable.empty()); + if (kv_committing_to_finalize.empty() && + deferred_stable_to_finalize.empty()) { + if (kv_finalize_stop) + break; + dout(20) << __func__ << " sleep" << dendl; + kv_finalize_cond.wait(l); + dout(20) << __func__ << " wake" << dendl; + } else { + kv_committed.swap(kv_committing_to_finalize); + deferred_stable.swap(deferred_stable_to_finalize); + l.unlock(); + dout(20) << __func__ << " kv_committed " << kv_committed << dendl; + dout(20) << __func__ << " deferred_stable " << deferred_stable << dendl; + + while (!kv_committed.empty()) { + TransContext *txc = kv_committed.front(); assert(txc->state == TransContext::STATE_KV_SUBMITTED); _txc_state_proc(txc); - kv_committing.pop_front(); + kv_committed.pop_front(); } + for (auto b : deferred_stable) { auto p = b->txcs.begin(); while (p != b->txcs.end()) { @@ -8141,10 +8437,11 @@ void BlueStore::_kv_sync_thread() } delete b; } + deferred_stable.clear(); if (!deferred_aggressive) { std::lock_guard l(deferred_lock); - if (deferred_queue_size >= deferred_batch_ops || + if (deferred_queue_size >= deferred_batch_ops.load() || throttle_deferred_bytes.past_midpoint()) { _deferred_try_submit(); } @@ -8153,28 +8450,11 @@ void BlueStore::_kv_sync_thread() // this is as good a place as any ... _reap_collections(); - if (bluefs) { - if (!bluefs_gift_extents.empty()) { - _commit_bluefs_freespace(bluefs_gift_extents); - } - for (auto p = bluefs_extents_reclaiming.begin(); - p != bluefs_extents_reclaiming.end(); - ++p) { - dout(20) << __func__ << " releasing old bluefs 0x" << std::hex - << p.get_start() << "~" << p.get_len() << std::dec - << dendl; - alloc->release(p.get_start(), p.get_len()); - } - bluefs_extents_reclaiming.clear(); - } - l.lock(); - // previously deferred "done" are now "stable" by virtue of this - // commit cycle. - deferred_stable_queue.swap(deferred_done); } } dout(10) << __func__ << " finish" << dendl; + kv_finalize_started = false; } bluestore_deferred_op_t *BlueStore::_get_deferred_op( @@ -8297,13 +8577,15 @@ void BlueStore::_deferred_aio_finish(OpSequencer *osr) } { + uint64_t costs = 0; std::lock_guard l2(osr->qlock); for (auto& i : b->txcs) { TransContext *txc = &i; txc->state = TransContext::STATE_DEFERRED_CLEANUP; - txc->osr->qcond.notify_all(); - throttle_deferred_bytes.put(txc->cost); + costs += txc->cost; } + osr->qcond.notify_all(); + throttle_deferred_bytes.put(costs); std::lock_guard l(kv_lock); deferred_done_queue.emplace_back(b); } @@ -9485,14 +9767,12 @@ int BlueStore::_do_alloc_write( } if (!compressed && wi.new_blob) { // initialize newly created blob only - assert(!dblob.has_flag(bluestore_blob_t::FLAG_MUTABLE)); - dblob.set_flag(bluestore_blob_t::FLAG_MUTABLE); - + assert(dblob.is_mutable()); if (l->length() != wi.blob_length) { // hrm, maybe we could do better here, but let's not bother. dout(20) << __func__ << " forcing csum_order to block_size_order " << block_size_order << dendl; - csum_order = block_size_order; + csum_order = block_size_order; } else { csum_order = std::min(wctx->csum_order, ctz(l->length())); } @@ -9593,7 +9873,8 @@ void BlueStore::_wctx_finish( TransContext *txc, CollectionRef& c, OnodeRef o, - WriteContext *wctx) + WriteContext *wctx, + set *maybe_unshared_blobs) { auto oep = wctx->old_extents.begin(); while (oep != wctx->old_extents.end()) { @@ -9616,7 +9897,9 @@ void BlueStore::_wctx_finish( PExtentVector final; c->load_shared_blob(b->shared_blob); for (auto e : r) { - b->shared_blob->put_ref(e.offset, e.length, &final); + b->shared_blob->put_ref( + e.offset, e.length, &final, + b->is_referenced() ? nullptr : maybe_unshared_blobs); } dout(20) << __func__ << " shared_blob release " << final << " from " << *b->shared_blob << dendl; @@ -9693,68 +9976,41 @@ void BlueStore::_do_write_data( } } -int BlueStore::_do_write( - TransContext *txc, - CollectionRef& c, - OnodeRef o, - uint64_t offset, - uint64_t length, - bufferlist& bl, - uint32_t fadvise_flags) +void BlueStore::_choose_write_options( + CollectionRef& c, + OnodeRef o, + uint32_t fadvise_flags, + WriteContext *wctx) { - int r = 0; - - dout(20) << __func__ - << " " << o->oid - << " 0x" << std::hex << offset << "~" << length - << " - have 0x" << o->onode.size - << " (" << std::dec << o->onode.size << ")" - << " bytes" - << " fadvise_flags 0x" << std::hex << fadvise_flags << std::dec - << dendl; - _dump_onode(o); - - if (length == 0) { - return 0; - } - - uint64_t end = offset + length; - bool was_gc = false; - GarbageCollector gc(c->store->cct); - int64_t benefit; - auto dirty_start = offset; - auto dirty_end = offset + length; - - WriteContext wctx, wctx_gc; if (fadvise_flags & CEPH_OSD_OP_FLAG_FADVISE_WILLNEED) { dout(20) << __func__ << " will do buffered write" << dendl; - wctx.buffered = true; + wctx->buffered = true; } else if (cct->_conf->bluestore_default_buffered_write && (fadvise_flags & (CEPH_OSD_OP_FLAG_FADVISE_DONTNEED | CEPH_OSD_OP_FLAG_FADVISE_NOCACHE)) == 0) { dout(20) << __func__ << " defaulting to buffered write" << dendl; - wctx.buffered = true; + wctx->buffered = true; } - // FIXME: Using the MAX of the block_size_order and preferred_csum_order - // results in poor small random read performance when data was initially - // written out in large chunks. Reverting to previous behavior for now. - wctx.csum_order = block_size_order; + // apply basic csum block size + wctx->csum_order = block_size_order; // compression parameters unsigned alloc_hints = o->onode.alloc_hint_flags; auto cm = select_option( "compression_mode", - comp_mode.load(), + comp_mode.load(), [&]() { string val; if(c->pool_opts.get(pool_opts_t::COMPRESSION_MODE, &val)) { - return boost::optional(Compressor::get_comp_mode_type(val)); + return boost::optional( + Compressor::get_comp_mode_type(val)); } return boost::optional(); } ); - wctx.compress = (cm != Compressor::COMP_NONE) && + + wctx->compress = (cm != Compressor::COMP_NONE) && ((cm == Compressor::COMP_FORCE) || (cm == Compressor::COMP_AGGRESSIVE && (alloc_hints & CEPH_OSD_ALLOC_HINT_FLAG_INCOMPRESSIBLE) == 0) || @@ -9763,22 +10019,24 @@ int BlueStore::_do_write( if ((alloc_hints & CEPH_OSD_ALLOC_HINT_FLAG_SEQUENTIAL_READ) && (alloc_hints & CEPH_OSD_ALLOC_HINT_FLAG_RANDOM_READ) == 0 && - (alloc_hints & (CEPH_OSD_ALLOC_HINT_FLAG_IMMUTABLE| - CEPH_OSD_ALLOC_HINT_FLAG_APPEND_ONLY)) && + (alloc_hints & (CEPH_OSD_ALLOC_HINT_FLAG_IMMUTABLE | + CEPH_OSD_ALLOC_HINT_FLAG_APPEND_ONLY)) && (alloc_hints & CEPH_OSD_ALLOC_HINT_FLAG_RANDOM_WRITE) == 0) { + dout(20) << __func__ << " will prefer large blob and csum sizes" << dendl; + auto order = min_alloc_size_order.load(); if (o->onode.expected_write_size) { - wctx.csum_order = std::max(order, - (uint8_t)ctz(o->onode.expected_write_size)); + wctx->csum_order = std::max(order, + (uint8_t)ctz(o->onode.expected_write_size)); } else { - wctx.csum_order = order; + wctx->csum_order = order; } - if (wctx.compress) { - wctx.target_blob_size = select_option( + if (wctx->compress) { + wctx->target_blob_size = select_option( "compression_max_blob_size", - comp_max_blob_size.load(), + comp_max_blob_size.load(), [&]() { int val; if(c->pool_opts.get(pool_opts_t::COMPRESSION_MAX_BLOB_SIZE, &val)) { @@ -9789,10 +10047,10 @@ int BlueStore::_do_write( ); } } else { - if (wctx.compress) { - wctx.target_blob_size = select_option( + if (wctx->compress) { + wctx->target_blob_size = select_option( "compression_min_blob_size", - comp_min_blob_size.load(), + comp_min_blob_size.load(), [&]() { int val; if(c->pool_opts.get(pool_opts_t::COMPRESSION_MIN_BLOB_SIZE, &val)) { @@ -9803,25 +10061,107 @@ int BlueStore::_do_write( ); } } + uint64_t max_bsize = max_blob_size.load(); - if (wctx.target_blob_size == 0 || wctx.target_blob_size > max_bsize) { - wctx.target_blob_size = max_bsize; + if (wctx->target_blob_size == 0 || wctx->target_blob_size > max_bsize) { + wctx->target_blob_size = max_bsize; } + // set the min blob size floor at 2x the min_alloc_size, or else we // won't be able to allocate a smaller extent for the compressed // data. - if (wctx.compress && - wctx.target_blob_size < min_alloc_size * 2) { - wctx.target_blob_size = min_alloc_size * 2; + if (wctx->compress && + wctx->target_blob_size < min_alloc_size * 2) { + wctx->target_blob_size = min_alloc_size * 2; } + + dout(20) << __func__ << " prefer csum_order " << wctx->csum_order + << " target_blob_size 0x" << std::hex << wctx->target_blob_size + << std::dec << dendl; +} + +int BlueStore::_do_gc( + TransContext *txc, + CollectionRef& c, + OnodeRef o, + const GarbageCollector& gc, + const WriteContext& wctx, + uint64_t *dirty_start, + uint64_t *dirty_end) +{ + auto& extents_to_collect = gc.get_extents_to_collect(); + + WriteContext wctx_gc; wctx_gc.fork(wctx); // make a clone for garbage collection - dout(20) << __func__ << " prefer csum_order " << wctx.csum_order - << " target_blob_size 0x" << std::hex << wctx.target_blob_size - << std::dec << dendl; + for (auto it = extents_to_collect.begin(); + it != extents_to_collect.end(); + ++it) { + bufferlist bl; + int r = _do_read(c.get(), o, it->offset, it->length, bl, 0); + assert(r == (int)it->length); + + o->extent_map.fault_range(db, it->offset, it->length); + _do_write_data(txc, c, o, it->offset, it->length, bl, &wctx_gc); + logger->inc(l_bluestore_gc_merged, it->length); + + if (*dirty_start > it->offset) { + *dirty_start = it->offset; + } + + if (*dirty_end < it->offset + it->length) { + *dirty_end = it->offset + it->length; + } + } + + dout(30) << __func__ << " alloc write" << dendl; + int r = _do_alloc_write(txc, c, o, &wctx_gc); + if (r < 0) { + derr << __func__ << " _do_alloc_write failed with " << cpp_strerror(r) + << dendl; + return r; + } + + _wctx_finish(txc, c, o, &wctx_gc); + return 0; +} + +int BlueStore::_do_write( + TransContext *txc, + CollectionRef& c, + OnodeRef o, + uint64_t offset, + uint64_t length, + bufferlist& bl, + uint32_t fadvise_flags) +{ + int r = 0; + + dout(20) << __func__ + << " " << o->oid + << " 0x" << std::hex << offset << "~" << length + << " - have 0x" << o->onode.size + << " (" << std::dec << o->onode.size << ")" + << " bytes" + << " fadvise_flags 0x" << std::hex << fadvise_flags << std::dec + << dendl; + _dump_onode(o); + + if (length == 0) { + return 0; + } + + uint64_t end = offset + length; + + GarbageCollector gc(c->store->cct); + int64_t benefit; + auto dirty_start = offset; + auto dirty_end = end; + + WriteContext wctx; + _choose_write_options(c, o, fadvise_flags, &wctx); o->extent_map.fault_range(db, offset, length); _do_write_data(txc, c, o, offset, length, bl, &wctx); - r = _do_alloc_write(txc, c, o, &wctx); if (r < 0) { derr << __func__ << " _do_alloc_write failed with " << cpp_strerror(r) @@ -9829,54 +10169,37 @@ int BlueStore::_do_write( goto out; } + // NB: _wctx_finish() will empty old_extents + // so we must do gc estimation before that benefit = gc.estimate(offset, - length, - o->extent_map, - wctx.old_extents, - min_alloc_size); + length, + o->extent_map, + wctx.old_extents, + min_alloc_size); _wctx_finish(txc, c, o, &wctx); if (end > o->onode.size) { dout(20) << __func__ << " extending size to 0x" << std::hex << end - << std::dec << dendl; + << std::dec << dendl; o->onode.size = end; } if (benefit >= g_conf->bluestore_gc_enable_total_threshold) { - dout(20) << __func__ << " perform garbage collection, expected benefit = " - << benefit << " AUs" << dendl; - auto& extents_to_collect = gc.get_extents_to_collect(); - for (auto it = extents_to_collect.begin(); - it != extents_to_collect.end(); - ++it) { - bufferlist bl; - int r = _do_read(c.get(), o, it->offset, it->length, bl, 0); - assert(r == (int)it->length); - o->extent_map.fault_range(db, it->offset, it->length); - _do_write_data(txc, c, o, it->offset, it->length, bl, &wctx_gc); - logger->inc(l_bluestore_gc_merged, it->length); - was_gc = true; - if (dirty_start > it->offset) { - dirty_start = it->offset; - } - if (dirty_end < it->offset + it->length) { - dirty_end = it->offset + it->length; + if (!gc.get_extents_to_collect().empty()) { + dout(20) << __func__ << " perform garbage collection, " + << "expected benefit = " << benefit << " AUs" << dendl; + r = _do_gc(txc, c, o, gc, wctx, &dirty_start, &dirty_end); + if (r < 0) { + derr << __func__ << " _do_gc failed with " << cpp_strerror(r) + << dendl; + goto out; } } } - if (was_gc) { - dout(30) << __func__ << " alloc write for GC" << dendl; - r = _do_alloc_write(txc, c, o, &wctx_gc); - if (r < 0) { - derr << __func__ << " _do_alloc_write(gc) failed with " << cpp_strerror(r) - << dendl; - goto out; - } - _wctx_finish(txc, c, o, &wctx_gc); - } o->extent_map.compress_extent_map(dirty_start, dirty_end - dirty_start); - o->extent_map.dirty_range(txc->t, dirty_start, dirty_end - dirty_start); + o->extent_map.dirty_range(dirty_start, dirty_end - dirty_start); + r = 0; out: @@ -9886,9 +10209,9 @@ int BlueStore::_do_write( int BlueStore::_write(TransContext *txc, CollectionRef& c, OnodeRef& o, - uint64_t offset, size_t length, - bufferlist& bl, - uint32_t fadvise_flags) + uint64_t offset, size_t length, + bufferlist& bl, + uint32_t fadvise_flags) { dout(15) << __func__ << " " << c->cid << " " << o->oid << " 0x" << std::hex << offset << "~" << length << std::dec @@ -9936,7 +10259,7 @@ int BlueStore::_do_zero(TransContext *txc, WriteContext wctx; o->extent_map.fault_range(db, offset, length); o->extent_map.punch_hole(c, offset, length, &wctx.old_extents); - o->extent_map.dirty_range(txc->t, offset, length); + o->extent_map.dirty_range(offset, length); _wctx_finish(txc, c, o, &wctx); if (offset + length > o->onode.size) { @@ -9953,7 +10276,8 @@ int BlueStore::_do_zero(TransContext *txc, } void BlueStore::_do_truncate( - TransContext *txc, CollectionRef& c, OnodeRef o, uint64_t offset) + TransContext *txc, CollectionRef& c, OnodeRef o, uint64_t offset, + set *maybe_unshared_blobs) { dout(15) << __func__ << " " << c->cid << " " << o->oid << " 0x" << std::hex << offset << std::dec << dendl; @@ -9961,15 +10285,15 @@ void BlueStore::_do_truncate( _dump_onode(o, 30); if (offset == o->onode.size) - return ; + return; if (offset < o->onode.size) { WriteContext wctx; uint64_t length = o->onode.size - offset; o->extent_map.fault_range(db, offset, length); o->extent_map.punch_hole(c, offset, length, &wctx.old_extents); - o->extent_map.dirty_range(txc->t, offset, length); - _wctx_finish(txc, c, o, &wctx); + o->extent_map.dirty_range(offset, length); + _wctx_finish(txc, c, o, &wctx, maybe_unshared_blobs); // if we have shards past EOF, ask for a reshard if (!o->onode.extent_map_shards.empty() && @@ -10004,7 +10328,8 @@ int BlueStore::_do_remove( CollectionRef& c, OnodeRef o) { - _do_truncate(txc, c, o, 0); + set maybe_unshared_blobs; + _do_truncate(txc, c, o, 0, &maybe_unshared_blobs); if (o->onode.has_omap()) { o->flush(); _do_omap_clear(txc, o->onode.nid); @@ -10025,6 +10350,73 @@ int BlueStore::_do_remove( o->extent_map.clear(); o->onode = bluestore_onode_t(); _debug_obj_on_delete(o->oid); + + if (!o->oid.is_no_gen() && + !maybe_unshared_blobs.empty()) { + // see if we can unshare blobs still referenced by the head + dout(10) << __func__ << " gen and maybe_unshared_blobs " + << maybe_unshared_blobs << dendl; + ghobject_t nogen = o->oid; + nogen.generation = ghobject_t::NO_GEN; + OnodeRef h = c->onode_map.lookup(nogen); + if (h && h->exists) { + dout(20) << __func__ << " checking for unshareable blobs on " << h + << " " << h->oid << dendl; + map expect; + for (auto& e : h->extent_map.extent_map) { + const bluestore_blob_t& b = e.blob->get_blob(); + SharedBlob *sb = e.blob->shared_blob.get(); + if (b.is_shared() && + sb->loaded && + maybe_unshared_blobs.count(sb)) { + b.map(e.blob_offset, e.length, [&](uint64_t off, uint64_t len) { + expect[sb].get(off, len); + return 0; + }); + } + } + vector unshared_blobs; + unshared_blobs.reserve(maybe_unshared_blobs.size()); + for (auto& p : expect) { + dout(20) << " ? " << *p.first << " vs " << p.second << dendl; + if (p.first->persistent->ref_map == p.second) { + SharedBlob *sb = p.first; + dout(20) << __func__ << " unsharing " << *sb << dendl; + unshared_blobs.push_back(sb); + txc->unshare_blob(sb); + uint64_t sbid = c->make_blob_unshared(sb); + string key; + get_shared_blob_key(sbid, &key); + txc->t->rmkey(PREFIX_SHARED_BLOB, key); + } + } + + if (!unshared_blobs.empty()) { + uint32_t b_start = OBJECT_MAX_SIZE; + uint32_t b_end = 0; + for (auto& e : h->extent_map.extent_map) { + const bluestore_blob_t& b = e.blob->get_blob(); + SharedBlob *sb = e.blob->shared_blob.get(); + if (b.is_shared() && + std::find(unshared_blobs.begin(), unshared_blobs.end(), + sb) != unshared_blobs.end()) { + dout(20) << __func__ << " unsharing " << e << dendl; + bluestore_blob_t& blob = e.blob->dirty_blob(); + blob.clear_flag(bluestore_blob_t::FLAG_SHARED); + if (e.logical_offset < b_start) { + b_start = e.logical_offset; + } + if (e.logical_end() > b_end) { + b_end = e.logical_end(); + } + } + } + + h->extent_map.dirty_range(b_start, b_end - b_start); + txc->write_onode(h); + } + } + } return 0; } @@ -10476,7 +10868,7 @@ int BlueStore::_do_clone_range( ++n; } if (dirtied_oldo) { - oldo->extent_map.dirty_range(txc->t, srcoff, length); // overkill + oldo->extent_map.dirty_range(srcoff, length); // overkill txc->write_onode(oldo); } txc->write_onode(newo); @@ -10484,7 +10876,7 @@ int BlueStore::_do_clone_range( if (dstoff + length > newo->onode.size) { newo->onode.size = dstoff + length; } - newo->extent_map.dirty_range(txc->t, dstoff, length); + newo->extent_map.dirty_range(dstoff, length); _dump_onode(oldo); _dump_onode(newo); return 0; @@ -10545,7 +10937,7 @@ int BlueStore::_rename(TransContext *txc, << new_oid << dendl; int r; ghobject_t old_oid = oldo->oid; - mempool::bluestore_meta_other::string new_okey; + mempool::bluestore_cache_other::string new_okey; if (newo) { if (newo->exists) { @@ -10906,11 +11298,12 @@ void BlueStore::generate_db_histogram(Formatter *f) } -void BlueStore::flush_cache() +void BlueStore::_flush_cache() { dout(10) << __func__ << dendl; for (auto i : cache_shards) { i->trim_all(); + assert(i->empty()); } for (auto& p : coll_map) { assert(p.second->onode_map.empty()); @@ -10919,6 +11312,18 @@ void BlueStore::flush_cache() coll_map.clear(); } +// For external caller. +// We use a best-effort policy instead, e.g., +// we don't care if there are still some pinned onodes/data in the cache +// after this command is completed. +void BlueStore::flush_cache() +{ + dout(10) << __func__ << dendl; + for (auto i : cache_shards) { + i->trim_all(); + } +} + void BlueStore::_apply_padding(uint64_t head_pad, uint64_t tail_pad, bufferlist& bl, diff --git a/ceph/src/os/bluestore/BlueStore.h b/ceph/src/os/bluestore/BlueStore.h index 50b3df8d7..1114e7b4f 100644 --- a/ceph/src/os/bluestore/BlueStore.h +++ b/ceph/src/os/bluestore/BlueStore.h @@ -49,6 +49,12 @@ class BlueFS; //#define DEBUG_CACHE //#define DEBUG_DEFERRED + + +// constants for Buffer::optimize() +#define MAX_BUFFER_SLOP_RATIO_DEN 8 // so actually 1/N + + enum { l_bluestore_first = 732430, l_bluestore_kv_flush_lat, @@ -126,6 +132,7 @@ public: void _set_csum(); void _set_compression(); void _set_throttle_params(); + int _set_cache_sizes(); class TransContext; @@ -210,6 +217,13 @@ public: } length = newlen; } + void maybe_rebuild() { + if (data.length() && + (data.get_num_buffers() > 1 || + data.front().wasted() > data.length() / MAX_BUFFER_SLOP_RATIO_DEN)) { + data.rebuild(); + } + } void dump(Formatter *f) const { f->dump_string("state", get_state_name(state)); @@ -231,7 +245,7 @@ public: boost::intrusive::list_member_hook<>, &Buffer::state_item> > state_list_t; - mempool::bluestore_meta_other::map> + mempool::bluestore_cache_other::map> buffer_map; // we use a bare intrusive list here instead of std::map because @@ -248,8 +262,10 @@ public: cache->_audit("_add_buffer start"); buffer_map[b->offset].reset(b); if (b->is_writing()) { + b->data.reassign_to_mempool(mempool::mempool_bluestore_writing); writing.push_back(*b); } else { + b->data.reassign_to_mempool(mempool::mempool_bluestore_cache_data); cache->_add_buffer(b, level, near); } cache->_audit("_add_buffer end"); @@ -257,7 +273,8 @@ public: void _rm_buffer(Cache* cache, Buffer *b) { _rm_buffer(cache, buffer_map.find(b->offset)); } - void _rm_buffer(Cache* cache, map>::iterator p) { + void _rm_buffer(Cache* cache, + map>::iterator p) { assert(p != buffer_map.end()); cache->_audit("_rm_buffer start"); if (p->second->is_writing()) { @@ -372,7 +389,7 @@ public: /// put logical references, and get back any released extents void put_ref(uint64_t offset, uint32_t length, - PExtentVector *r); + PExtentVector *r, set *maybe_unshared_blobs); friend bool operator==(const SharedBlob &l, const SharedBlob &r) { return l.get_sbid() == r.get_sbid(); @@ -396,7 +413,7 @@ public: // we use a bare pointer because we don't want to affect the ref // count - mempool::bluestore_meta_other::unordered_map sb_map; + mempool::bluestore_cache_other::unordered_map sb_map; SharedBlobRef lookup(uint64_t sbid) { std::lock_guard l(lock); @@ -601,7 +618,7 @@ public: #endif }; typedef boost::intrusive_ptr BlobRef; - typedef mempool::bluestore_meta_other::map blob_map_t; + typedef mempool::bluestore_cache_other::map blob_map_t; /// a logical extent, pointing to (some portion of) a blob typedef boost::intrusive::set_base_hook > ExtentBase; //making an alias to avoid build warnings @@ -706,7 +723,7 @@ public: bool loaded = false; ///< true if shard is loaded bool dirty = false; ///< true if shard is dirty and needs reencoding }; - mempool::bluestore_meta_other::vector shards; ///< shards + mempool::bluestore_cache_other::vector shards; ///< shards bufferlist inline_bl; ///< cached encoded map, if unsharded; empty=>dirty @@ -759,6 +776,7 @@ public: } void update(KeyValueDB::Transaction t, bool force); + decltype(BlueStore::Blob::id) allocate_spanning_blob_id(); void reshard( KeyValueDB *db, KeyValueDB::Transaction t); @@ -811,14 +829,11 @@ public: uint32_t offset, uint32_t length); /// ensure a range of the map is marked dirty - void dirty_range(KeyValueDB::Transaction t, - uint32_t offset, uint32_t length); + void dirty_range(uint32_t offset, uint32_t length); + /// for seek_lextent test extent_map_t::iterator find(uint64_t offset); - /// find a lextent that includes offset - extent_map_t::iterator find_lextent(uint64_t offset); - /// seek to the first lextent including or after offset extent_map_t::iterator seek_lextent(uint64_t offset); extent_map_t::const_iterator seek_lextent(uint64_t offset) const; @@ -974,7 +989,7 @@ public: ghobject_t oid; /// key under PREFIX_OBJ where we are stored - mempool::bluestore_meta_other::string key; + mempool::bluestore_cache_other::string key; boost::intrusive::list_member_hook<> lru_item; @@ -990,7 +1005,7 @@ public: std::condition_variable flush_cond; ///< wait here for uncommitted txns Onode(Collection *c, const ghobject_t& o, - const mempool::bluestore_meta_other::string& k) + const mempool::bluestore_cache_other::string& k) : nref(0), c(c), oid(o), @@ -1020,8 +1035,6 @@ public: std::atomic num_extents = {0}; std::atomic num_blobs = {0}; - size_t last_trim_seq = 0; - static Cache *create(CephContext* cct, string type, PerfCounters *logger); Cache(CephContext* cct) : cct(cct), logger(nullptr) {} @@ -1054,7 +1067,9 @@ public: --num_blobs; } - void trim(uint64_t target_bytes, float target_meta_ratio, + void trim(uint64_t target_bytes, + float target_meta_ratio, + float target_data_ratio, float bytes_per_onode); void trim_all(); @@ -1066,6 +1081,11 @@ public: uint64_t *buffers, uint64_t *bytes) = 0; + bool empty() { + std::lock_guard l(lock); + return _get_num_onodes() == 0 && _get_buffer_bytes() == 0; + } + #ifdef DEBUG_CACHE virtual void _audit(const char *s) = 0; #else @@ -1265,7 +1285,7 @@ public: Cache *cache; /// forward lookups - mempool::bluestore_meta_other::unordered_map onode_map; + mempool::bluestore_cache_other::unordered_map onode_map; friend class Collection; // for split_cache() @@ -1282,7 +1302,7 @@ public: } void rename(OnodeRef& o, const ghobject_t& old_oid, const ghobject_t& new_oid, - const mempool::bluestore_meta_other::string& new_okey); + const mempool::bluestore_cache_other::string& new_okey); void clear(); bool empty(); @@ -1324,6 +1344,7 @@ public: void open_shared_blob(uint64_t sbid, BlobRef b); void load_shared_blob(SharedBlobRef sb); void make_blob_shared(uint64_t sbid, BlobRef b); + uint64_t make_blob_unshared(SharedBlob *sb); BlobRef new_blob() { BlobRef b = new Blob(); @@ -1347,7 +1368,6 @@ public: } void split_cache(Collection *dest); - void trim_cache(); Collection(BlueStore *ns, Cache *ca, coll_t c); }; @@ -1374,7 +1394,66 @@ public: class OpSequencer; typedef boost::intrusive_ptr OpSequencerRef; + struct volatile_statfs{ + enum { + STATFS_ALLOCATED = 0, + STATFS_STORED, + STATFS_COMPRESSED_ORIGINAL, + STATFS_COMPRESSED, + STATFS_COMPRESSED_ALLOCATED, + STATFS_LAST + }; + int64_t values[STATFS_LAST]; + volatile_statfs() { + memset(this, 0, sizeof(volatile_statfs)); + } + void reset() { + *this = volatile_statfs(); + } + volatile_statfs& operator+=(const volatile_statfs& other) { + for (size_t i = 0; i < STATFS_LAST; ++i) { + values[i] += other.values[i]; + } + return *this; + } + int64_t& allocated() { + return values[STATFS_ALLOCATED]; + } + int64_t& stored() { + return values[STATFS_STORED]; + } + int64_t& compressed_original() { + return values[STATFS_COMPRESSED_ORIGINAL]; + } + int64_t& compressed() { + return values[STATFS_COMPRESSED]; + } + int64_t& compressed_allocated() { + return values[STATFS_COMPRESSED_ALLOCATED]; + } + bool is_empty() { + return values[STATFS_ALLOCATED] == 0 && + values[STATFS_STORED] == 0 && + values[STATFS_COMPRESSED] == 0 && + values[STATFS_COMPRESSED_ORIGINAL] == 0 && + values[STATFS_COMPRESSED_ALLOCATED] == 0; + } + void decode(bufferlist::iterator& it) { + for (size_t i = 0; i < STATFS_LAST; i++) { + ::decode(values[i], it); + } + } + + void encode(bufferlist& bl) { + for (size_t i = 0; i < STATFS_LAST; i++) { + ::encode(values[i], bl); + } + } + }; + struct TransContext : public AioContext { + MEMPOOL_CLASS_HELPERS(); + typedef enum { STATE_PREPARE, STATE_AIO_WAIT, @@ -1460,57 +1539,7 @@ public: bluestore_deferred_transaction_t *deferred_txn = nullptr; ///< if any interval_set allocated, released; - struct volatile_statfs{ - enum { - STATFS_ALLOCATED = 0, - STATFS_STORED, - STATFS_COMPRESSED_ORIGINAL, - STATFS_COMPRESSED, - STATFS_COMPRESSED_ALLOCATED, - STATFS_LAST - }; - int64_t values[STATFS_LAST]; - volatile_statfs() { - memset(this, 0, sizeof(volatile_statfs)); - } - void reset() { - *this = volatile_statfs(); - } - int64_t& allocated() { - return values[STATFS_ALLOCATED]; - } - int64_t& stored() { - return values[STATFS_STORED]; - } - int64_t& compressed_original() { - return values[STATFS_COMPRESSED_ORIGINAL]; - } - int64_t& compressed() { - return values[STATFS_COMPRESSED]; - } - int64_t& compressed_allocated() { - return values[STATFS_COMPRESSED_ALLOCATED]; - } - bool is_empty() { - return values[STATFS_ALLOCATED] == 0 && - values[STATFS_STORED] == 0 && - values[STATFS_COMPRESSED] == 0 && - values[STATFS_COMPRESSED_ORIGINAL] == 0 && - values[STATFS_COMPRESSED_ALLOCATED] == 0; - } - void decode(bufferlist::iterator& it) { - for (size_t i = 0; i < STATFS_LAST; i++) { - ::decode(values[i], it); - } - } - - void encode(bufferlist& bl) { - for (size_t i = 0; i < STATFS_LAST; i++) { - ::encode(values[i], bl); - } - } - } statfs_delta; - + volatile_statfs statfs_delta; IOContext ioc; bool had_ios = false; ///< true if we submitted IOs before our kv txn @@ -1540,6 +1569,10 @@ public: void write_shared_blob(SharedBlobRef &sb) { shared_blobs.insert(sb); } + void unshare_blob(SharedBlob *sb) { + shared_blobs.erase(sb); + } + /// note we logically modified object (when onode itself is unmodified) void note_modified_object(OnodeRef &o) { // onode itself isn't written, though @@ -1729,6 +1762,14 @@ public: return NULL; } }; + struct KVFinalizeThread : public Thread { + BlueStore *store; + explicit KVFinalizeThread(BlueStore *s) : store(s) {} + void *entry() { + store->_kv_finalize_thread(); + return NULL; + } + }; struct DBHistogram { struct value_dist { @@ -1772,7 +1813,7 @@ private: bool mounted = false; RWLock coll_lock = {"BlueStore::coll_lock"}; ///< rwlock to protect coll_map - mempool::bluestore_meta_other::unordered_map coll_map; + mempool::bluestore_cache_other::unordered_map coll_map; vector cache_shards; @@ -1802,13 +1843,22 @@ private: KVSyncThread kv_sync_thread; std::mutex kv_lock; std::condition_variable kv_cond; + bool kv_sync_started = false; bool kv_stop = false; + bool kv_finalize_started = false; + bool kv_finalize_stop = false; deque kv_queue; ///< ready, already submitted deque kv_queue_unsubmitted; ///< ready, need submit by kv thread deque kv_committing; ///< currently syncing deque deferred_done_queue; ///< deferred ios done deque deferred_stable_queue; ///< deferred ios done + stable + KVFinalizeThread kv_finalize_thread; + std::mutex kv_finalize_lock; + std::condition_variable kv_finalize_cond; + deque kv_committing_to_finalize; ///< pending finalization + deque deferred_stable_to_finalize; ///< pending finalization + PerfCounters *logger = nullptr; std::mutex reap_lock; @@ -1825,7 +1875,7 @@ private: size_t block_size_order = 0; ///< bits to shift to get block size uint64_t min_alloc_size = 0; ///< minimum allocation unit (power of 2) - int deferred_batch_ops = 0; ///< deferred batch size + std::atomic deferred_batch_ops = {0}; ///< deferred batch size ///< bits for min_alloc_size std::atomic min_alloc_size_order = {0}; @@ -1849,20 +1899,16 @@ private: std::atomic max_blob_size = {0}; ///< maximum blob size + uint64_t kv_ios = 0; + uint64_t kv_throttle_costs = 0; + // cache trim control + float cache_meta_ratio = 0; ///< cache ratio dedicated to metadata + float cache_kv_ratio = 0; ///< cache ratio dedicated to kv (e.g., rocksdb) + float cache_data_ratio = 0; ///< cache ratio dedicated to object data - // note that these update in a racy way, but we don't *really* care if - // they're perfectly accurate. they are all word sized so they will - // individually update atomically, but may not be coherent with each other. - size_t mempool_seq = 0; - size_t mempool_bytes = 0; - size_t mempool_onodes = 0; - - void get_mempool_stats(size_t *seq, uint64_t *bytes, uint64_t *onodes) { - *seq = mempool_seq; - *bytes = mempool_bytes; - *onodes = mempool_onodes; - } + std::mutex vstatfs_lock; + volatile_statfs vstatfs; struct MempoolThread : public Thread { BlueStore *store; @@ -1928,6 +1974,8 @@ private: int _open_super_meta(); + void open_statfs(); + int _reconcile_bluefs_freespace(); int _balance_bluefs_freespace(PExtentVector *extents); void _commit_bluefs_freespace(const PExtentVector& extents); @@ -1967,19 +2015,10 @@ private: void _osr_drain_all(); void _osr_unregister_all(); + void _kv_start(); + void _kv_stop(); void _kv_sync_thread(); - void _kv_stop() { - { - std::lock_guard l(kv_lock); - kv_stop = true; - kv_cond.notify_all(); - } - kv_sync_thread.join(); - { - std::lock_guard l(kv_lock); - kv_stop = false; - } - } + void _kv_finalize_thread(); bluestore_deferred_op_t *_get_deferred_op(TransContext *txc, OnodeRef o); void _deferred_queue(TransContext *txc); @@ -2061,6 +2100,8 @@ public: bool wants_journal() override { return false; }; bool allows_journal() override { return false; }; + bool is_rotational() override; + static int get_block_device_fsid(CephContext* cct, const string& path, uuid_d *fsid); @@ -2100,6 +2141,7 @@ public: void get_db_statistics(Formatter *f) override; void generate_db_histogram(Formatter *f) override; + void _flush_cache(); void flush_cache() override; void dump_perf_counters(Formatter *f) override { f->open_object_section("perf_counters"); @@ -2467,7 +2509,8 @@ private: TransContext *txc, CollectionRef& c, OnodeRef o, - WriteContext *wctx); + WriteContext *wctx, + set *maybe_unshared_blobs=0); int _do_transaction(Transaction *t, TransContext *txc, @@ -2482,6 +2525,19 @@ private: void _pad_zeros(bufferlist *bl, uint64_t *offset, uint64_t chunk_size); + void _choose_write_options(CollectionRef& c, + OnodeRef o, + uint32_t fadvise_flags, + WriteContext *wctx); + + int _do_gc(TransContext *txc, + CollectionRef& c, + OnodeRef o, + const GarbageCollector& gc, + const WriteContext& wctx, + uint64_t *dirty_start, + uint64_t *dirty_end); + int _do_write(TransContext *txc, CollectionRef &c, OnodeRef o, @@ -2510,7 +2566,8 @@ private: void _do_truncate(TransContext *txc, CollectionRef& c, OnodeRef o, - uint64_t offset); + uint64_t offset, + set *maybe_unshared_blobs=0); void _truncate(TransContext *txc, CollectionRef& c, OnodeRef& o, diff --git a/ceph/src/os/bluestore/KernelDevice.cc b/ceph/src/os/bluestore/KernelDevice.cc index 52cab96bb..c6b9e5ad2 100644 --- a/ceph/src/os/bluestore/KernelDevice.cc +++ b/ceph/src/os/bluestore/KernelDevice.cc @@ -145,15 +145,17 @@ int KernelDevice::open(const string& p) } } + r = _aio_start(); + if (r < 0) { + goto out_fail; + } + fs = FS::create_by_fd(fd_direct); assert(fs); // round size down to an even block size &= ~(block_size - 1); - r = _aio_start(); - assert(r == 0); - dout(1) << __func__ << " size " << size << " (0x" << std::hex << size << std::dec << ", " @@ -261,7 +263,7 @@ int KernelDevice::collect_metadata(string prefix, map *pm) const int KernelDevice::flush() { - // protect flush with a mutex. not that we are not really protected + // protect flush with a mutex. note that we are not really protecting // data here. instead, we're ensuring that if any flush() caller // sees that io_since_flush is true, they block any racing callers // until the flush is observed. that allows racing threads to be @@ -308,7 +310,12 @@ int KernelDevice::_aio_start() dout(10) << __func__ << dendl; int r = aio_queue.init(); if (r < 0) { - derr << __func__ << " failed: " << cpp_strerror(r) << dendl; + if (r == -EAGAIN) { + derr << __func__ << " io_setup(2) failed with EAGAIN; " + << "try increasing /proc/sys/fs/aio-max-nr" << dendl; + } else { + derr << __func__ << " io_setup(2) failed: " << cpp_strerror(r) << dendl; + } return r; } aio_thread.create("bstore_aio"); @@ -373,11 +380,7 @@ void KernelDevice::_aio_thread() aio_callback(aio_callback_priv, ioc->priv); } } else { - if (ioc->num_running == 1) { - ioc->aio_wake(); - } else { - --ioc->num_running; - } + ioc->try_aio_wake(); } } } @@ -559,6 +562,9 @@ int KernelDevice::_sync_write(uint64_t off, bufferlist &bl, bool buffered) return r; } } + + io_since_flush.store(true); + return 0; } diff --git a/ceph/src/os/bluestore/NVMEDevice.cc b/ceph/src/os/bluestore/NVMEDevice.cc index 89b8b5552..9d1a84066 100644 --- a/ceph/src/os/bluestore/NVMEDevice.cc +++ b/ceph/src/os/bluestore/NVMEDevice.cc @@ -816,11 +816,7 @@ void io_complete(void *t, const struct spdk_nvme_cpl *completion) task->device->aio_callback(task->device->aio_callback_priv, ctx->priv); } } else { - if (ctx->num_running == 1) { - ctx->aio_wake(); - } else { - --ctx->num_running; - } + ctx->try_aio_wake(); } task->release_segs(queue); delete task; @@ -837,11 +833,7 @@ void io_complete(void *t, const struct spdk_nvme_cpl *completion) task->device->aio_callback(task->device->aio_callback_priv, ctx->priv); } } else { - if (ctx->num_running == 1) { - ctx->aio_wake(); - } else { - --ctx->num_running; - } + ctx->try_aio_wake(); } delete task; } else { diff --git a/ceph/src/os/bluestore/NVMEDevice.h b/ceph/src/os/bluestore/NVMEDevice.h index f670e308e..a44b1e1ec 100644 --- a/ceph/src/os/bluestore/NVMEDevice.h +++ b/ceph/src/os/bluestore/NVMEDevice.h @@ -25,7 +25,6 @@ #define _Static_assert static_assert -#include "include/atomic.h" #include "include/interval_set.h" #include "common/ceph_time.h" #include "common/Mutex.h" diff --git a/ceph/src/os/bluestore/PMEMDevice.cc b/ceph/src/os/bluestore/PMEMDevice.cc new file mode 100644 index 000000000..262eeb1c3 --- /dev/null +++ b/ceph/src/os/bluestore/PMEMDevice.cc @@ -0,0 +1,305 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2015 Intel + * + * Author: Jianpeng Ma + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include +#include +#include +#include +#include + +#include "PMEMDevice.h" +#include "include/types.h" +#include "include/compat.h" +#include "include/stringify.h" +#include "common/errno.h" +#include "common/debug.h" +#include "common/blkdev.h" + +#define dout_context cct +#define dout_subsys ceph_subsys_bdev +#undef dout_prefix +#define dout_prefix *_dout << "bdev-PMEM(" << path << ") " + +PMEMDevice::PMEMDevice(CephContext *cct, aio_callback_t cb, void *cbpriv) + : BlockDevice(cct), + fd(-1), addr(0), + size(0), block_size(0), + debug_lock("PMEMDevice::debug_lock"), + injecting_crash(0) +{ +} + +int PMEMDevice::_lock() +{ + struct flock l; + memset(&l, 0, sizeof(l)); + l.l_type = F_WRLCK; + l.l_whence = SEEK_SET; + l.l_start = 0; + l.l_len = 0; + int r = ::fcntl(fd, F_SETLK, &l); + if (r < 0) + return -errno; + return 0; +} + +int PMEMDevice::open(const string& p) +{ + path = p; + int r = 0; + dout(1) << __func__ << " path " << path << dendl; + + fd = ::open(path.c_str(), O_RDWR); + if (fd < 0) { + r = -errno; + derr << __func__ << " open got: " << cpp_strerror(r) << dendl; + return r; + } + + r = _lock(); + if (r < 0) { + derr << __func__ << " failed to lock " << path << ": " << cpp_strerror(r) + << dendl; + goto out_fail; + } + + struct stat st; + r = ::fstat(fd, &st); + if (r < 0) { + r = -errno; + derr << __func__ << " fstat got " << cpp_strerror(r) << dendl; + goto out_fail; + } + if (S_ISBLK(st.st_mode)) { + int64_t s; + r = get_block_device_size(fd, &s); + if (r < 0) { + goto out_fail; + } + size = s; + } else { + size = st.st_size; + } + + size_t map_len; + addr = (char *)pmem_map_file(path.c_str(), size, PMEM_FILE_EXCL, O_RDWR, &map_len, NULL); + if (addr == NULL) { + derr << __func__ << " pmem_map_file error" << dendl; + goto out_fail; + } + size = map_len; + + // Operate as though the block size is 4 KB. The backing file + // blksize doesn't strictly matter except that some file systems may + // require a read/modify/write if we write something smaller than + // it. + block_size = g_conf->bdev_block_size; + if (block_size != (unsigned)st.st_blksize) { + dout(1) << __func__ << " backing device/file reports st_blksize " + << st.st_blksize << ", using bdev_block_size " + << block_size << " anyway" << dendl; + } + + dout(1) << __func__ + << " size " << size + << " (" << pretty_si_t(size) << "B)" + << " block_size " << block_size + << " (" << pretty_si_t(block_size) << "B)" + << dendl; + return 0; + + out_fail: + VOID_TEMP_FAILURE_RETRY(::close(fd)); + fd = -1; + return r; +} + +void PMEMDevice::close() +{ + dout(1) << __func__ << dendl; + + assert(addr != NULL); + pmem_unmap(addr, size); + assert(fd >= 0); + VOID_TEMP_FAILURE_RETRY(::close(fd)); + fd = -1; + + path.clear(); +} + +static string get_dev_property(const char *dev, const char *property) +{ + char val[1024] = {0}; + get_block_device_string_property(dev, property, val, sizeof(val)); + return val; +} + +int PMEMDevice::collect_metadata(string prefix, map *pm) const +{ + (*pm)[prefix + "rotational"] = stringify((int)(bool)rotational); + (*pm)[prefix + "size"] = stringify(get_size()); + (*pm)[prefix + "block_size"] = stringify(get_block_size()); + (*pm)[prefix + "driver"] = "PMEMDevice"; + (*pm)[prefix + "type"] = "ssd"; + + struct stat st; + int r = ::fstat(fd, &st); + if (r < 0) + return -errno; + if (S_ISBLK(st.st_mode)) { + (*pm)[prefix + "access_mode"] = "blk"; + char partition_path[PATH_MAX]; + char dev_node[PATH_MAX]; + int rc = get_device_by_fd(fd, partition_path, dev_node, PATH_MAX); + switch (rc) { + case -EOPNOTSUPP: + case -EINVAL: + (*pm)[prefix + "partition_path"] = "unknown"; + (*pm)[prefix + "dev_node"] = "unknown"; + break; + case -ENODEV: + (*pm)[prefix + "partition_path"] = string(partition_path); + (*pm)[prefix + "dev_node"] = "unknown"; + break; + default: + { + (*pm)[prefix + "partition_path"] = string(partition_path); + (*pm)[prefix + "dev_node"] = string(dev_node); + (*pm)[prefix + "model"] = get_dev_property(dev_node, "device/model"); + (*pm)[prefix + "dev"] = get_dev_property(dev_node, "dev"); + + // nvme exposes a serial number + string serial = get_dev_property(dev_node, "device/serial"); + if (serial.length()) { + (*pm)[prefix + "serial"] = serial; + } + + // nvme has a device/device/* structure; infer from that. there + // is probably a better way? + string nvme_vendor = get_dev_property(dev_node, "device/device/vendor"); + if (nvme_vendor.length()) { + (*pm)[prefix + "type"] = "nvme"; + } + } + } + } else { + (*pm)[prefix + "access_mode"] = "file"; + (*pm)[prefix + "path"] = path; + } + return 0; +} + +int PMEMDevice::flush() +{ + //Because all write is persist. So no need + return 0; +} + + +void PMEMDevice::aio_submit(IOContext *ioc) +{ + return; +} + +int PMEMDevice::write(uint64_t off, bufferlist& bl, bool buffered) +{ + uint64_t len = bl.length(); + dout(20) << __func__ << " " << off << "~" << len << dendl; + assert(len > 0); + assert(off < size); + assert(off + len <= size); + + dout(40) << "data: "; + bl.hexdump(*_dout); + *_dout << dendl; + + if (g_conf->bdev_inject_crash && + rand() % g_conf->bdev_inject_crash == 0) { + derr << __func__ << " bdev_inject_crash: dropping io " << off << "~" << len + << dendl; + ++injecting_crash; + return 0; + } + + bufferlist::iterator p = bl.begin(); + uint32_t off1 = off; + while (len) { + const char *data; + uint32_t l = p.get_ptr_and_advance(len, &data); + pmem_memcpy_persist(addr + off1, data, l); + len -= l; + off1 += l; + } + + return 0; +} + +int PMEMDevice::aio_write( + uint64_t off, + bufferlist &bl, + IOContext *ioc, + bool buffered) +{ + return write(off, bl, buffered); +} + + +int PMEMDevice::read(uint64_t off, uint64_t len, bufferlist *pbl, + IOContext *ioc, + bool buffered) +{ + dout(5) << __func__ << " " << off << "~" << len << dendl; + assert(len > 0); + assert(off < size); + assert(off + len <= size); + + bufferptr p = buffer::create_page_aligned(len); + memcpy(p.c_str(), addr + off, len); + + pbl->clear(); + pbl->push_back(std::move(p)); + + dout(40) << "data: "; + pbl->hexdump(*_dout); + *_dout << dendl; + + return 0; +} + +int PMEMDevice::aio_read(uint64_t off, uint64_t len, bufferlist *pbl, + IOContext *ioc) +{ + return read(off, len, pbl, ioc, false); +} + +int PMEMDevice::read_random(uint64_t off, uint64_t len, char *buf, bool buffered) +{ + assert(len > 0); + assert(off < size); + assert(off + len <= size); + + memcpy(buf, addr + off, len); + return 0; +} + + +int PMEMDevice::invalidate_cache(uint64_t off, uint64_t len) +{ + dout(5) << __func__ << " " << off << "~" << len << dendl; + return 0; +} + + diff --git a/ceph/src/os/bluestore/PMEMDevice.h b/ceph/src/os/bluestore/PMEMDevice.h new file mode 100644 index 000000000..a908c7876 --- /dev/null +++ b/ceph/src/os/bluestore/PMEMDevice.h @@ -0,0 +1,74 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2015 Intel + * + * Author: Jianpeng Ma + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_OS_BLUESTORE_PMEMDEVICE_H +#define CEPH_OS_BLUESTORE_PMEMDEVICE_H + +#include + +#include "os/fs/FS.h" +#include "os/fs/aio.h" +#include "include/interval_set.h" +#include "BlockDevice.h" + +class PMEMDevice : public BlockDevice { + int fd; + char *addr; //the address of mmap + uint64_t size; + uint64_t block_size; + std::string path; + + Mutex debug_lock; + interval_set debug_inflight; + + std::atomic_int injecting_crash; + int _lock(); + +public: + PMEMDevice(CephContext *cct, aio_callback_t cb, void *cbpriv); + + + void aio_submit(IOContext *ioc) override; + + uint64_t get_size() const override { + return size; + } + uint64_t get_block_size() const override { + return block_size; + } + + int collect_metadata(std::string prefix, map *pm) const override; + + int read(uint64_t off, uint64_t len, bufferlist *pbl, + IOContext *ioc, + bool buffered) override; + int aio_read(uint64_t off, uint64_t len, bufferlist *pbl, + IOContext *ioc) override; + + int read_random(uint64_t off, uint64_t len, char *buf, bool buffered) override; + int write(uint64_t off, bufferlist& bl, bool buffered) override; + int aio_write(uint64_t off, bufferlist& bl, + IOContext *ioc, + bool buffered) override; + int flush() override; + + // for managing buffered readers/writers + int invalidate_cache(uint64_t off, uint64_t len) override; + int open(const std::string &path) override; + void close() override; +}; + +#endif diff --git a/ceph/src/os/bluestore/bluefs_types.cc b/ceph/src/os/bluestore/bluefs_types.cc index e414c8b6d..93d79ffec 100644 --- a/ceph/src/os/bluestore/bluefs_types.cc +++ b/ceph/src/os/bluestore/bluefs_types.cc @@ -23,7 +23,7 @@ void bluefs_extent_t::generate_test_instances(list& ls) ls.back()->bdev = 1; } -ostream& operator<<(ostream& out, bluefs_extent_t e) +ostream& operator<<(ostream& out, const bluefs_extent_t& e) { return out << (int)e.bdev << ":0x" << std::hex << e.offset << "+" << e.length << std::dec; diff --git a/ceph/src/os/bluestore/bluefs_types.h b/ceph/src/os/bluestore/bluefs_types.h index 6a015892d..ddd55def0 100644 --- a/ceph/src/os/bluestore/bluefs_types.h +++ b/ceph/src/os/bluestore/bluefs_types.h @@ -28,7 +28,7 @@ public: }; WRITE_CLASS_DENC(bluefs_extent_t) -ostream& operator<<(ostream& out, bluefs_extent_t e); +ostream& operator<<(ostream& out, const bluefs_extent_t& e); struct bluefs_fnode_t { diff --git a/ceph/src/os/bluestore/bluestore_tool.cc b/ceph/src/os/bluestore/bluestore_tool.cc index 23f19e59e..29863db67 100644 --- a/ceph/src/os/bluestore/bluestore_tool.cc +++ b/ceph/src/os/bluestore/bluestore_tool.cc @@ -31,7 +31,7 @@ int main(int argc, char **argv) vector devs; string path; string action; - bool fsck_deep; + bool fsck_deep = false; po::options_description po_options("Options"); po_options.add_options() ("help,h", "produce help message") diff --git a/ceph/src/os/bluestore/bluestore_types.cc b/ceph/src/os/bluestore/bluestore_types.cc index dcc937a9f..659f3e5bc 100644 --- a/ceph/src/os/bluestore/bluestore_types.cc +++ b/ceph/src/os/bluestore/bluestore_types.cc @@ -196,10 +196,11 @@ void bluestore_extent_ref_map_t::get(uint64_t offset, uint32_t length) void bluestore_extent_ref_map_t::put( uint64_t offset, uint32_t length, - PExtentVector *release) + PExtentVector *release, + bool *maybe_unshared) { //NB: existing entries in 'release' container must be preserved! - + bool unshared = true; auto p = ref_map.lower_bound(offset); if (p == ref_map.end() || p->first > offset) { if (p == ref_map.begin()) { @@ -213,30 +214,42 @@ void bluestore_extent_ref_map_t::put( if (p->first < offset) { uint64_t left = p->first + p->second.length - offset; p->second.length = offset - p->first; + if (p->second.refs != 1) { + unshared = false; + } p = ref_map.insert(map::value_type( offset, record_t(left, p->second.refs))).first; } while (length > 0) { assert(p->first == offset); if (length < p->second.length) { + if (p->second.refs != 1) { + unshared = false; + } ref_map.insert(make_pair(offset + length, record_t(p->second.length - length, p->second.refs))); if (p->second.refs > 1) { p->second.length = length; --p->second.refs; + if (p->second.refs != 1) { + unshared = false; + } _maybe_merge_left(p); } else { if (release) release->push_back(bluestore_pextent_t(p->first, length)); ref_map.erase(p); } - return; + goto out; } offset += p->second.length; length -= p->second.length; if (p->second.refs > 1) { --p->second.refs; + if (p->second.refs != 1) { + unshared = false; + } _maybe_merge_left(p); ++p; } else { @@ -248,6 +261,19 @@ void bluestore_extent_ref_map_t::put( if (p != ref_map.end()) _maybe_merge_left(p); //_check(); +out: + if (maybe_unshared) { + if (unshared) { + // we haven't seen a ref != 1 yet; check the whole map. + for (auto& p : ref_map) { + if (p.second.refs != 1) { + unshared = false; + break; + } + } + } + *maybe_unshared = unshared; + } } bool bluestore_extent_ref_map_t::contains(uint64_t offset, uint32_t length) const @@ -569,9 +595,6 @@ void bluestore_pextent_t::generate_test_instances(list& ls string bluestore_blob_t::get_flags_string(unsigned flags) { string s; - if (flags & FLAG_MUTABLE) { - s = "mutable"; - } if (flags & FLAG_COMPRESSED) { if (s.length()) s += '+'; @@ -758,6 +781,7 @@ void bluestore_blob_t::allocated(uint32_t b_off, uint32_t length, const AllocExt auto start_it = extents.begin(); size_t pos = 0; while(true) { + assert(start_it != extents.end()); if (cur_offs + start_it->length > b_off) { break; } @@ -770,6 +794,7 @@ void bluestore_blob_t::allocated(uint32_t b_off, uint32_t length, const AllocExt auto end_it = start_it; while (true) { + assert(end_it != extents.end()); assert(!end_it->is_valid()); if (cur_offs + end_it->length >= end_off) { break; @@ -995,8 +1020,8 @@ void bluestore_shared_blob_t::generate_test_instances( ostream& operator<<(ostream& out, const bluestore_shared_blob_t& sb) { - out << " sbid 0x" << std::hex << sb.sbid << std::dec; - out << " ref_map(" << sb.ref_map << ")"; + out << "(sbid 0x" << std::hex << sb.sbid << std::dec; + out << " " << sb.ref_map << ")"; return out; } diff --git a/ceph/src/os/bluestore/bluestore_types.h b/ceph/src/os/bluestore/bluestore_types.h index f60b53baf..8e2b77aeb 100644 --- a/ceph/src/os/bluestore/bluestore_types.h +++ b/ceph/src/os/bluestore/bluestore_types.h @@ -161,13 +161,14 @@ WRITE_CLASS_DENC(bluestore_pextent_t) ostream& operator<<(ostream& out, const bluestore_pextent_t& o); -typedef mempool::bluestore_meta_other::vector PExtentVector; +typedef mempool::bluestore_cache_other::vector PExtentVector; template<> struct denc_traits { static constexpr bool supported = true; static constexpr bool bounded = false; static constexpr bool featured = false; + static constexpr bool need_contiguous = true; static void bound_encode(const PExtentVector& v, size_t& p) { p += sizeof(uint32_t); const auto size = v.size(); @@ -208,7 +209,7 @@ struct bluestore_extent_ref_map_t { } }; - typedef mempool::bluestore_meta_other::map map_t; + typedef mempool::bluestore_cache_other::map map_t; map_t ref_map; void _check() const; @@ -222,7 +223,8 @@ struct bluestore_extent_ref_map_t { } void get(uint64_t offset, uint32_t len); - void put(uint64_t offset, uint32_t len, PExtentVector *release); + void put(uint64_t offset, uint32_t len, PExtentVector *release, + bool *maybe_unshared); bool contains(uint64_t offset, uint32_t len) const; bool intersects(uint64_t offset, uint32_t len) const; @@ -406,7 +408,7 @@ struct bluestore_blob_use_tracker_t { /// return false if there are some references to the blob, /// in this case release_units contains pextents /// (identified by their offsets relative to the blob start) - // that are not used any more and can be safely deallocated. + /// that are not used any more and can be safely deallocated. bool put( uint32_t offset, uint32_t len, @@ -469,7 +471,6 @@ struct bluestore_blob_use_tracker_t { static void generate_test_instances(list& o); private: void allocate(); - void fall_back_to_per_au(uint32_t _num_au, uint32_t _au_size); }; WRITE_CLASS_DENC(bluestore_blob_use_tracker_t) ostream& operator<<(ostream& out, const bluestore_blob_use_tracker_t& rm); @@ -478,12 +479,12 @@ ostream& operator<<(ostream& out, const bluestore_blob_use_tracker_t& rm); struct bluestore_blob_t { private: PExtentVector extents; ///< raw data position on device - uint32_t logical_length = 0; ///< < original length of data stored in the blob + uint32_t logical_length = 0; ///< original length of data stored in the blob uint32_t compressed_length = 0; ///< compressed length if any public: enum { - FLAG_MUTABLE = 1, ///< blob can be overwritten or split + LEGACY_FLAG_MUTABLE = 1, ///< [legacy] blob can be overwritten or split FLAG_COMPRESSED = 2, ///< blob is compressed FLAG_CSUM = 4, ///< blob has checksums FLAG_HAS_UNUSED = 8, ///< blob has unused map @@ -595,7 +596,7 @@ public: compressed_length = clen; } bool is_mutable() const { - return has_flag(FLAG_MUTABLE); + return !is_compressed() && !is_shared(); } bool is_compressed() const { return has_flag(FLAG_COMPRESSED); @@ -634,8 +635,10 @@ public: return p->offset + x_off; } - /// return true if the entire range is allocated (mapped to extents on disk) - bool is_allocated(uint64_t b_off, uint64_t b_len) const { + // validate whether or not the status of pextents within the given range + // meets the requirement(allocated or unallocated). + bool _validate_range(uint64_t b_off, uint64_t b_len, + bool require_allocated) const { auto p = extents.begin(); assert(p != extents.end()); while (b_off >= p->length) { @@ -646,11 +649,12 @@ public: b_len += b_off; while (b_len) { assert(p != extents.end()); - if (!p->is_valid()) { - return false; + if (require_allocated != p->is_valid()) { + return false; } + if (p->length >= b_len) { - return true; + return true; } b_len -= p->length; ++p; @@ -658,29 +662,16 @@ public: assert(0 == "we should not get here"); } + /// return true if the entire range is allocated + /// (mapped to extents on disk) + bool is_allocated(uint64_t b_off, uint64_t b_len) const { + return _validate_range(b_off, b_len, true); + } + /// return true if the entire range is unallocated - /// (not mapped to extents on disk) + /// (not mapped to extents on disk) bool is_unallocated(uint64_t b_off, uint64_t b_len) const { - auto p = extents.begin(); - assert(p != extents.end()); - while (b_off >= p->length) { - b_off -= p->length; - ++p; - assert(p != extents.end()); - } - b_len += b_off; - while (b_len) { - assert(p != extents.end()); - if (p->is_valid()) { - return false; - } - if (p->length >= b_len) { - return true; - } - b_len -= p->length; - ++p; - } - assert(0 == "we should not get here"); + return _validate_range(b_off, b_len, false); } /// return true if the logical range has never been used @@ -939,7 +930,7 @@ ostream& operator<<(ostream& out, const bluestore_shared_blob_t& o); struct bluestore_onode_t { uint64_t nid = 0; ///< numeric id (locally unique) uint64_t size = 0; ///< object size - map attrs; ///< attrs + map attrs; ///< attrs struct shard_info { uint32_t offset = 0; ///< logical offset for start of shard diff --git a/ceph/src/os/filestore/FileJournal.h b/ceph/src/os/filestore/FileJournal.h index ff65cdb33..532fe2eae 100644 --- a/ceph/src/os/filestore/FileJournal.h +++ b/ceph/src/os/filestore/FileJournal.h @@ -31,6 +31,9 @@ using std::deque; # include #endif +// re-include our assert to clobber the system one; fix dout: +#include "include/assert.h" + /** * Implements journaling on top of block device or file. * diff --git a/ceph/src/os/filestore/FileStore.cc b/ceph/src/os/filestore/FileStore.cc index d262725f6..1fb483945 100644 --- a/ceph/src/os/filestore/FileStore.cc +++ b/ceph/src/os/filestore/FileStore.cc @@ -107,6 +107,7 @@ using ceph::crypto::SHA1; #define XATTR_SPILL_OUT_NAME "user.cephos.spill_out" #define XATTR_NO_SPILL_OUT "0" #define XATTR_SPILL_OUT "1" +#define __FUNC__ __func__ << "(" << __LINE__ << ")" //Initial features in new superblock. static CompatSet get_fs_initial_compat_set() { @@ -259,7 +260,7 @@ int FileStore::lfn_open(const coll_t& cid, if (!((*index).index)) { r = get_index(cid, index); if (r < 0) { - dout(10) << __func__ << " could not get index r = " << r << dendl; + dout(10) << __FUNC__ << ": could not get index r = " << r << dendl; return r; } } else { @@ -403,8 +404,8 @@ int FileStore::lfn_link(const coll_t& c, const coll_t& newcid, const ghobject_t& if (exist) return -EEXIST; - dout(25) << "lfn_link path_old: " << path_old << dendl; - dout(25) << "lfn_link path_new: " << path_new << dendl; + dout(25) << __FUNC__ << ": path_old: " << path_old << dendl; + dout(25) << __FUNC__ << ": path_new: " << path_new << dendl; r = ::link(path_old->path(), path_new->path()); if (r < 0) return -errno; @@ -433,8 +434,8 @@ int FileStore::lfn_link(const coll_t& c, const coll_t& newcid, const ghobject_t& if (exist) return -EEXIST; - dout(25) << "lfn_link path_old: " << path_old << dendl; - dout(25) << "lfn_link path_new: " << path_new << dendl; + dout(25) << __FUNC__ << ": path_old: " << path_old << dendl; + dout(25) << __FUNC__ << ": path_new: " << path_new << dendl; r = ::link(path_old->path(), path_new->path()); if (r < 0) return -errno; @@ -458,7 +459,7 @@ int FileStore::lfn_unlink(const coll_t& cid, const ghobject_t& o, Index index; int r = get_index(cid, &index); if (r < 0) { - dout(25) << __func__ << " get_index failed " << cpp_strerror(r) << dendl; + dout(25) << __FUNC__ << ": get_index failed " << cpp_strerror(r) << dendl; return r; } @@ -480,11 +481,11 @@ int FileStore::lfn_unlink(const coll_t& cid, const ghobject_t& o, } } if (force_clear_omap) { - dout(20) << __func__ << ": clearing omap on " << o + dout(20) << __FUNC__ << ": clearing omap on " << o << " in cid " << cid << dendl; r = object_map->clear(o, &spos); if (r < 0 && r != -ENOENT) { - dout(25) << __func__ << " omap clear failed " << cpp_strerror(r) << dendl; + dout(25) << __FUNC__ << ": omap clear failed " << cpp_strerror(r) << dendl; assert(!m_filestore_fail_eio || r != -EIO); return r; } @@ -511,7 +512,7 @@ int FileStore::lfn_unlink(const coll_t& cid, const ghobject_t& o, } r = index->unlink(o); if (r < 0) { - dout(25) << __func__ << " index unlink failed " << cpp_strerror(r) << dendl; + dout(25) << __FUNC__ << ": index unlink failed " << cpp_strerror(r) << dendl; return r; } return 0; @@ -574,7 +575,7 @@ FileStore::FileStore(CephContext* cct, const std::string &base, m_filestore_max_inline_xattrs(0), m_filestore_max_xattr_value_size(0) { - m_filestore_kill_at.set(cct->_conf->filestore_kill_at); + m_filestore_kill_at = cct->_conf->filestore_kill_at; for (int i = 0; i < m_ondisk_finisher_num; ++i) { ostringstream oss; oss << "filestore-ondisk-" << i; @@ -849,37 +850,37 @@ int FileStore::mkfs() ret = ::ftruncate(fsid_fd, 0); if (ret < 0) { ret = -errno; - derr << "mkfs: failed to truncate fsid: " + derr << __FUNC__ << ": failed to truncate fsid: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } ret = safe_write(fsid_fd, fsid_str, strlen(fsid_str)); if (ret < 0) { - derr << "mkfs: failed to write fsid: " + derr << __FUNC__ << ": failed to write fsid: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } if (::fsync(fsid_fd) < 0) { ret = -errno; - derr << "mkfs: close failed: can't write fsid: " + derr << __FUNC__ << ": close failed: can't write fsid: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } dout(10) << "mkfs fsid is " << fsid << dendl; } else { if (!fsid.is_zero() && fsid != old_fsid) { - derr << "mkfs on-disk fsid " << old_fsid << " != provided " << fsid << dendl; + derr << __FUNC__ << ": on-disk fsid " << old_fsid << " != provided " << fsid << dendl; ret = -EINVAL; goto close_fsid_fd; } fsid = old_fsid; - dout(1) << "mkfs fsid is already set to " << fsid << dendl; + dout(1) << __FUNC__ << ": fsid is already set to " << fsid << dendl; } // version stamp ret = write_version_stamp(); if (ret < 0) { - derr << "mkfs: write_version_stamp() failed: " + derr << __FUNC__ << ": write_version_stamp() failed: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -888,7 +889,7 @@ int FileStore::mkfs() superblock.omap_backend = cct->_conf->filestore_omap_backend; ret = write_superblock(); if (ret < 0) { - derr << "mkfs: write_superblock() failed: " + derr << __FUNC__ << ": write_superblock() failed: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -897,7 +898,7 @@ int FileStore::mkfs() ret = ::fstatfs(basedir_fd, &basefs); if (ret < 0) { ret = -errno; - derr << "mkfs cannot fstatfs basedir " + derr << __FUNC__ << ": cannot fstatfs basedir " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -906,7 +907,7 @@ int FileStore::mkfs() ret = backend->create_current(); if (ret < 0) { - derr << "mkfs: failed to create current/ " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": failed to create current/ " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -916,7 +917,7 @@ int FileStore::mkfs() int fd = read_op_seq(&initial_seq); if (fd < 0) { ret = fd; - derr << "mkfs: failed to create " << current_op_seq_fn << ": " + derr << __FUNC__ << ": failed to create " << current_op_seq_fn << ": " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -924,7 +925,7 @@ int FileStore::mkfs() ret = write_op_seq(fd, 1); if (ret < 0) { VOID_TEMP_FAILURE_RETRY(::close(fd)); - derr << "mkfs: failed to write to " << current_op_seq_fn << ": " + derr << __FUNC__ << ": failed to write to " << current_op_seq_fn << ": " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -939,7 +940,7 @@ int FileStore::mkfs() VOID_TEMP_FAILURE_RETRY(::close(current_fd)); if (ret < 0 && ret != -EEXIST) { VOID_TEMP_FAILURE_RETRY(::close(fd)); - derr << "mkfs: failed to create snap_1: " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": failed to create snap_1: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } } @@ -948,7 +949,7 @@ int FileStore::mkfs() } ret = KeyValueDB::test_init(superblock.omap_backend, omap_dir); if (ret < 0) { - derr << "mkfs failed to create " << cct->_conf->filestore_omap_backend << dendl; + derr << __FUNC__ << ": failed to create " << cct->_conf->filestore_omap_backend << dendl; goto close_fsid_fd; } // create fsid under omap @@ -959,7 +960,7 @@ int FileStore::mkfs() omap_fsid_fd = ::open(omap_fsid_fn, O_RDWR|O_CREAT, 0644); if (omap_fsid_fd < 0) { ret = -errno; - derr << "mkfs: failed to open " << omap_fsid_fn << ": " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": failed to open " << omap_fsid_fn << ": " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } @@ -970,34 +971,34 @@ int FileStore::mkfs() ret = ::ftruncate(omap_fsid_fd, 0); if (ret < 0) { ret = -errno; - derr << "mkfs: failed to truncate fsid: " + derr << __FUNC__ << ": failed to truncate fsid: " << cpp_strerror(ret) << dendl; goto close_omap_fsid_fd; } ret = safe_write(omap_fsid_fd, fsid_str, strlen(fsid_str)); if (ret < 0) { - derr << "mkfs: failed to write fsid: " + derr << __FUNC__ << ": failed to write fsid: " << cpp_strerror(ret) << dendl; goto close_omap_fsid_fd; } - dout(10) << "mkfs: write success, fsid:" << fsid_str << ", ret:" << ret << dendl; + dout(10) << __FUNC__ << ": write success, fsid:" << fsid_str << ", ret:" << ret << dendl; if (::fsync(omap_fsid_fd) < 0) { ret = -errno; - derr << "mkfs: close failed: can't write fsid: " + derr << __FUNC__ << ": close failed: can't write fsid: " << cpp_strerror(ret) << dendl; goto close_omap_fsid_fd; } dout(10) << "mkfs omap fsid is " << fsid << dendl; } else { if (fsid != old_omap_fsid) { - derr << "FileStore::mkfs: " << omap_fsid_fn + derr << __FUNC__ << ": " << omap_fsid_fn << " has existed omap fsid " << old_omap_fsid << " != expected osd fsid " << fsid << dendl; ret = -EINVAL; goto close_omap_fsid_fd; } - dout(1) << "FileStore::mkfs: omap fsid is already set to " << fsid << dendl; + dout(1) << __FUNC__ << ": omap fsid is already set to " << fsid << dendl; } dout(1) << cct->_conf->filestore_omap_backend << " db exists/created" << dendl; @@ -1035,12 +1036,12 @@ int FileStore::mkjournal() int fd = ::open(fn, O_RDONLY, 0644); if (fd < 0) { int err = errno; - derr << "FileStore::mkjournal: open error: " << cpp_strerror(err) << dendl; + derr << __FUNC__ << ": open error: " << cpp_strerror(err) << dendl; return -err; } ret = read_fsid(fd, &fsid); if (ret < 0) { - derr << "FileStore::mkjournal: read error: " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": read error: " << cpp_strerror(ret) << dendl; VOID_TEMP_FAILURE_RETRY(::close(fd)); return ret; } @@ -1054,10 +1055,10 @@ int FileStore::mkjournal() if (ret < 0) { ret = journal->create(); if (ret) - derr << "mkjournal error creating journal on " << journalpath + derr << __FUNC__ << ": error creating journal on " << journalpath << ": " << cpp_strerror(ret) << dendl; else - dout(0) << "mkjournal created journal on " << journalpath << dendl; + dout(0) << __FUNC__ << ": created journal on " << journalpath << dendl; } delete journal; journal = 0; @@ -1099,7 +1100,7 @@ int FileStore::lock_fsid() int r = ::fcntl(fsid_fd, F_SETLK, &l); if (r < 0) { int err = errno; - dout(0) << "lock_fsid failed to lock " << basedir << "/fsid, is another ceph-osd still running? " + dout(0) << __FUNC__ << ": failed to lock " << basedir << "/fsid, is another ceph-osd still running? " << cpp_strerror(err) << dendl; return -err; } @@ -1108,7 +1109,7 @@ int FileStore::lock_fsid() bool FileStore::test_mount_in_use() { - dout(5) << "test_mount basedir " << basedir << " journal " << journalpath << dendl; + dout(5) << __FUNC__ << ": basedir " << basedir << " journal " << journalpath << dendl; char fn[PATH_MAX]; snprintf(fn, sizeof(fn), "%s/fsid", basedir.c_str()); @@ -1123,6 +1124,30 @@ bool FileStore::test_mount_in_use() return inuse; } +bool FileStore::is_rotational() +{ + bool rotational; + if (backend) { + rotational = backend->is_rotational(); + } else { + int fd = ::open(basedir.c_str(), O_RDONLY); + if (fd < 0) + return true; + struct statfs st; + int r = ::fstatfs(fd, &st); + ::close(fd); + if (r < 0) { + return true; + } + create_backend(st.f_type); + rotational = backend->is_rotational(); + delete backend; + backend = NULL; + } + dout(10) << __func__ << " " << (int)rotational << dendl; + return rotational; +} + int FileStore::_detect_fs() { struct statfs st; @@ -1136,7 +1161,7 @@ int FileStore::_detect_fs() r = backend->detect_features(); if (r < 0) { - derr << "_detect_fs: detect_features error: " << cpp_strerror(r) << dendl; + derr << __FUNC__ << ": detect_features error: " << cpp_strerror(r) << dendl; return r; } @@ -1148,7 +1173,7 @@ int FileStore::_detect_fs() int tmpfd = ::open(fn, O_CREAT|O_WRONLY|O_TRUNC, 0700); if (tmpfd < 0) { int ret = -errno; - derr << "_detect_fs unable to create " << fn << ": " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": unable to create " << fn << ": " << cpp_strerror(ret) << dendl; return ret; } @@ -1276,7 +1301,7 @@ int FileStore::version_stamp_is_valid(uint32_t *version) bl.push_back(std::move(bp)); bufferlist::iterator i = bl.begin(); ::decode(*version, i); - dout(10) << __func__ << " was " << *version << " vs target " + dout(10) << __FUNC__ << ": was " << *version << " vs target " << target_version << dendl; if (*version == target_version) return 1; @@ -1286,7 +1311,7 @@ int FileStore::version_stamp_is_valid(uint32_t *version) int FileStore::write_version_stamp() { - dout(1) << __func__ << " " << target_version << dendl; + dout(1) << __FUNC__ << ": " << target_version << dendl; bufferlist bl; ::encode(target_version, bl); @@ -1296,7 +1321,7 @@ int FileStore::write_version_stamp() int FileStore::upgrade() { - dout(1) << "upgrade" << dendl; + dout(1) << __FUNC__ << dendl; uint32_t version; int r = version_stamp_is_valid(&version); @@ -1332,7 +1357,7 @@ int FileStore::read_op_seq(uint64_t *seq) memset(s, 0, sizeof(s)); int ret = safe_read(op_fd, s, sizeof(s) - 1); if (ret < 0) { - derr << "error reading " << current_op_seq_fn << ": " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": error reading " << current_op_seq_fn << ": " << cpp_strerror(ret) << dendl; VOID_TEMP_FAILURE_RETRY(::close(op_fd)); assert(!m_filestore_fail_eio || ret != -EIO); return ret; @@ -1371,7 +1396,7 @@ int FileStore::mount() // make sure global base dir exists if (::access(basedir.c_str(), R_OK | W_OK)) { ret = -errno; - derr << "FileStore::mount: unable to access basedir '" << basedir << "': " + derr << __FUNC__ << ": unable to access basedir '" << basedir << "': " << cpp_strerror(ret) << dendl; goto done; } @@ -1381,20 +1406,20 @@ int FileStore::mount() fsid_fd = ::open(buf, O_RDWR, 0644); if (fsid_fd < 0) { ret = -errno; - derr << "FileStore::mount: error opening '" << buf << "': " + derr << __FUNC__ << ": error opening '" << buf << "': " << cpp_strerror(ret) << dendl; goto done; } ret = read_fsid(fsid_fd, &fsid); if (ret < 0) { - derr << "FileStore::mount: error reading fsid_fd: " << cpp_strerror(ret) + derr << __FUNC__ << ": error reading fsid_fd: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } if (lock_fsid() < 0) { - derr << "FileStore::mount: lock_fsid failed" << dendl; + derr << __FUNC__ << ": lock_fsid failed" << dendl; ret = -EBUSY; goto close_fsid_fd; } @@ -1405,12 +1430,12 @@ int FileStore::mount() uint32_t version_stamp; ret = version_stamp_is_valid(&version_stamp); if (ret < 0) { - derr << "FileStore::mount: error in version_stamp_is_valid: " + derr << __FUNC__ << ": error in version_stamp_is_valid: " << cpp_strerror(ret) << dendl; goto close_fsid_fd; } else if (ret == 0) { if (do_update || (int)version_stamp < cct->_conf->filestore_update_to) { - derr << "FileStore::mount: stale version stamp detected: " + derr << __FUNC__ << ": stale version stamp detected: " << version_stamp << ". Proceeding, do_update " << "is set, performing disk format upgrade." @@ -1418,7 +1443,7 @@ int FileStore::mount() do_update = true; } else { ret = -EINVAL; - derr << "FileStore::mount: stale version stamp " << version_stamp + derr << __FUNC__ << ": stale version stamp " << version_stamp << ". Please run the FileStore update script before starting the " << "OSD, or set filestore_update_to to " << target_version << " (currently " << cct->_conf->filestore_update_to << ")" @@ -1434,7 +1459,7 @@ int FileStore::mount() // Check if this FileStore supports all the necessary features to mount if (supported_compat_set.compare(superblock.compat_features) == -1) { - derr << "FileStore::mount: Incompatible features set " + derr << __FUNC__ << ": Incompatible features set " << superblock.compat_features << dendl; ret = -EINVAL; goto close_fsid_fd; @@ -1444,7 +1469,7 @@ int FileStore::mount() basedir_fd = ::open(basedir.c_str(), O_RDONLY); if (basedir_fd < 0) { ret = -errno; - derr << "FileStore::mount: failed to open " << basedir << ": " + derr << __FUNC__ << ": failed to open " << basedir << ": " << cpp_strerror(ret) << dendl; basedir_fd = -1; goto close_fsid_fd; @@ -1453,7 +1478,7 @@ int FileStore::mount() // test for btrfs, xattrs, etc. ret = _detect_fs(); if (ret < 0) { - derr << "FileStore::mount: error in _detect_fs: " + derr << __FUNC__ << ": error in _detect_fs: " << cpp_strerror(ret) << dendl; goto close_basedir_fd; } @@ -1462,7 +1487,7 @@ int FileStore::mount() list ls; ret = backend->list_checkpoints(ls); if (ret < 0) { - derr << "FileStore::mount: error in _list_snaps: "<< cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": error in _list_snaps: "<< cpp_strerror(ret) << dendl; goto close_basedir_fd; } @@ -1490,7 +1515,7 @@ int FileStore::mount() if (backend->can_checkpoint()) { if (snaps.empty()) { - dout(0) << "mount WARNING: no consistent snaps found, store may be in inconsistent state" << dendl; + dout(0) << __FUNC__ << ": WARNING: no consistent snaps found, store may be in inconsistent state" << dendl; } else { char s[NAME_MAX]; uint64_t curr_seq = 0; @@ -1536,14 +1561,14 @@ int FileStore::mount() << TEXT_NORMAL << std::endl; } - dout(10) << "mount rolling back to consistent snap " << cp << dendl; + dout(10) << __FUNC__ << ": rolling back to consistent snap " << cp << dendl; snprintf(s, sizeof(s), COMMIT_SNAP_ITEM, (long long unsigned)cp); } // drop current? ret = backend->rollback_to(s); if (ret) { - derr << "FileStore::mount: error rolling back to " << s << ": " + derr << __FUNC__ << ": error rolling back to " << s << ": " << cpp_strerror(ret) << dendl; goto close_basedir_fd; } @@ -1554,7 +1579,7 @@ int FileStore::mount() current_fd = ::open(current_fn.c_str(), O_RDONLY); if (current_fd < 0) { ret = -errno; - derr << "FileStore::mount: error opening: " << current_fn << ": " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": error opening: " << current_fn << ": " << cpp_strerror(ret) << dendl; goto close_basedir_fd; } @@ -1563,7 +1588,7 @@ int FileStore::mount() op_fd = read_op_seq(&initial_op_seq); if (op_fd < 0) { ret = op_fd; - derr << "FileStore::mount: read_op_seq failed" << dendl; + derr << __FUNC__ << ": read_op_seq failed" << dendl; goto close_current_fd; } @@ -1580,7 +1605,7 @@ int FileStore::mount() int r = ::creat(nosnapfn, 0644); if (r < 0) { ret = -errno; - derr << "FileStore::mount: failed to create current/nosnap" << dendl; + derr << __FUNC__ << ": failed to create current/nosnap" << dendl; goto close_current_fd; } VOID_TEMP_FAILURE_RETRY(::close(r)); @@ -1597,7 +1622,7 @@ int FileStore::mount() snprintf(omap_fsid_buf, sizeof(omap_fsid_buf), "%s/osd_uuid", omap_dir.c_str()); // if osd_uuid not exists, assume as this omap matchs corresponding osd if (::stat(omap_fsid_buf, &omap_fsid_stat) != 0){ - dout(10) << "Filestore::mount osd_uuid not found under omap, " + dout(10) << __FUNC__ << ": osd_uuid not found under omap, " << "assume as matched." << dendl; }else{ @@ -1605,7 +1630,7 @@ int FileStore::mount() omap_fsid_fd = ::open(omap_fsid_buf, O_RDONLY, 0644); if (omap_fsid_fd < 0) { ret = -errno; - derr << "FileStore::mount: error opening '" << omap_fsid_buf << "': " + derr << __FUNC__ << ": error opening '" << omap_fsid_buf << "': " << cpp_strerror(ret) << dendl; goto close_current_fd; @@ -1614,14 +1639,14 @@ int FileStore::mount() VOID_TEMP_FAILURE_RETRY(::close(omap_fsid_fd)); omap_fsid_fd = -1; // defensive if (ret < 0) { - derr << "FileStore::mount: error reading omap_fsid_fd" + derr << __FUNC__ << ": error reading omap_fsid_fd" << ", omap_fsid = " << omap_fsid << cpp_strerror(ret) << dendl; goto close_current_fd; } if (fsid != omap_fsid) { - derr << "FileStore::mount: " << omap_fsid_buf + derr << __FUNC__ << ": " << omap_fsid_buf << " has existed omap fsid " << omap_fsid << " != expected osd fsid " << fsid << dendl; @@ -1637,7 +1662,7 @@ int FileStore::mount() omap_dir); if (omap_store == NULL) { - derr << "Error creating " << superblock.omap_backend << dendl; + derr << __FUNC__ << ": Error creating " << superblock.omap_backend << dendl; ret = -1; goto close_current_fd; } @@ -1648,14 +1673,14 @@ int FileStore::mount() ret = omap_store->init(); if (ret < 0) { - derr << "Error initializing omap_store: " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": Error initializing omap_store: " << cpp_strerror(ret) << dendl; goto close_current_fd; } stringstream err; if (omap_store->create_and_open(err)) { delete omap_store; - derr << "Error initializing " << superblock.omap_backend + derr << __FUNC__ << ": Error initializing " << superblock.omap_backend << " : " << err.str() << dendl; ret = -1; goto close_current_fd; @@ -1665,7 +1690,7 @@ int FileStore::mount() ret = dbomap->init(do_update); if (ret < 0) { delete dbomap; - derr << "Error initializing DBObjectMap: " << ret << dendl; + derr << __FUNC__ << ": Error initializing DBObjectMap: " << ret << dendl; goto close_current_fd; } stringstream err2; @@ -1689,28 +1714,28 @@ int FileStore::mount() !m_filestore_journal_trailing) { if (!backend->can_checkpoint()) { m_filestore_journal_writeahead = true; - dout(0) << "mount: enabling WRITEAHEAD journal mode: checkpoint is not enabled" << dendl; + dout(0) << __FUNC__ << ": enabling WRITEAHEAD journal mode: checkpoint is not enabled" << dendl; } else { m_filestore_journal_parallel = true; - dout(0) << "mount: enabling PARALLEL journal mode: fs, checkpoint is enabled" << dendl; + dout(0) << __FUNC__ << ": enabling PARALLEL journal mode: fs, checkpoint is enabled" << dendl; } } else { if (m_filestore_journal_writeahead) - dout(0) << "mount: WRITEAHEAD journal mode explicitly enabled in conf" << dendl; + dout(0) << __FUNC__ << ": WRITEAHEAD journal mode explicitly enabled in conf" << dendl; if (m_filestore_journal_parallel) - dout(0) << "mount: PARALLEL journal mode explicitly enabled in conf" << dendl; + dout(0) << __FUNC__ << ": PARALLEL journal mode explicitly enabled in conf" << dendl; if (m_filestore_journal_trailing) - dout(0) << "mount: TRAILING journal mode explicitly enabled in conf" << dendl; + dout(0) << __FUNC__ << ": TRAILING journal mode explicitly enabled in conf" << dendl; } if (m_filestore_journal_writeahead) journal->set_wait_on_full(true); } else { - dout(0) << "mount: no journal" << dendl; + dout(0) << __FUNC__ << ": no journal" << dendl; } ret = _sanity_check_fs(); if (ret) { - derr << "FileStore::mount: _sanity_check_fs failed with error " + derr << __FUNC__ << ": _sanity_check_fs failed with error " << ret << dendl; goto close_current_fd; } @@ -1742,9 +1767,9 @@ int FileStore::mount() if (!m_disable_wbthrottle) { wbthrottle.start(); } else { - dout(0) << "mount INFO: WbThrottle is disabled" << dendl; + dout(0) << __FUNC__ << ": INFO: WbThrottle is disabled" << dendl; if (cct->_conf->filestore_odsync_write) { - dout(0) << "mount INFO: O_DSYNC write is enabled" << dendl; + dout(0) << __FUNC__ << ": INFO: O_DSYNC write is enabled" << dendl; } } sync_thread.create("filestore_sync"); @@ -1752,7 +1777,7 @@ int FileStore::mount() if (!(generic_flags & SKIP_JOURNAL_REPLAY)) { ret = journal_replay(initial_op_seq); if (ret < 0) { - derr << "mount failed to open journal " << journalpath << ": " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": failed to open journal " << journalpath << ": " << cpp_strerror(ret) << dendl; if (ret == -ENOTTY) { derr << "maybe journal is not pointing to a block device and its size " << "wasn't configured?" << dendl; @@ -1827,7 +1852,7 @@ done: void FileStore::init_temp_collections() { - dout(10) << __func__ << dendl; + dout(10) << __FUNC__ << dendl; vector ls; int r = list_collections(ls, true); assert(r >= 0); @@ -1851,14 +1876,14 @@ void FileStore::init_temp_collections() if (temps.count(temp)) { temps.erase(temp); } else { - dout(10) << __func__ << " creating " << temp << dendl; + dout(10) << __FUNC__ << ": creating " << temp << dendl; r = _create_collection(temp, 0, spos); assert(r == 0); } } for (set::iterator p = temps.begin(); p != temps.end(); ++p) { - dout(10) << __func__ << " removing stray " << *p << dendl; + dout(10) << __FUNC__ << ": removing stray " << *p << dendl; r = _collection_remove_recursive(*p, spos); assert(r == 0); } @@ -1866,7 +1891,7 @@ void FileStore::init_temp_collections() int FileStore::umount() { - dout(5) << "umount " << basedir << dendl; + dout(5) << __FUNC__ << ": " << basedir << dendl; flush(); sync(); @@ -1969,7 +1994,7 @@ void FileStore::queue_op(OpSequencer *osr, Op *o) logger->inc(l_filestore_ops); logger->inc(l_filestore_bytes, o->bytes); - dout(5) << "queue_op " << o << " seq " << o->op + dout(5) << __FUNC__ << ": " << o << " seq " << o->op << " " << *osr << " " << o->bytes << " bytes" << " (queue has " << throttle_ops.get_current() << " ops and " << throttle_bytes.get_current() << " bytes)" @@ -2002,22 +2027,22 @@ void FileStore::_do_op(OpSequencer *osr, ThreadPool::TPHandle &handle) // inject a stall? if (cct->_conf->filestore_inject_stall) { int orig = cct->_conf->filestore_inject_stall; - dout(5) << "_do_op filestore_inject_stall " << orig << ", sleeping" << dendl; + dout(5) << __FUNC__ << ": filestore_inject_stall " << orig << ", sleeping" << dendl; sleep(orig); cct->_conf->set_val("filestore_inject_stall", "0"); - dout(5) << "_do_op done stalling" << dendl; + dout(5) << __FUNC__ << ": done stalling" << dendl; } osr->apply_lock.Lock(); Op *o = osr->peek_queue(); o->trace.event("op_apply_start"); apply_manager.op_apply_start(o->op); - dout(5) << "_do_op " << o << " seq " << o->op << " " << *osr << "/" << osr->parent << " start" << dendl; + dout(5) << __FUNC__ << ": " << o << " seq " << o->op << " " << *osr << "/" << osr->parent << " start" << dendl; o->trace.event("_do_transactions start"); int r = _do_transactions(o->tls, o->op, &handle); o->trace.event("op_apply_finish"); apply_manager.op_apply_finish(o->op); - dout(10) << "_do_op " << o << " seq " << o->op << " r = " << r + dout(10) << __FUNC__ << ": " << o << " seq " << o->op << " r = " << r << ", finisher " << o->onreadable << " " << o->onreadable_sync << dendl; o->tls.clear(); @@ -2032,7 +2057,7 @@ void FileStore::_finish_op(OpSequencer *osr) utime_t lat = ceph_clock_now(); lat -= o->start; - dout(10) << "_finish_op " << o << " seq " << o->op << " " << *osr << "/" << osr->parent << " lat " << lat << dendl; + dout(10) << __FUNC__ << ": " << o << " seq " << o->op << " " << *osr << "/" << osr->parent << " lat " << lat << dendl; osr->apply_lock.Unlock(); // locked in _do_op o->trace.event("_finish_op"); @@ -2078,7 +2103,7 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, tls, &onreadable, &ondisk, &onreadable_sync); if (cct->_conf->objectstore_blackhole) { - dout(0) << __func__ << " objectstore_blackhole = TRUE, dropping transaction" + dout(0) << __FUNC__ << ": objectstore_blackhole = TRUE, dropping transaction" << dendl; delete ondisk; delete onreadable; @@ -2092,13 +2117,13 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, assert(posr); if (posr->p) { osr = static_cast(posr->p.get()); - dout(5) << "queue_transactions existing " << osr << " " << *osr << dendl; + dout(5) << __FUNC__ << ": existing " << osr << " " << *osr << dendl; } else { - osr = new OpSequencer(cct, next_osr_id.inc()); + osr = new OpSequencer(cct, ++next_osr_id); osr->set_cct(cct); osr->parent = posr; posr->p = osr; - dout(5) << "queue_transactions new " << osr << " " << *osr << dendl; + dout(5) << __FUNC__ << ": new " << osr << " " << *osr << dendl; } // used to include osr information in tracepoints during transaction apply @@ -2136,7 +2161,7 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, dump_transactions(o->tls, o->op, osr); if (m_filestore_journal_parallel) { - dout(5) << "queue_transactions (parallel) " << o->op << " " << o->tls << dendl; + dout(5) << __FUNC__ << ": (parallel) " << o->op << " " << o->tls << dendl; trace.keyval("journal mode", "parallel"); trace.event("journal started"); @@ -2146,7 +2171,7 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, queue_op(osr, o); trace.event("op queued"); } else if (m_filestore_journal_writeahead) { - dout(5) << "queue_transactions (writeahead) " << o->op << " " << o->tls << dendl; + dout(5) << __FUNC__ << ": (writeahead) " << o->op << " " << o->tls << dendl; osr->queue_journal(o->op); @@ -2166,7 +2191,7 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, if (!journal) { Op *o = build_op(tls, onreadable, onreadable_sync, osd_op); - dout(5) << __func__ << " (no journal) " << o << " " << tls << dendl; + dout(5) << __FUNC__ << ": (no journal) " << o << " " << tls << dendl; if (handle) handle->suspend_tp_timeout(); @@ -2203,7 +2228,7 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, orig_len = journal->prepare_entry(tls, &tbl); } uint64_t op = submit_manager.op_submit_start(); - dout(5) << "queue_transactions (trailing journal) " << op << " " << tls << dendl; + dout(5) << __FUNC__ << ": (trailing journal) " << op << " " << tls << dendl; if (m_filestore_do_dump) dump_transactions(tls, op, osr); @@ -2240,7 +2265,7 @@ int FileStore::queue_transactions(Sequencer *posr, vector& tls, void FileStore::_journaled_ahead(OpSequencer *osr, Op *o, Context *ondisk) { - dout(5) << "_journaled_ahead " << o << " seq " << o->op << " " << *osr << " " << o->tls << dendl; + dout(5) << __FUNC__ << ": " << o << " seq " << o->op << " " << *osr << " " << o->tls << dendl; o->trace.event("writeahead journal finished"); @@ -2288,12 +2313,12 @@ void FileStore::_set_global_replay_guard(const coll_t& cid, // sync all previous operations on this sequencer int ret = object_map->sync(); if (ret < 0) { - derr << __func__ << " : omap sync error " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": omap sync error " << cpp_strerror(ret) << dendl; assert(0 == "_set_global_replay_guard failed"); } ret = sync_filesystem(basedir_fd); if (ret < 0) { - derr << __func__ << " : sync_filesystem error " << cpp_strerror(ret) << dendl; + derr << __FUNC__ << ": sync_filesystem error " << cpp_strerror(ret) << dendl; assert(0 == "_set_global_replay_guard failed"); } @@ -2302,7 +2327,7 @@ void FileStore::_set_global_replay_guard(const coll_t& cid, int fd = ::open(fn, O_RDONLY); if (fd < 0) { int err = errno; - derr << __func__ << ": " << cid << " error " << cpp_strerror(err) << dendl; + derr << __FUNC__ << ": " << cid << " error " << cpp_strerror(err) << dendl; assert(0 == "_set_global_replay_guard failed"); } @@ -2314,7 +2339,7 @@ void FileStore::_set_global_replay_guard(const coll_t& cid, int r = chain_fsetxattr( fd, GLOBAL_REPLAY_GUARD_XATTR, v.c_str(), v.length()); if (r < 0) { - derr << __func__ << ": fsetxattr " << GLOBAL_REPLAY_GUARD_XATTR + derr << __FUNC__ << ": fsetxattr " << GLOBAL_REPLAY_GUARD_XATTR << " got " << cpp_strerror(r) << dendl; assert(0 == "fsetxattr failed"); } @@ -2325,7 +2350,7 @@ void FileStore::_set_global_replay_guard(const coll_t& cid, _inject_failure(); VOID_TEMP_FAILURE_RETRY(::close(fd)); - dout(10) << __func__ << ": " << spos << " done" << dendl; + dout(10) << __FUNC__ << ": " << spos << " done" << dendl; } int FileStore::_check_global_replay_guard(const coll_t& cid, @@ -2335,14 +2360,14 @@ int FileStore::_check_global_replay_guard(const coll_t& cid, get_cdir(cid, fn, sizeof(fn)); int fd = ::open(fn, O_RDONLY); if (fd < 0) { - dout(10) << __func__ << ": " << cid << " dne" << dendl; + dout(10) << __FUNC__ << ": " << cid << " dne" << dendl; return 1; // if collection does not exist, there is no guard, and we can replay. } char buf[100]; int r = chain_fgetxattr(fd, GLOBAL_REPLAY_GUARD_XATTR, buf, sizeof(buf)); if (r < 0) { - dout(20) << __func__ << " no xattr" << dendl; + dout(20) << __FUNC__ << ": no xattr" << dendl; assert(!m_filestore_fail_eio || r != -EIO); VOID_TEMP_FAILURE_RETRY(::close(fd)); return 1; // no xattr @@ -2368,7 +2393,7 @@ void FileStore::_set_replay_guard(const coll_t& cid, int fd = ::open(fn, O_RDONLY); if (fd < 0) { int err = errno; - derr << "_set_replay_guard " << cid << " error " << cpp_strerror(err) << dendl; + derr << __FUNC__ << ": " << cid << " error " << cpp_strerror(err) << dendl; assert(0 == "_set_replay_guard failed"); } _set_replay_guard(fd, spos, 0, in_progress); @@ -2384,7 +2409,7 @@ void FileStore::_set_replay_guard(int fd, if (backend->can_checkpoint()) return; - dout(10) << "_set_replay_guard " << spos << (in_progress ? " START" : "") << dendl; + dout(10) << __FUNC__ << ": " << spos << (in_progress ? " START" : "") << dendl; _inject_failure(); @@ -2416,7 +2441,7 @@ void FileStore::_set_replay_guard(int fd, _inject_failure(); - dout(10) << "_set_replay_guard " << spos << " done" << dendl; + dout(10) << __FUNC__ << ": " << spos << " done" << dendl; } void FileStore::_close_replay_guard(const coll_t& cid, @@ -2427,7 +2452,7 @@ void FileStore::_close_replay_guard(const coll_t& cid, int fd = ::open(fn, O_RDONLY); if (fd < 0) { int err = errno; - derr << "_close_replay_guard " << cid << " error " << cpp_strerror(err) << dendl; + derr << __FUNC__ << ": " << cid << " error " << cpp_strerror(err) << dendl; assert(0 == "_close_replay_guard failed"); } _close_replay_guard(fd, spos); @@ -2440,7 +2465,7 @@ void FileStore::_close_replay_guard(int fd, const SequencerPosition& spos, if (backend->can_checkpoint()) return; - dout(10) << "_close_replay_guard " << spos << dendl; + dout(10) << __FUNC__ << ": " << spos << dendl; _inject_failure(); @@ -2466,7 +2491,7 @@ void FileStore::_close_replay_guard(int fd, const SequencerPosition& spos, _inject_failure(); - dout(10) << "_close_replay_guard " << spos << " done" << dendl; + dout(10) << __FUNC__ << ": " << spos << " done" << dendl; } int FileStore::_check_replay_guard(const coll_t& cid, const ghobject_t &oid, @@ -2482,7 +2507,7 @@ int FileStore::_check_replay_guard(const coll_t& cid, const ghobject_t &oid, FDRef fd; r = lfn_open(cid, oid, false, &fd); if (r < 0) { - dout(10) << "_check_replay_guard " << cid << " " << oid << " dne" << dendl; + dout(10) << __FUNC__ << ": " << cid << " " << oid << " dne" << dendl; return 1; // if file does not exist, there is no guard, and we can replay. } int ret = _check_replay_guard(**fd, spos); @@ -2499,7 +2524,7 @@ int FileStore::_check_replay_guard(const coll_t& cid, const SequencerPosition& s get_cdir(cid, fn, sizeof(fn)); int fd = ::open(fn, O_RDONLY); if (fd < 0) { - dout(10) << "_check_replay_guard " << cid << " dne" << dendl; + dout(10) << __FUNC__ << ": " << cid << " dne" << dendl; return 1; // if collection does not exist, there is no guard, and we can replay. } int ret = _check_replay_guard(fd, spos); @@ -2515,7 +2540,7 @@ int FileStore::_check_replay_guard(int fd, const SequencerPosition& spos) char buf[100]; int r = chain_fgetxattr(fd, REPLAY_GUARD_XATTR, buf, sizeof(buf)); if (r < 0) { - dout(20) << "_check_replay_guard no xattr" << dendl; + dout(20) << __FUNC__ << ": no xattr" << dendl; assert(!m_filestore_fail_eio || r != -EIO); return 1; // no xattr } @@ -2529,21 +2554,21 @@ int FileStore::_check_replay_guard(int fd, const SequencerPosition& spos) if (!p.end()) // older journals don't have this ::decode(in_progress, p); if (opos > spos) { - dout(10) << "_check_replay_guard object has " << opos << " > current pos " << spos + dout(10) << __FUNC__ << ": object has " << opos << " > current pos " << spos << ", now or in future, SKIPPING REPLAY" << dendl; return -1; } else if (opos == spos) { if (in_progress) { - dout(10) << "_check_replay_guard object has " << opos << " == current pos " << spos + dout(10) << __FUNC__ << ": object has " << opos << " == current pos " << spos << ", in_progress=true, CONDITIONAL REPLAY" << dendl; return 0; } else { - dout(10) << "_check_replay_guard object has " << opos << " == current pos " << spos + dout(10) << __FUNC__ << ": object has " << opos << " == current pos " << spos << ", in_progress=false, SKIPPING REPLAY" << dendl; return -1; } } else { - dout(10) << "_check_replay_guard object has " << opos << " < current pos " << spos + dout(10) << __FUNC__ << ": object has " << opos << " < current pos " << spos << ", in past, will replay" << dendl; return 1; } @@ -2553,7 +2578,7 @@ void FileStore::_do_transaction( Transaction& t, uint64_t op_seq, int trans_num, ThreadPool::TPHandle *handle) { - dout(10) << "_do_transaction on " << &t << dendl; + dout(10) << __FUNC__ << ": on " << &t << dendl; #ifdef WITH_LTTNG const char *osr_name = t.get_osr() ? static_cast(t.get_osr())->get_name().c_str() : ""; @@ -3129,10 +3154,10 @@ int FileStore::stat( int r = lfn_stat(cid, oid, st); assert(allow_eio || !m_filestore_fail_eio || r != -EIO); if (r < 0) { - dout(10) << "stat " << cid << "/" << oid + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " = " << r << dendl; } else { - dout(10) << "stat " << cid << "/" << oid + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " = " << r << " (size " << st->st_size << ")" << dendl; } @@ -3165,12 +3190,12 @@ int FileStore::read( tracepoint(objectstore, read_enter, _cid.c_str(), offset, len); const coll_t& cid = !_need_temp_object_collection(_cid, oid) ? _cid : _cid.get_temp(); - dout(15) << "read " << cid << "/" << oid << " " << offset << "~" << len << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << dendl; FDRef fd; int r = lfn_open(cid, oid, false, &fd); if (r < 0) { - dout(10) << "FileStore::read(" << cid << "/" << oid << ") open error: " + dout(10) << __FUNC__ << ": (" << cid << "/" << oid << ") open error: " << cpp_strerror(r) << dendl; return r; } @@ -3193,10 +3218,10 @@ int FileStore::read( bufferptr bptr(len); // prealloc space for entire read got = safe_pread(**fd, bptr.c_str(), len, offset); if (got < 0) { - dout(10) << "FileStore::read(" << cid << "/" << oid << ") pread error: " << cpp_strerror(got) << dendl; + dout(10) << __FUNC__ << ": (" << cid << "/" << oid << ") pread error: " << cpp_strerror(got) << dendl; lfn_close(fd); if (!(allow_eio || !m_filestore_fail_eio || got != -EIO)) { - derr << "FileStore::read(" << cid << "/" << oid << ") pread error: " << cpp_strerror(got) << dendl; + derr << __FUNC__ << ": (" << cid << "/" << oid << ") pread error: " << cpp_strerror(got) << dendl; assert(0 == "eio on pread"); } return got; @@ -3216,7 +3241,7 @@ int FileStore::read( ostringstream ss; int errors = backend->_crc_verify_read(**fd, offset, got, bl, &ss); if (errors != 0) { - dout(0) << "FileStore::read " << cid << "/" << oid << " " << offset << "~" + dout(0) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << got << " ... BAD CRC:\n" << ss.str() << dendl; assert(0 == "bad crc on read"); } @@ -3224,7 +3249,7 @@ int FileStore::read( lfn_close(fd); - dout(10) << "FileStore::read " << cid << "/" << oid << " " << offset << "~" + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << got << "/" << len << dendl; if (cct->_conf->filestore_debug_inject_read_err && debug_data_eio(oid)) { @@ -3267,7 +3292,7 @@ more: while (i < fiemap->fm_mapped_extents) { struct fiemap_extent *next = extent + 1; - dout(10) << "FileStore::fiemap() fm_mapped_extents=" << fiemap->fm_mapped_extents + dout(10) << __FUNC__ << ": fm_mapped_extents=" << fiemap->fm_mapped_extents << " fe_logical=" << extent->fe_logical << " fe_length=" << extent->fe_length << dendl; /* try to merge extents */ @@ -3374,7 +3399,7 @@ int FileStore::fiemap(const coll_t& _cid, const ghobject_t& oid, return 0; } - dout(15) << "fiemap " << cid << "/" << oid << " " << offset << "~" << len << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << dendl; FDRef fd; @@ -3396,7 +3421,7 @@ int FileStore::fiemap(const coll_t& _cid, const ghobject_t& oid, done: - dout(10) << "fiemap " << cid << "/" << oid << " " << offset << "~" << len << " = " << r << " num_extents=" << destmap.size() << " " << destmap << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << " = " << r << " num_extents=" << destmap.size() << " " << destmap << dendl; assert(!m_filestore_fail_eio || r != -EIO); tracepoint(objectstore, fiemap_exit, r); return r; @@ -3405,24 +3430,24 @@ done: int FileStore::_remove(const coll_t& cid, const ghobject_t& oid, const SequencerPosition &spos) { - dout(15) << "remove " << cid << "/" << oid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << dendl; int r = lfn_unlink(cid, oid, spos); - dout(10) << "remove " << cid << "/" << oid << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " = " << r << dendl; return r; } int FileStore::_truncate(const coll_t& cid, const ghobject_t& oid, uint64_t size) { - dout(15) << "truncate " << cid << "/" << oid << " size " << size << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " size " << size << dendl; int r = lfn_truncate(cid, oid, size); - dout(10) << "truncate " << cid << "/" << oid << " size " << size << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " size " << size << " = " << r << dendl; return r; } int FileStore::_touch(const coll_t& cid, const ghobject_t& oid) { - dout(15) << "touch " << cid << "/" << oid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << dendl; FDRef fd; int r = lfn_open(cid, oid, true, &fd); @@ -3431,7 +3456,7 @@ int FileStore::_touch(const coll_t& cid, const ghobject_t& oid) } else { lfn_close(fd); } - dout(10) << "touch " << cid << "/" << oid << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " = " << r << dendl; return r; } @@ -3439,13 +3464,13 @@ int FileStore::_write(const coll_t& cid, const ghobject_t& oid, uint64_t offset, size_t len, const bufferlist& bl, uint32_t fadvise_flags) { - dout(15) << "write " << cid << "/" << oid << " " << offset << "~" << len << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << dendl; int r; FDRef fd; r = lfn_open(cid, oid, true, &fd); if (r < 0) { - dout(0) << "write couldn't open " << cid << "/" + dout(0) << __FUNC__ << ": couldn't open " << cid << "/" << oid << ": " << cpp_strerror(r) << dendl; goto out; @@ -3454,7 +3479,7 @@ int FileStore::_write(const coll_t& cid, const ghobject_t& oid, // write r = bl.write_fd(**fd, offset); if (r < 0) { - derr << __func__ << " write_fd on " << cid << "/" << oid + derr << __FUNC__ << ": write_fd on " << cid << "/" << oid << " error: " << cpp_strerror(r) << dendl; lfn_close(fd); goto out; @@ -3480,13 +3505,13 @@ int FileStore::_write(const coll_t& cid, const ghobject_t& oid, lfn_close(fd); out: - dout(10) << "write " << cid << "/" << oid << " " << offset << "~" << len << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << " = " << r << dendl; return r; } int FileStore::_zero(const coll_t& cid, const ghobject_t& oid, uint64_t offset, size_t len) { - dout(15) << "zero " << cid << "/" << oid << " " << offset << "~" << len << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << dendl; int ret = 0; if (cct->_conf->filestore_punch_hole) { @@ -3542,7 +3567,7 @@ int FileStore::_zero(const coll_t& cid, const ghobject_t& oid, uint64_t offset, // lame, kernel is old and doesn't support it. // write zeros.. yuck! - dout(20) << "zero falling back to writing zeros" << dendl; + dout(20) << __FUNC__ << ": falling back to writing zeros" << dendl; { bufferlist bl; bl.append_zero(len); @@ -3556,14 +3581,14 @@ int FileStore::_zero(const coll_t& cid, const ghobject_t& oid, uint64_t offset, # endif # endif #endif - dout(20) << "zero " << cid << "/" << oid << " " << offset << "~" << len << " = " << ret << dendl; + dout(20) << __FUNC__ << ": " << cid << "/" << oid << " " << offset << "~" << len << " = " << ret << dendl; return ret; } int FileStore::_clone(const coll_t& cid, const ghobject_t& oldoid, const ghobject_t& newoid, const SequencerPosition& spos) { - dout(15) << "clone " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << dendl; if (_check_replay_guard(cid, newoid, spos) < 0) return 0; @@ -3637,20 +3662,20 @@ int FileStore::_clone(const coll_t& cid, const ghobject_t& oldoid, const ghobjec out: lfn_close(o); out2: - dout(10) << "clone " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oldoid << " -> " << cid << "/" << newoid << " = " << r << dendl; assert(!m_filestore_fail_eio || r != -EIO); return r; } int FileStore::_do_clone_range(int from, int to, uint64_t srcoff, uint64_t len, uint64_t dstoff) { - dout(20) << "_do_clone_range copy " << srcoff << "~" << len << " to " << dstoff << dendl; + dout(20) << __FUNC__ << ": copy " << srcoff << "~" << len << " to " << dstoff << dendl; return backend->clone_range(from, to, srcoff, len, dstoff); } int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t len, uint64_t dstoff) { - dout(20) << __func__ << " " << srcoff << "~" << len << " to " << dstoff << dendl; + dout(20) << __FUNC__ << ": " << srcoff << "~" << len << " to " << dstoff << dendl; int r = 0; map exomap; // fiemap doesn't allow zero length @@ -3674,7 +3699,7 @@ int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t uint64_t it_off = miter->first - srcoff + dstoff; r = _do_copy_range(from, to, miter->first, miter->second, it_off, true); if (r < 0) { - derr << "FileStore::_do_copy_range: copy error at " << miter->first << "~" << miter->second + derr << __FUNC__ << ": copy error at " << miter->first << "~" << miter->second << " to " << it_off << ", " << cpp_strerror(r) << dendl; break; } @@ -3690,14 +3715,14 @@ int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t r = ::fstat(to, &st); if (r < 0) { r = -errno; - derr << __func__ << ": fstat error at " << to << " " << cpp_strerror(r) << dendl; + derr << __FUNC__ << ": fstat error at " << to << " " << cpp_strerror(r) << dendl; goto out; } if (st.st_size < (int)(dstoff + len)) { r = ::ftruncate(to, dstoff + len); if (r < 0) { r = -errno; - derr << __func__ << ": ftruncate error at " << dstoff+len << " " << cpp_strerror(r) << dendl; + derr << __FUNC__ << ": ftruncate error at " << dstoff+len << " " << cpp_strerror(r) << dendl; goto out; } } @@ -3705,13 +3730,13 @@ int FileStore::_do_sparse_copy_range(int from, int to, uint64_t srcoff, uint64_t } out: - dout(20) << __func__ << " " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; + dout(20) << __FUNC__ << ": " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; return r; } int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, uint64_t dstoff, bool skip_sloppycrc) { - dout(20) << "_do_copy_range " << srcoff << "~" << len << " to " << dstoff << dendl; + dout(20) << __FUNC__ << ": " << srcoff << "~" << len << " to " << dstoff << dendl; int r = 0; loff_t pos = srcoff; loff_t end = srcoff + len; @@ -3732,14 +3757,14 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u r = safe_splice(from, &pos, pipefd[1], NULL, l, SPLICE_F_NONBLOCK); dout(10) << " safe_splice read from " << pos << "~" << l << " got " << r << dendl; if (r < 0) { - derr << "FileStore::_do_copy_range: safe_splice read error at " << pos << "~" << len + derr << __FUNC__ << ": safe_splice read error at " << pos << "~" << len << ", " << cpp_strerror(r) << dendl; break; } if (r == 0) { // hrm, bad source range, wtf. r = -ERANGE; - derr << "FileStore::_do_copy_range got short read result at " << pos + derr << __FUNC__ << ": got short read result at " << pos << " of fd " << from << " len " << len << dendl; break; } @@ -3748,7 +3773,7 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u dout(10) << " safe_splice write to " << to << " len " << r << " got " << r << dendl; if (r < 0) { - derr << "FileStore::_do_copy_range: write error at " << pos << "~" + derr << __FUNC__ << ": write error at " << pos << "~" << r << ", " << cpp_strerror(r) << dendl; break; } @@ -3789,7 +3814,7 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u continue; } else { r = -errno; - derr << "FileStore::_do_copy_range: read error at " << pos << "~" << len + derr << __FUNC__ << ": read error at " << pos << "~" << len << ", " << cpp_strerror(r) << dendl; break; } @@ -3797,7 +3822,7 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u if (r == 0) { // hrm, bad source range, wtf. r = -ERANGE; - derr << "FileStore::_do_copy_range got short read result at " << pos + derr << __FUNC__ << ": got short read result at " << pos << " of fd " << from << " len " << len << dendl; break; } @@ -3808,7 +3833,7 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u << " got " << r2 << dendl; if (r2 < 0) { r = r2; - derr << "FileStore::_do_copy_range: write error at " << pos << "~" + derr << __FUNC__ << ": write error at " << pos << "~" << r-op << ", " << cpp_strerror(r) << dendl; break; @@ -3823,7 +3848,7 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u if (r < 0 && replaying) { assert(r == -ERANGE); - derr << "Filestore: short source tolerated because we are replaying" << dendl; + derr << __FUNC__ << ": short source tolerated because we are replaying" << dendl; r = pos - from;; } assert(replaying || pos == end); @@ -3831,7 +3856,7 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u int rc = backend->_crc_update_clone_range(from, to, srcoff, len, dstoff); assert(rc >= 0); } - dout(20) << "_do_copy_range " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; + dout(20) << __FUNC__ << ": " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; return r; } @@ -3839,7 +3864,7 @@ int FileStore::_clone_range(const coll_t& oldcid, const ghobject_t& oldoid, cons uint64_t srcoff, uint64_t len, uint64_t dstoff, const SequencerPosition& spos) { - dout(15) << "clone_range " << oldcid << "/" << oldoid << " -> " << newcid << "/" << newoid << " " << srcoff << "~" << len << " to " << dstoff << dendl; + dout(15) << __FUNC__ << ": " << oldcid << "/" << oldoid << " -> " << newcid << "/" << newoid << " " << srcoff << "~" << len << " to " << dstoff << dendl; if (_check_replay_guard(newcid, newoid, spos) < 0) return 0; @@ -3867,7 +3892,7 @@ int FileStore::_clone_range(const coll_t& oldcid, const ghobject_t& oldoid, cons out: lfn_close(o); out2: - dout(10) << "clone_range " << oldcid << "/" << oldoid << " -> " << newcid << "/" << newoid << " " + dout(10) << __FUNC__ << ": " << oldcid << "/" << oldoid << " -> " << newcid << "/" << newoid << " " << srcoff << "~" << len << " to " << dstoff << " = " << r << dendl; return r; } @@ -3904,27 +3929,27 @@ void FileStore::sync_entry() utime_t startwait = ceph_clock_now(); if (!force_sync) { - dout(20) << "sync_entry waiting for max_interval " << max_interval << dendl; + dout(20) << __FUNC__ << ": waiting for max_interval " << max_interval << dendl; sync_cond.WaitInterval(lock, max_interval); } else { - dout(20) << "sync_entry not waiting, force_sync set" << dendl; + dout(20) << __FUNC__ << ": not waiting, force_sync set" << dendl; } if (force_sync) { - dout(20) << "sync_entry force_sync set" << dendl; + dout(20) << __FUNC__ << ": force_sync set" << dendl; force_sync = false; } else if (stop) { - dout(20) << __func__ << " stop set" << dendl; + dout(20) << __FUNC__ << ": stop set" << dendl; break; } else { // wait for at least the min interval utime_t woke = ceph_clock_now(); woke -= startwait; - dout(20) << "sync_entry woke after " << woke << dendl; + dout(20) << __FUNC__ << ": woke after " << woke << dendl; if (woke < min_interval) { utime_t t = min_interval; t -= woke; - dout(20) << "sync_entry waiting for another " << t + dout(20) << __FUNC__ << ": waiting for another " << t << " to reach min interval " << min_interval << dendl; sync_cond.WaitInterval(lock, t); } @@ -3948,7 +3973,7 @@ void FileStore::sync_entry() logger->set(l_filestore_committing, 1); - dout(15) << "sync_entry committing " << cp << dendl; + dout(15) << __FUNC__ << ": committing " << cp << dendl; stringstream errstream; if (cct->_conf->filestore_debug_omap_check && !object_map->check(errstream)) { derr << errstream.str() << dendl; @@ -4017,7 +4042,7 @@ void FileStore::sync_entry() utime_t done = ceph_clock_now(); utime_t lat = done - start; utime_t dur = done - startwait; - dout(10) << "sync_entry commit took " << lat << ", interval was " << dur << dendl; + dout(10) << __FUNC__ << ": commit took " << lat << ", interval was " << dur << dendl; logger->inc(l_filestore_commitcycle); logger->tinc(l_filestore_commitcycle_latency, lat); @@ -4045,7 +4070,7 @@ void FileStore::sync_entry() } } - dout(15) << "sync_entry committed to op_seq " << cp << dendl; + dout(15) << __FUNC__ << ": committed to op_seq " << cp << dendl; sync_entry_timeo_lock.Lock(); timer.cancel_event(sync_entry_timeo); @@ -4058,11 +4083,11 @@ void FileStore::sync_entry() finish_contexts(cct, fin, 0); fin.clear(); if (!sync_waiters.empty()) { - dout(10) << "sync_entry more waiters, committing again" << dendl; + dout(10) << __FUNC__ << ": more waiters, committing again" << dendl; goto again; } if (!stop && journal && journal->should_commit_now()) { - dout(10) << "sync_entry journal says we should commit again (probably is/was full)" << dendl; + dout(10) << __FUNC__ << ": journal says we should commit again (probably is/was full)" << dendl; goto again; } } @@ -4073,16 +4098,16 @@ void FileStore::sync_entry() void FileStore::_start_sync() { if (!journal) { // don't do a big sync if the journal is on - dout(10) << "start_sync" << dendl; + dout(10) << __FUNC__ << dendl; sync_cond.Signal(); } else { - dout(10) << "start_sync - NOOP (journal is on)" << dendl; + dout(10) << __FUNC__ << ": - NOOP (journal is on)" << dendl; } } void FileStore::do_force_sync() { - dout(10) << __func__ << dendl; + dout(10) << __FUNC__ << dendl; Mutex::Locker l(lock); force_sync = true; sync_cond.Signal(); @@ -4094,7 +4119,7 @@ void FileStore::start_sync(Context *onsafe) sync_waiters.push_back(onsafe); sync_cond.Signal(); force_sync = true; - dout(10) << "start_sync" << dendl; + dout(10) << __FUNC__ << dendl; } void FileStore::sync() @@ -4117,9 +4142,9 @@ void FileStore::sync() void FileStore::_flush_op_queue() { - dout(10) << "_flush_op_queue draining op tp" << dendl; + dout(10) << __FUNC__ << ": draining op tp" << dendl; op_wq.drain(); - dout(10) << "_flush_op_queue waiting for apply finisher" << dendl; + dout(10) << __FUNC__ << ": waiting for apply finisher" << dendl; for (vector::iterator it = apply_finishers.begin(); it != apply_finishers.end(); ++it) { (*it)->wait_for_empty(); } @@ -4130,7 +4155,7 @@ void FileStore::_flush_op_queue() */ void FileStore::flush() { - dout(10) << "flush" << dendl; + dout(10) << __FUNC__ << dendl; if (cct->_conf->filestore_blackhole) { // wait forever @@ -4145,14 +4170,14 @@ void FileStore::flush() if (m_filestore_journal_writeahead) { if (journal) journal->flush(); - dout(10) << "flush draining ondisk finisher" << dendl; + dout(10) << __FUNC__ << ": draining ondisk finisher" << dendl; for (vector::iterator it = ondisk_finishers.begin(); it != ondisk_finishers.end(); ++it) { (*it)->wait_for_empty(); } } _flush_op_queue(); - dout(10) << "flush complete" << dendl; + dout(10) << __FUNC__ << ": complete" << dendl; } /* @@ -4160,7 +4185,7 @@ void FileStore::flush() */ void FileStore::sync_and_flush() { - dout(10) << "sync_and_flush" << dendl; + dout(10) << __FUNC__ << dendl; if (m_filestore_journal_writeahead) { if (journal) @@ -4171,12 +4196,12 @@ void FileStore::sync_and_flush() _flush_op_queue(); sync(); } - dout(10) << "sync_and_flush done" << dendl; + dout(10) << __FUNC__ << ": done" << dendl; } int FileStore::flush_journal() { - dout(10) << __func__ << dendl; + dout(10) << __FUNC__ << dendl; sync_and_flush(); sync(); return 0; @@ -4184,11 +4209,11 @@ int FileStore::flush_journal() int FileStore::snapshot(const string& name) { - dout(10) << "snapshot " << name << dendl; + dout(10) << __FUNC__ << ": " << name << dendl; sync_and_flush(); if (!backend->can_checkpoint()) { - dout(0) << "snapshot " << name << " failed, not supported" << dendl; + dout(0) << __FUNC__ << ": " << name << " failed, not supported" << dendl; return -EOPNOTSUPP; } @@ -4197,7 +4222,7 @@ int FileStore::snapshot(const string& name) int r = backend->create_checkpoint(s, NULL); if (r) { - derr << "snapshot " << name << " failed: " << cpp_strerror(r) << dendl; + derr << __FUNC__ << ": " << name << " failed: " << cpp_strerror(r) << dendl; } return r; @@ -4260,7 +4285,7 @@ int FileStore::_fgetattrs(int fd, map& aset) char *attrname = name; if (parse_attrname(&name)) { if (*name) { - dout(20) << "fgetattrs " << fd << " getting '" << name << "'" << dendl; + dout(20) << __FUNC__ << ": " << fd << " getting '" << name << "'" << dendl; int r = _fgetattr(fd, attrname, aset[name]); if (r < 0) { delete[] names2; @@ -4290,7 +4315,7 @@ int FileStore::_fsetattrs(int fd, map &aset) // ??? Why do we skip setting all the other attrs if one fails? int r = chain_fsetxattr(fd, n, val, p->second.length()); if (r < 0) { - derr << "FileStore::_setattrs: chain_setxattr returned " << r << dendl; + derr << __FUNC__ << ": chain_setxattr returned " << r << dendl; return r; } } @@ -4300,24 +4325,24 @@ int FileStore::_fsetattrs(int fd, map &aset) // debug EIO injection void FileStore::inject_data_error(const ghobject_t &oid) { Mutex::Locker l(read_error_lock); - dout(10) << __func__ << ": init error on " << oid << dendl; + dout(10) << __FUNC__ << ": init error on " << oid << dendl; data_error_set.insert(oid); } void FileStore::inject_mdata_error(const ghobject_t &oid) { Mutex::Locker l(read_error_lock); - dout(10) << __func__ << ": init error on " << oid << dendl; + dout(10) << __FUNC__ << ": init error on " << oid << dendl; mdata_error_set.insert(oid); } void FileStore::debug_obj_on_delete(const ghobject_t &oid) { Mutex::Locker l(read_error_lock); - dout(10) << __func__ << ": clear error on " << oid << dendl; + dout(10) << __FUNC__ << ": clear error on " << oid << dendl; data_error_set.erase(oid); mdata_error_set.erase(oid); } bool FileStore::debug_data_eio(const ghobject_t &oid) { Mutex::Locker l(read_error_lock); if (data_error_set.count(oid)) { - dout(10) << __func__ << ": inject error on " << oid << dendl; + dout(10) << __FUNC__ << ": inject error on " << oid << dendl; return true; } else { return false; @@ -4326,7 +4351,7 @@ bool FileStore::debug_data_eio(const ghobject_t &oid) { bool FileStore::debug_mdata_eio(const ghobject_t &oid) { Mutex::Locker l(read_error_lock); if (mdata_error_set.count(oid)) { - dout(10) << __func__ << ": inject error on " << oid << dendl; + dout(10) << __FUNC__ << ": inject error on " << oid << dendl; return true; } else { return false; @@ -4340,7 +4365,7 @@ int FileStore::getattr(const coll_t& _cid, const ghobject_t& oid, const char *na { tracepoint(objectstore, getattr_enter, _cid.c_str()); const coll_t& cid = !_need_temp_object_collection(_cid, oid) ? _cid : _cid.get_temp(); - dout(15) << "getattr " << cid << "/" << oid << " '" << name << "'" << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " '" << name << "'" << dendl; FDRef fd; int r = lfn_open(cid, oid, false, &fd); if (r < 0) { @@ -4357,16 +4382,16 @@ int FileStore::getattr(const coll_t& _cid, const ghobject_t& oid, const char *na Index index; r = get_index(cid, &index); if (r < 0) { - dout(10) << __func__ << " could not get index r = " << r << dendl; + dout(10) << __FUNC__ << ": could not get index r = " << r << dendl; goto out; } r = object_map->get_xattrs(oid, to_get, &got); if (r < 0 && r != -ENOENT) { - dout(10) << __func__ << " get_xattrs err r =" << r << dendl; + dout(10) << __FUNC__ << ": get_xattrs err r =" << r << dendl; goto out; } if (got.empty()) { - dout(10) << __func__ << " got.size() is 0" << dendl; + dout(10) << __FUNC__ << ": got.size() is 0" << dendl; return -ENODATA; } bp = bufferptr(got.begin()->second.c_str(), @@ -4374,7 +4399,7 @@ int FileStore::getattr(const coll_t& _cid, const ghobject_t& oid, const char *na r = bp.length(); } out: - dout(10) << "getattr " << cid << "/" << oid << " '" << name << "' = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " '" << name << "' = " << r << dendl; assert(!m_filestore_fail_eio || r != -EIO); if (cct->_conf->filestore_debug_inject_read_err && debug_mdata_eio(oid)) { @@ -4392,7 +4417,7 @@ int FileStore::getattrs(const coll_t& _cid, const ghobject_t& oid, map omap_attrs; map omap_aset; Index index; - dout(15) << "getattrs " << cid << "/" << oid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << dendl; FDRef fd; bool spill_out = true; char buf[2]; @@ -4414,25 +4439,25 @@ int FileStore::getattrs(const coll_t& _cid, const ghobject_t& oid, mapremove_xattrs(oid, omap_remove, &spos); if (r < 0 && r != -ENOENT) { - dout(10) << __func__ << " could not remove_xattrs r = " << r << dendl; + dout(10) << __FUNC__ << ": could not remove_xattrs r = " << r << dendl; assert(!m_filestore_fail_eio || r != -EIO); goto out_close; } else { @@ -4546,7 +4571,7 @@ int FileStore::_setattrs(const coll_t& cid, const ghobject_t& oid, mapset_xattrs(oid, omap_set, &spos); if (r < 0) { - dout(10) << __func__ << " could not set_xattrs r = " << r << dendl; + dout(10) << __FUNC__ << ": could not set_xattrs r = " << r << dendl; assert(!m_filestore_fail_eio || r != -EIO); goto out_close; } @@ -4554,7 +4579,7 @@ int FileStore::_setattrs(const coll_t& cid, const ghobject_t& oid, map aset; FDRef fd; @@ -4632,32 +4657,32 @@ int FileStore::_rmattrs(const coll_t& cid, const ghobject_t& oid, get_attrname(p->first.c_str(), n, CHAIN_XATTR_MAX_NAME_LEN); r = chain_fremovexattr(**fd, n); if (r < 0) { - dout(10) << __func__ << " could not remove xattr r = " << r << dendl; + dout(10) << __FUNC__ << ": could not remove xattr r = " << r << dendl; goto out_close; } } } if (!spill_out) { - dout(10) << __func__ << " no xattr exists in object_map r = " << r << dendl; + dout(10) << __FUNC__ << ": no xattr exists in object_map r = " << r << dendl; goto out_close; } r = get_index(cid, &index); if (r < 0) { - dout(10) << __func__ << " could not get index r = " << r << dendl; + dout(10) << __FUNC__ << ": could not get index r = " << r << dendl; goto out_close; } { r = object_map->get_all_xattrs(oid, &omap_attrs); if (r < 0 && r != -ENOENT) { - dout(10) << __func__ << " could not get omap_attrs r = " << r << dendl; + dout(10) << __FUNC__ << ": could not get omap_attrs r = " << r << dendl; assert(!m_filestore_fail_eio || r != -EIO); goto out_close; } r = object_map->remove_xattrs(oid, omap_attrs, &spos); if (r < 0 && r != -ENOENT) { - dout(10) << __func__ << " could not remove omap_attrs r = " << r << dendl; + dout(10) << __FUNC__ << ": could not remove omap_attrs r = " << r << dendl; goto out_close; } if (r == -ENOENT) @@ -4669,7 +4694,7 @@ int FileStore::_rmattrs(const coll_t& cid, const ghobject_t& oid, out_close: lfn_close(fd); out: - dout(10) << "rmattrs " << cid << "/" << oid << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " = " << r << dendl; return r; } @@ -4718,7 +4743,7 @@ int FileStore::list_collections(vector& ls) int FileStore::list_collections(vector& ls, bool include_temp) { tracepoint(objectstore, list_collections_enter); - dout(10) << "list_collections" << dendl; + dout(10) << __FUNC__ << dendl; char fn[PATH_MAX]; snprintf(fn, sizeof(fn), "%s/current", basedir.c_str()); @@ -4786,11 +4811,11 @@ int FileStore::collection_stat(const coll_t& c, struct stat *st) tracepoint(objectstore, collection_stat_enter, c.c_str()); char fn[PATH_MAX]; get_cdir(c, fn, sizeof(fn)); - dout(15) << "collection_stat " << fn << dendl; + dout(15) << __FUNC__ << ": " << fn << dendl; int r = ::stat(fn, st); if (r < 0) r = -errno; - dout(10) << "collection_stat " << fn << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << fn << " = " << r << dendl; assert(!m_filestore_fail_eio || r != -EIO); tracepoint(objectstore, collection_stat_exit, r); return r; @@ -4808,11 +4833,11 @@ bool FileStore::collection_exists(const coll_t& c) int FileStore::collection_empty(const coll_t& c, bool *empty) { tracepoint(objectstore, collection_empty_enter, c.c_str()); - dout(15) << "collection_empty " << c << dendl; + dout(15) << __FUNC__ << ": " << c << dendl; Index index; int r = get_index(c, &index); if (r < 0) { - derr << __func__ << " get_index returned: " << cpp_strerror(r) + derr << __FUNC__ << ": get_index returned: " << cpp_strerror(r) << dendl; return r; } @@ -4824,7 +4849,7 @@ int FileStore::collection_empty(const coll_t& c, bool *empty) r = index->collection_list_partial(ghobject_t(), ghobject_t::get_max(), 1, &ls, NULL); if (r < 0) { - derr << __func__ << " collection_list_partial returned: " + derr << __FUNC__ << ": collection_list_partial returned: " << cpp_strerror(r) << dendl; assert(!m_filestore_fail_eio || r != -EIO); return r; @@ -4838,7 +4863,7 @@ int FileStore::_collection_set_bits(const coll_t& c, int bits) { char fn[PATH_MAX]; get_cdir(c, fn, sizeof(fn)); - dout(10) << "collection_set_bits " << fn << " " << bits << dendl; + dout(10) << __FUNC__ << ": " << fn << " " << bits << dendl; char n[PATH_MAX]; int r; int32_t v = bits; @@ -4851,7 +4876,7 @@ int FileStore::_collection_set_bits(const coll_t& c, int bits) r = chain_fsetxattr(fd, n, (char*)&v, sizeof(v)); VOID_TEMP_FAILURE_RETRY(::close(fd)); out: - dout(10) << "collection_setattr " << fn << " " << bits << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << fn << " " << bits << " = " << r << dendl; return r; } @@ -4859,7 +4884,7 @@ int FileStore::collection_bits(const coll_t& c) { char fn[PATH_MAX]; get_cdir(c, fn, sizeof(fn)); - dout(15) << "collection_bits " << fn << dendl; + dout(15) << __FUNC__ << ": " << fn << dendl; int r; char n[PATH_MAX]; int32_t bits; @@ -4876,7 +4901,7 @@ int FileStore::collection_bits(const coll_t& c) goto out; } out: - dout(10) << "collection_bits " << fn << " = " << bits << dendl; + dout(10) << __FUNC__ << ": " << fn << " = " << bits << dendl; return bits; } @@ -4914,7 +4939,7 @@ int FileStore::collection_list(const coll_t& c, pool = 0; shard = shard_id_t::NO_SHARD; } - dout(20) << __func__ << " pool is " << pool << " shard is " << shard + dout(20) << __FUNC__ << ": pool is " << pool << " shard is " << shard << " pgid " << pgid << dendl; } ghobject_t sep; @@ -4922,7 +4947,7 @@ int FileStore::collection_list(const coll_t& c, sep.set_shard(shard); if (!c.is_temp() && !c.is_meta()) { if (start < sep) { - dout(10) << __func__ << " first checking temp pool" << dendl; + dout(10) << __FUNC__ << ": first checking temp pool" << dendl; coll_t temp = c.get_temp(); int r = collection_list(temp, start, end, max, ls, next); if (r < 0) @@ -4930,10 +4955,10 @@ int FileStore::collection_list(const coll_t& c, if (*next != ghobject_t::get_max()) return r; start = sep; - dout(10) << __func__ << " fall through to non-temp collection, start " + dout(10) << __FUNC__ << ": fall through to non-temp collection, start " << start << dendl; } else { - dout(10) << __func__ << " start " << start << " >= sep " << sep << dendl; + dout(10) << __FUNC__ << ": start " << start << " >= sep " << sep << dendl; } } @@ -4969,7 +4994,7 @@ int FileStore::omap_get(const coll_t& _c, const ghobject_t &hoid, { tracepoint(objectstore, omap_get_enter, _c.c_str()); const coll_t& c = !_need_temp_object_collection(_c, hoid) ? _c : _c.get_temp(); - dout(15) << __func__ << " " << c << "/" << hoid << dendl; + dout(15) << __FUNC__ << ": " << c << "/" << hoid << dendl; Index index; int r = get_index(c, &index); if (r < 0) @@ -4998,7 +5023,7 @@ int FileStore::omap_get_header( { tracepoint(objectstore, omap_get_header_enter, _c.c_str()); const coll_t& c = !_need_temp_object_collection(_c, hoid) ? _c : _c.get_temp(); - dout(15) << __func__ << " " << c << "/" << hoid << dendl; + dout(15) << __FUNC__ << ": " << c << "/" << hoid << dendl; Index index; int r = get_index(c, &index); if (r < 0) @@ -5023,7 +5048,7 @@ int FileStore::omap_get_keys(const coll_t& _c, const ghobject_t &hoid, setaccess_lock); r = lfn_find(hoid, index); if (r < 0) { - dout(10) << __func__ << " " << c << "/" << hoid << " = 0 " + dout(10) << __FUNC__ << ": " << c << "/" << hoid << " = 0 " << "(lfn_find failed with " << cpp_strerror(r) << ")" << dendl; return ObjectMap::ObjectMapIterator(); } @@ -5139,7 +5164,7 @@ int FileStore::_collection_hint_expected_num_objs(const coll_t& c, uint32_t pg_n uint64_t expected_num_objs, const SequencerPosition &spos) { - dout(15) << __func__ << " collection: " << c << " pg number: " + dout(15) << __FUNC__ << ": collection: " << c << " pg number: " << pg_num << " expected number of objects: " << expected_num_objs << dendl; bool empty; @@ -5173,13 +5198,13 @@ int FileStore::_create_collection( { char fn[PATH_MAX]; get_cdir(c, fn, sizeof(fn)); - dout(15) << "create_collection " << fn << dendl; + dout(15) << __FUNC__ << ": " << fn << dendl; int r = ::mkdir(fn, 0755); if (r < 0) r = -errno; if (r == -EEXIST && replaying) r = 0; - dout(10) << "create_collection " << fn << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << fn << " = " << r << dendl; if (r < 0) return r; @@ -5206,7 +5231,7 @@ int FileStore::_destroy_collection(const coll_t& c) int r = 0; char fn[PATH_MAX]; get_cdir(c, fn, sizeof(fn)); - dout(15) << "_destroy_collection " << fn << dendl; + dout(15) << __FUNC__ << ": " << fn << dendl; { Index from; r = get_index(c, &from); @@ -5237,7 +5262,7 @@ int FileStore::_destroy_collection(const coll_t& c) } out_final: - dout(10) << "_destroy_collection " << fn << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << fn << " = " << r << dendl; return r; } @@ -5245,7 +5270,7 @@ int FileStore::_destroy_collection(const coll_t& c) int FileStore::_collection_add(const coll_t& c, const coll_t& oldcid, const ghobject_t& o, const SequencerPosition& spos) { - dout(15) << "collection_add " << c << "/" << o << " from " << oldcid << "/" << o << dendl; + dout(15) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << o << dendl; int dstcmp = _check_replay_guard(c, o, spos); if (dstcmp < 0) @@ -5265,7 +5290,7 @@ int FileStore::_collection_add(const coll_t& c, const coll_t& oldcid, const ghob // the source collection/object does not exist. If we are replaying, we // should be safe, so just return 0 and move on. assert(replaying); - dout(10) << "collection_add " << c << "/" << o << " from " + dout(10) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << o << " (dne, continue replay) " << dendl; return 0; } @@ -5286,7 +5311,7 @@ int FileStore::_collection_add(const coll_t& c, const coll_t& oldcid, const ghob } lfn_close(fd); - dout(10) << "collection_add " << c << "/" << o << " from " << oldcid << "/" << o << " = " << r << dendl; + dout(10) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << o << " = " << r << dendl; return r; } @@ -5295,7 +5320,7 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o const SequencerPosition& spos, bool allow_enoent) { - dout(15) << __func__ << " " << c << "/" << o << " from " << oldcid << "/" << oldoid << dendl; + dout(15) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << oldoid << dendl; int r = 0; int dstcmp, srccmp; @@ -5326,10 +5351,10 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o // the source collection/object does not exist. If we are replaying, we // should be safe, so just return 0 and move on. if (replaying) { - dout(10) << __func__ << " " << c << "/" << o << " from " + dout(10) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << oldoid << " (dne, continue replay) " << dendl; } else if (allow_enoent) { - dout(10) << __func__ << " " << c << "/" << o << " from " + dout(10) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << oldoid << " (dne, ignoring enoent)" << dendl; } else { @@ -5382,7 +5407,7 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o } } - dout(10) << __func__ << " " << c << "/" << o << " from " << oldcid << "/" << oldoid + dout(10) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << oldoid << " = " << r << dendl; return r; @@ -5392,18 +5417,18 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o r = lfn_unlink(oldcid, oldoid, spos, true); } - dout(10) << __func__ << " " << c << "/" << o << " from " << oldcid << "/" << oldoid + dout(10) << __FUNC__ << ": " << c << "/" << o << " from " << oldcid << "/" << oldoid << " = " << r << dendl; return r; } void FileStore::_inject_failure() { - if (m_filestore_kill_at.read()) { - int final = m_filestore_kill_at.dec(); - dout(5) << "_inject_failure " << (final+1) << " -> " << final << dendl; + if (m_filestore_kill_at) { + int final = --m_filestore_kill_at; + dout(5) << __FUNC__ << ": " << (final+1) << " -> " << final << dendl; if (final == 0) { - derr << "_inject_failure KILLING" << dendl; + derr << __FUNC__ << ": KILLING" << dendl; cct->_log->flush(); _exit(1); } @@ -5412,7 +5437,7 @@ void FileStore::_inject_failure() int FileStore::_omap_clear(const coll_t& cid, const ghobject_t &hoid, const SequencerPosition &spos) { - dout(15) << __func__ << " " << cid << "/" << hoid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << hoid << dendl; Index index; int r = get_index(cid, &index); if (r < 0) @@ -5433,7 +5458,7 @@ int FileStore::_omap_clear(const coll_t& cid, const ghobject_t &hoid, int FileStore::_omap_setkeys(const coll_t& cid, const ghobject_t &hoid, const map &aset, const SequencerPosition &spos) { - dout(15) << __func__ << " " << cid << "/" << hoid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << hoid << dendl; Index index; int r; //treat pgmeta as a logical object, skip to check exist @@ -5442,7 +5467,7 @@ int FileStore::_omap_setkeys(const coll_t& cid, const ghobject_t &hoid, r = get_index(cid, &index); if (r < 0) { - dout(20) << __func__ << " get_index got " << cpp_strerror(r) << dendl; + dout(20) << __FUNC__ << ": get_index got " << cpp_strerror(r) << dendl; return r; } { @@ -5450,25 +5475,25 @@ int FileStore::_omap_setkeys(const coll_t& cid, const ghobject_t &hoid, RWLock::RLocker l((index.index)->access_lock); r = lfn_find(hoid, index); if (r < 0) { - dout(20) << __func__ << " lfn_find got " << cpp_strerror(r) << dendl; + dout(20) << __FUNC__ << ": lfn_find got " << cpp_strerror(r) << dendl; return r; } } skip: if (g_conf->subsys.should_gather(ceph_subsys_filestore, 20)) { for (auto& p : aset) { - dout(20) << __func__ << " set " << p.first << dendl; + dout(20) << __FUNC__ << ": set " << p.first << dendl; } } r = object_map->set_keys(hoid, aset, &spos); - dout(20) << __func__ << " " << cid << "/" << hoid << " = " << r << dendl; + dout(20) << __FUNC__ << ": " << cid << "/" << hoid << " = " << r << dendl; return r; } int FileStore::_omap_rmkeys(const coll_t& cid, const ghobject_t &hoid, const set &keys, const SequencerPosition &spos) { - dout(15) << __func__ << " " << cid << "/" << hoid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << hoid << dendl; Index index; int r; //treat pgmeta as a logical object, skip to check exist @@ -5495,7 +5520,7 @@ skip: int FileStore::_omap_rmkeyrange(const coll_t& cid, const ghobject_t &hoid, const string& first, const string& last, const SequencerPosition &spos) { - dout(15) << __func__ << " " << cid << "/" << hoid << " [" << first << "," << last << "]" << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << hoid << " [" << first << "," << last << "]" << dendl; set keys; { ObjectMap::ObjectMapIterator iter = get_omap_iterator(cid, hoid); @@ -5513,7 +5538,7 @@ int FileStore::_omap_setheader(const coll_t& cid, const ghobject_t &hoid, const bufferlist &bl, const SequencerPosition &spos) { - dout(15) << __func__ << " " << cid << "/" << hoid << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << hoid << dendl; Index index; int r = get_index(cid, &index); if (r < 0) @@ -5536,14 +5561,14 @@ int FileStore::_split_collection(const coll_t& cid, { int r; { - dout(15) << __func__ << " " << cid << " bits: " << bits << dendl; + dout(15) << __FUNC__ << ": " << cid << " bits: " << bits << dendl; if (!collection_exists(cid)) { - dout(2) << __func__ << ": " << cid << " DNE" << dendl; + dout(2) << __FUNC__ << ": " << cid << " DNE" << dendl; assert(replaying); return 0; } if (!collection_exists(dest)) { - dout(2) << __func__ << ": " << dest << " DNE" << dendl; + dout(2) << __FUNC__ << ": " << dest << " DNE" << dendl; assert(replaying); return 0; } @@ -5596,7 +5621,7 @@ int FileStore::_split_collection(const coll_t& cid, for (vector::iterator i = objects.begin(); i != objects.end(); ++i) { - dout(20) << __func__ << ": " << *i << " still in source " + dout(20) << __FUNC__ << ": " << *i << " still in source " << cid << dendl; assert(!i->match(bits, rem)); } @@ -5615,7 +5640,7 @@ int FileStore::_split_collection(const coll_t& cid, for (vector::iterator i = objects.begin(); i != objects.end(); ++i) { - dout(20) << __func__ << ": " << *i << " now in dest " + dout(20) << __FUNC__ << ": " << *i << " now in dest " << *i << dendl; assert(i->match(bits, rem)); } @@ -5629,7 +5654,7 @@ int FileStore::_set_alloc_hint(const coll_t& cid, const ghobject_t& oid, uint64_t expected_object_size, uint64_t expected_write_size) { - dout(15) << "set_alloc_hint " << cid << "/" << oid << " object_size " << expected_object_size << " write_size " << expected_write_size << dendl; + dout(15) << __FUNC__ << ": " << cid << "/" << oid << " object_size " << expected_object_size << " write_size " << expected_write_size << dendl; FDRef fd; int ret = 0; @@ -5646,12 +5671,12 @@ int FileStore::_set_alloc_hint(const coll_t& cid, const ghobject_t& oid, uint64_t hint = MIN(expected_write_size, m_filestore_max_alloc_hint_size); ret = backend->set_alloc_hint(**fd, hint); - dout(20) << "set_alloc_hint hint " << hint << " ret " << ret << dendl; + dout(20) << __FUNC__ << ": hint " << hint << " ret " << ret << dendl; } lfn_close(fd); out: - dout(10) << "set_alloc_hint " << cid << "/" << oid << " object_size " << expected_object_size << " write_size " << expected_write_size << " = " << ret << dendl; + dout(10) << __FUNC__ << ": " << cid << "/" << oid << " object_size " << expected_object_size << " write_size " << expected_write_size << " = " << ret << dendl; assert(!m_filestore_fail_eio || ret != -EIO); return ret; } @@ -5738,7 +5763,7 @@ void FileStore::handle_conf_change(const struct md_config_t *conf, Mutex::Locker l(lock); m_filestore_min_sync_interval = conf->filestore_min_sync_interval; m_filestore_max_sync_interval = conf->filestore_max_sync_interval; - m_filestore_kill_at.set(conf->filestore_kill_at); + m_filestore_kill_at = conf->filestore_kill_at; m_filestore_fail_eio = conf->filestore_fail_eio; m_filestore_fadvise = conf->filestore_fadvise; m_filestore_sloppy_crc = conf->filestore_sloppy_crc; @@ -5793,7 +5818,7 @@ int FileStore::set_throttle_params() void FileStore::dump_start(const std::string& file) { - dout(10) << "dump_start " << file << dendl; + dout(10) << __FUNC__ << ": " << file << dendl; if (m_filestore_do_dump) { dump_stop(); } @@ -5805,7 +5830,7 @@ void FileStore::dump_start(const std::string& file) void FileStore::dump_stop() { - dout(10) << "dump_stop" << dendl; + dout(10) << __FUNC__ << dendl; m_filestore_do_dump = false; if (m_filestore_dump.is_open()) { m_filestore_dump_fmt.close_section(); @@ -5897,7 +5922,7 @@ uint64_t FileStore::estimate_objects_overhead(uint64_t num_objects) int FileStore::apply_layout_settings(const coll_t &cid) { - dout(20) << __func__ << " " << cid << dendl; + dout(20) << __FUNC__ << ": " << cid << dendl; Index index; int r = get_index(cid, &index); if (r < 0) { diff --git a/ceph/src/os/filestore/FileStore.h b/ceph/src/os/filestore/FileStore.h index f80b807bd..88a1d3170 100644 --- a/ceph/src/os/filestore/FileStore.h +++ b/ceph/src/os/filestore/FileStore.h @@ -20,10 +20,13 @@ #include #include -#include +#include #include + using namespace std; +#include + #include "include/unordered_map.h" #include "include/assert.h" @@ -364,7 +367,7 @@ private: FDCache fdcache; WBThrottle wbthrottle; - atomic_t next_osr_id; + std::atomic next_osr_id = { 0 }; bool m_disable_wbthrottle; deque op_queue; BackoffThrottle throttle_ops, throttle_bytes; @@ -478,6 +481,9 @@ public: bool needs_journal() override { return false; } + + bool is_rotational() override; + void dump_perf_counters(Formatter *f) override { f->open_object_section("perf_counters"); logger->dump_formatted(f, false); @@ -766,7 +772,7 @@ private: bool m_filestore_do_dump; std::ofstream m_filestore_dump; JSONFormatter m_filestore_dump_fmt; - atomic_t m_filestore_kill_at; + std::atomic m_filestore_kill_at = { 0 }; bool m_filestore_sloppy_crc; int m_filestore_sloppy_crc_block_size; uint64_t m_filestore_max_alloc_hint_size; @@ -861,6 +867,7 @@ public: virtual int syncfs() = 0; virtual bool has_fiemap() = 0; virtual bool has_seek_data_hole() = 0; + virtual bool is_rotational() = 0; virtual int do_fiemap(int fd, off_t start, size_t len, struct fiemap **pfiemap) = 0; virtual int clone_range(int from, int to, uint64_t srcoff, uint64_t len, uint64_t dstoff) = 0; virtual int set_alloc_hint(int fd, uint64_t hint) = 0; diff --git a/ceph/src/os/filestore/GenericFileStoreBackend.cc b/ceph/src/os/filestore/GenericFileStoreBackend.cc index 4821621f4..33680a4ca 100644 --- a/ceph/src/os/filestore/GenericFileStoreBackend.cc +++ b/ceph/src/os/filestore/GenericFileStoreBackend.cc @@ -39,6 +39,7 @@ #include "common/errno.h" #include "common/config.h" #include "common/sync_filesystem.h" +#include "common/blkdev.h" #include "common/SloppyCRCMap.h" #include "os/filestore/chain_xattr.h" @@ -63,7 +64,30 @@ GenericFileStoreBackend::GenericFileStoreBackend(FileStore *fs): m_filestore_fiemap(cct()->_conf->filestore_fiemap), m_filestore_seek_data_hole(cct()->_conf->filestore_seek_data_hole), m_filestore_fsync_flushes_journal_data(cct()->_conf->filestore_fsync_flushes_journal_data), - m_filestore_splice(cct()->_conf->filestore_splice) {} + m_filestore_splice(cct()->_conf->filestore_splice) +{ + // rotational? + { + // NOTE: the below won't work on btrfs; we'll assume rotational. + string fn = get_basedir_path(); + int fd = ::open(fn.c_str(), O_RDONLY); + if (fd < 0) { + return; + } + char partition[PATH_MAX], devname[PATH_MAX]; + int r = get_device_by_fd(fd, partition, devname, sizeof(devname)); + if (r < 0) { + dout(1) << "unable to get device name for " << get_basedir_path() << ": " + << cpp_strerror(r) << dendl; + m_rotational = true; + } else { + m_rotational = block_device_is_rotational(devname); + dout(20) << __func__ << " devname " << devname + << " rotational " << (int)m_rotational << dendl; + } + ::close(fd); + } +} int GenericFileStoreBackend::detect_features() { diff --git a/ceph/src/os/filestore/GenericFileStoreBackend.h b/ceph/src/os/filestore/GenericFileStoreBackend.h index df5d1acf3..8478067fa 100644 --- a/ceph/src/os/filestore/GenericFileStoreBackend.h +++ b/ceph/src/os/filestore/GenericFileStoreBackend.h @@ -28,6 +28,7 @@ private: bool m_filestore_seek_data_hole; bool m_filestore_fsync_flushes_journal_data; bool m_filestore_splice; + bool m_rotational = true; public: explicit GenericFileStoreBackend(FileStore *fs); ~GenericFileStoreBackend() override {} @@ -38,6 +39,9 @@ public: int detect_features() override; int create_current() override; bool can_checkpoint() override { return false; } + bool is_rotational() override { + return m_rotational; + } int list_checkpoints(list& ls) override { return 0; } int create_checkpoint(const string& name, uint64_t *cid) override { return -EOPNOTSUPP; } int sync_checkpoint(uint64_t id) override { return -EOPNOTSUPP; } diff --git a/ceph/src/os/filestore/ZFSFileStoreBackend.h b/ceph/src/os/filestore/ZFSFileStoreBackend.h index 1c15bdaac..b1fa98874 100644 --- a/ceph/src/os/filestore/ZFSFileStoreBackend.h +++ b/ceph/src/os/filestore/ZFSFileStoreBackend.h @@ -18,6 +18,9 @@ private: public: explicit ZFSFileStoreBackend(FileStore *fs); ~ZFSFileStoreBackend(); + const char *get_name() override { + return "zfs"; + } int detect_features(); bool can_checkpoint(); int create_current(); diff --git a/ceph/src/os/filestore/chain_xattr.cc b/ceph/src/os/filestore/chain_xattr.cc index 0461c1953..97c547e14 100644 --- a/ceph/src/os/filestore/chain_xattr.cc +++ b/ceph/src/os/filestore/chain_xattr.cc @@ -2,29 +2,17 @@ // vim: ts=8 sw=2 smarttab #include "chain_xattr.h" - -#include "include/int_types.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "include/assert.h" +#include // for ERANGE, ENODATA, ENOMEM +#include // for size_t, snprintf +#include // for free, malloc +#include // for strcpy, strlen +#include "include/assert.h" // for assert +#include "include/buffer.h" #if defined(__linux__) #include #endif -#include "common/xattr.h" -#include "include/compat.h" - /* * chaining xattrs * diff --git a/ceph/src/os/filestore/chain_xattr.h b/ceph/src/os/filestore/chain_xattr.h index 9764c3477..7dba7ef93 100644 --- a/ceph/src/os/filestore/chain_xattr.h +++ b/ceph/src/os/filestore/chain_xattr.h @@ -5,13 +5,11 @@ #define __CEPH_OSD_CHAIN_XATTR_H #include "include/compat.h" +#include +#include #include "common/xattr.h" #include "include/assert.h" -#include "include/buffer.h" -#include -#include - -#include +#include "include/buffer_fwd.h" #if defined(__linux__) #include diff --git a/ceph/src/os/fs/aio.h b/ceph/src/os/fs/aio.h index 35d99f2c9..c4757158c 100644 --- a/ceph/src/os/fs/aio.h +++ b/ceph/src/os/fs/aio.h @@ -65,7 +65,14 @@ struct aio_queue_t { int init() { assert(ctx == 0); - return io_setup(max_iodepth, &ctx); + int r = io_setup(max_iodepth, &ctx); + if (r < 0) { + if (ctx) { + io_destroy(ctx); + ctx = 0; + } + } + return r; } void shutdown() { if (ctx) { diff --git a/ceph/src/osd/CMakeLists.txt b/ceph/src/osd/CMakeLists.txt index ecc944b18..670223b6c 100644 --- a/ceph/src/osd/CMakeLists.txt +++ b/ceph/src/osd/CMakeLists.txt @@ -2,6 +2,13 @@ set(osdc_osd_srcs ${CMAKE_SOURCE_DIR}/src/osdc/Objecter.cc ${CMAKE_SOURCE_DIR}/src/osdc/Striper.cc) +if(WITH_OSD_INSTRUMENT_FUNCTIONS AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) + set(GCC_C_FLAGS "-finstrument-functions") + set(GCC_C_FLAGS "${GCC_C_FLAGS} -finstrument-functions-exclude-function-list=_mm_loadu_si128,_mm_cmpeq_epi32,_mm_movemask_epi8") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_C_FLAGS}") + set(osd_cyg_functions_src ${CMAKE_SOURCE_DIR}/src/tracing/cyg_profile_functions.c) +endif() + set(osd_srcs OSD.cc Watch.cc @@ -23,17 +30,16 @@ set(osd_srcs ECUtil.cc ExtentCache.cc ${CMAKE_SOURCE_DIR}/src/common/TrackedOp.cc + ${osd_cyg_functions_src} ${osdc_osd_srcs}) if(HAS_VTA) set_source_files_properties(osdcap.cc PROPERTIES COMPILE_FLAGS -fno-var-tracking-assignments) endif() add_library(osd STATIC ${osd_srcs} - $ $ $ - $ - $) + $) target_link_libraries(osd ${LEVELDB_LIBRARIES} ${CMAKE_DL_LIBS} ${ALLOC_LIBS}) if(WITH_LTTNG) add_dependencies(osd osd-tp pg-tp) @@ -41,3 +47,6 @@ endif() if(WITH_LTTNG AND WITH_EVENTTRACE) add_dependencies(osd eventtrace_tp) endif() +if(WITH_OSD_INSTRUMENT_FUNCTIONS) + add_dependencies(osd cyg_profile_tp) +endif() diff --git a/ceph/src/osd/ECBackend.cc b/ceph/src/osd/ECBackend.cc index 53a8814b2..c35bf1ae2 100644 --- a/ceph/src/osd/ECBackend.cc +++ b/ceph/src/osd/ECBackend.cc @@ -1898,7 +1898,7 @@ bool ECBackend::try_reads_to_commit() op->plan, ec_impl, get_parent()->get_info().pgid.pgid, - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN), + (get_osdmap()->require_osd_release < CEPH_RELEASE_KRAKEN), sinfo, op->remote_read_result, op->log_entries, @@ -2030,7 +2030,7 @@ bool ECBackend::try_finish_rmw() if (op->version > committed_to) committed_to = op->version; - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_KRAKEN) { if (op->version > get_parent()->get_log().get_can_rollback_to() && waiting_reads.empty() && waiting_commit.empty()) { diff --git a/ceph/src/osd/ECTransaction.cc b/ceph/src/osd/ECTransaction.cc index 311977866..b23174f67 100644 --- a/ceph/src/osd/ECTransaction.cc +++ b/ceph/src/osd/ECTransaction.cc @@ -166,10 +166,10 @@ void ECTransaction::generate_transactions( if (entry && entry->is_modify() && op.updated_snaps) { - vector snaps( - op.updated_snaps->second.begin(), - op.updated_snaps->second.end()); - ::encode(snaps, entry->snaps); + bufferlist bl(op.updated_snaps->second.size() * 8 + 8); + ::encode(op.updated_snaps->second, bl); + entry->snaps.swap(bl); + entry->snaps.reassign_to_mempool(mempool::mempool_osd_pglog); } ldpp_dout(dpp, 20) << "generate_transactions: " diff --git a/ceph/src/osd/ECTransaction.h b/ceph/src/osd/ECTransaction.h index 346dcd146..036c8ca8d 100644 --- a/ceph/src/osd/ECTransaction.h +++ b/ceph/src/osd/ECTransaction.h @@ -98,6 +98,7 @@ namespace ECTransaction { raw_write_set.insert(extent.get_off(), extent.get_len()); } + auto orig_size = projected_size; for (auto extent = raw_write_set.begin(); extent != raw_write_set.end(); ++extent) { @@ -109,9 +110,12 @@ namespace ECTransaction { head_start = projected_size; } if (head_start != head_finish && - head_start < projected_size) { - assert(head_finish <= projected_size); + head_start < orig_size) { + assert(head_finish <= orig_size); assert(head_finish - head_start == sinfo.get_stripe_width()); + ldpp_dout(dpp, 20) << __func__ << ": reading partial head stripe " + << head_start << "~" << sinfo.get_stripe_width() + << dendl; plan.to_read[i.first].union_insert( head_start, sinfo.get_stripe_width()); } @@ -124,9 +128,12 @@ namespace ECTransaction { extent.get_start() + extent.get_len()); if (tail_start != tail_finish && (head_start == head_finish || tail_start != head_start) && - tail_start < projected_size) { - assert(tail_finish <= projected_size); + tail_start < orig_size) { + assert(tail_finish <= orig_size); assert(tail_finish - tail_start == sinfo.get_stripe_width()); + ldpp_dout(dpp, 20) << __func__ << ": reading partial tail stripe " + << tail_start << "~" << sinfo.get_stripe_width() + << dendl; plan.to_read[i.first].union_insert( tail_start, sinfo.get_stripe_width()); } @@ -152,7 +159,8 @@ namespace ECTransaction { ldpp_dout(dpp, 20) << __func__ << ": truncating out to " << truncating_to << dendl; - will_write.union_insert(projected_size, truncating_to - projected_size); + will_write.union_insert(projected_size, + truncating_to - projected_size); projected_size = truncating_to; } diff --git a/ceph/src/osd/ECUtil.cc b/ceph/src/osd/ECUtil.cc index 6e046526e..9c3c7981e 100644 --- a/ceph/src/osd/ECUtil.cc +++ b/ceph/src/osd/ECUtil.cc @@ -3,6 +3,7 @@ #include #include "include/encoding.h" #include "ECUtil.h" +using namespace std; int ECUtil::decode( const stripe_info_t &sinfo, diff --git a/ceph/src/osd/ECUtil.h b/ceph/src/osd/ECUtil.h index 4ca6f550b..1b00a095f 100644 --- a/ceph/src/osd/ECUtil.h +++ b/ceph/src/osd/ECUtil.h @@ -15,10 +15,6 @@ #ifndef ECUTIL_H #define ECUTIL_H -#include -#include - -#include "include/memory.h" #include "erasure-code/ErasureCodeInterface.h" #include "include/buffer_fwd.h" #include "include/assert.h" @@ -72,43 +68,43 @@ public: assert(offset % chunk_size == 0); return (offset / chunk_size) * stripe_width; } - pair aligned_offset_len_to_chunk( - pair in) const { - return make_pair( + std::pair aligned_offset_len_to_chunk( + std::pair in) const { + return std::make_pair( aligned_logical_offset_to_chunk_offset(in.first), aligned_logical_offset_to_chunk_offset(in.second)); } - pair offset_len_to_stripe_bounds( - pair in) const { + std::pair offset_len_to_stripe_bounds( + std::pair in) const { uint64_t off = logical_to_prev_stripe_offset(in.first); uint64_t len = logical_to_next_stripe_offset( (in.first - off) + in.second); - return make_pair(off, len); + return std::make_pair(off, len); } }; int decode( const stripe_info_t &sinfo, ErasureCodeInterfaceRef &ec_impl, - map &to_decode, + std::map &to_decode, bufferlist *out); int decode( const stripe_info_t &sinfo, ErasureCodeInterfaceRef &ec_impl, - map &to_decode, - map &out); + std::map &to_decode, + std::map &out); int encode( const stripe_info_t &sinfo, ErasureCodeInterfaceRef &ec_impl, bufferlist &in, - const set &want, - map *out); + const std::set &want, + std::map *out); class HashInfo { uint64_t total_chunk_size = 0; - vector cumulative_shard_hashes; + std::vector cumulative_shard_hashes; // purely ephemeral, represents the size once all in-flight ops commit uint64_t projected_total_chunk_size = 0; @@ -116,17 +112,17 @@ public: HashInfo() {} explicit HashInfo(unsigned num_chunks) : cumulative_shard_hashes(num_chunks, -1) {} - void append(uint64_t old_size, map &to_append); + void append(uint64_t old_size, std::map &to_append); void clear() { total_chunk_size = 0; - cumulative_shard_hashes = vector( + cumulative_shard_hashes = std::vector( cumulative_shard_hashes.size(), -1); } void encode(bufferlist &bl) const; void decode(bufferlist::iterator &bl); void dump(Formatter *f) const; - static void generate_test_instances(list& o); + static void generate_test_instances(std::list& o); uint32_t get_chunk_hash(int shard) const { assert((unsigned)shard < cumulative_shard_hashes.size()); return cumulative_shard_hashes[shard]; @@ -168,8 +164,8 @@ public: typedef ceph::shared_ptr HashInfoRef; -bool is_hinfo_key_string(const string &key); -const string &get_hinfo_key(); +bool is_hinfo_key_string(const std::string &key); +const std::string &get_hinfo_key(); } WRITE_CLASS_ENCODER(ECUtil::HashInfo) diff --git a/ceph/src/osd/OSD.cc b/ceph/src/osd/OSD.cc index e6d18ecd2..fb77b0777 100644 --- a/ceph/src/osd/OSD.cc +++ b/ceph/src/osd/OSD.cc @@ -256,6 +256,8 @@ OSDService::OSDService(OSD *osd) : next_notif_id(0), recovery_request_lock("OSDService::recovery_request_lock"), recovery_request_timer(cct, recovery_request_lock, false), + recovery_sleep_lock("OSDService::recovery_sleep_lock"), + recovery_sleep_timer(cct, recovery_sleep_lock, false), reserver_finisher(cct), local_reserver(&reserver_finisher, cct->_conf->osd_max_backfills, cct->_conf->osd_min_recovery_priority), @@ -265,6 +267,9 @@ OSDService::OSDService(OSD *osd) : snap_sleep_lock("OSDService::snap_sleep_lock"), snap_sleep_timer( osd->client_messenger->cct, snap_sleep_lock, false /* relax locking */), + scrub_sleep_lock("OSDService::scrub_sleep_lock"), + scrub_sleep_timer( + osd->client_messenger->cct, scrub_sleep_lock, false /* relax locking */), snap_reserver(&reserver_finisher, cct->_conf->osd_max_trimming_pgs), recovery_lock("OSDService::recovery_lock"), @@ -295,6 +300,41 @@ OSDService::~OSDService() delete objecter; } + + +#ifdef PG_DEBUG_REFS +void OSDService::add_pgid(spg_t pgid, PG *pg){ + Mutex::Locker l(pgid_lock); + if (!pgid_tracker.count(pgid)) { + live_pgs[pgid] = pg; + } + pgid_tracker[pgid]++; +} +void OSDService::remove_pgid(spg_t pgid, PG *pg) +{ + Mutex::Locker l(pgid_lock); + assert(pgid_tracker.count(pgid)); + assert(pgid_tracker[pgid] > 0); + pgid_tracker[pgid]--; + if (pgid_tracker[pgid] == 0) { + pgid_tracker.erase(pgid); + live_pgs.erase(pgid); + } +} +void OSDService::dump_live_pgids() +{ + Mutex::Locker l(pgid_lock); + derr << "live pgids:" << dendl; + for (map::const_iterator i = pgid_tracker.cbegin(); + i != pgid_tracker.cend(); + ++i) { + derr << "\t" << *i << dendl; + live_pgs[i->first]->dump_live_ids(); + } +} +#endif + + void OSDService::_start_split(spg_t parent, const set &children) { for (set::const_iterator i = children.begin(); @@ -478,12 +518,21 @@ void OSDService::start_shutdown() Mutex::Locker l(agent_timer_lock); agent_timer.shutdown(); } + + { + Mutex::Locker l(recovery_sleep_lock); + recovery_sleep_timer.shutdown(); + } } -void OSDService::shutdown() +void OSDService::shutdown_reserver() { reserver_finisher.wait_for_empty(); reserver_finisher.stop(); +} + +void OSDService::shutdown() +{ { Mutex::Locker l(watch_lock); watch_timer.shutdown(); @@ -503,6 +552,11 @@ void OSDService::shutdown() snap_sleep_timer.shutdown(); } + { + Mutex::Locker l(scrub_sleep_lock); + scrub_sleep_timer.shutdown(); + } + osdmap = OSDMapRef(); next_osdmap = OSDMapRef(); } @@ -519,6 +573,7 @@ void OSDService::init() watch_timer.init(); agent_timer.init(); snap_sleep_timer.init(); + scrub_sleep_timer.init(); agent_thread.create("osd_srv_agent"); @@ -732,7 +787,7 @@ void OSDService::check_full_status(const osd_stat_t &osd_stat) float full_ratio = std::max(osdmap->get_full_ratio(), backfillfull_ratio); float failsafe_ratio = std::max(get_failsafe_full_ratio(), full_ratio); - if (!osdmap->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (osdmap->require_osd_release < CEPH_RELEASE_LUMINOUS) { // use the failsafe for nearfull and full; the mon isn't using the // flags anyway because we're mid-upgrade. full_ratio = failsafe_ratio; @@ -1395,12 +1450,19 @@ void OSDService::send_incremental_map(epoch_t since, Connection *con, bool OSDService::_get_map_bl(epoch_t e, bufferlist& bl) { bool found = map_bl_cache.lookup(e, &bl); - if (found) + if (found) { + if (logger) + logger->inc(l_osd_map_bl_cache_hit); return true; + } + if (logger) + logger->inc(l_osd_map_bl_cache_miss); found = store->read(coll_t::meta(), - OSD::get_osdmap_pobject_name(e), 0, 0, bl) >= 0; - if (found) + OSD::get_osdmap_pobject_name(e), 0, 0, bl, + CEPH_OSD_OP_FLAG_FADVISE_WILLNEED) >= 0; + if (found) { _add_map_bl(e, bl); + } return found; } @@ -1408,36 +1470,61 @@ bool OSDService::get_inc_map_bl(epoch_t e, bufferlist& bl) { Mutex::Locker l(map_cache_lock); bool found = map_bl_inc_cache.lookup(e, &bl); - if (found) + if (found) { + if (logger) + logger->inc(l_osd_map_bl_cache_hit); return true; + } + if (logger) + logger->inc(l_osd_map_bl_cache_miss); found = store->read(coll_t::meta(), - OSD::get_inc_osdmap_pobject_name(e), 0, 0, bl) >= 0; - if (found) + OSD::get_inc_osdmap_pobject_name(e), 0, 0, bl, + CEPH_OSD_OP_FLAG_FADVISE_WILLNEED) >= 0; + if (found) { _add_map_inc_bl(e, bl); + } return found; } void OSDService::_add_map_bl(epoch_t e, bufferlist& bl) { dout(10) << "add_map_bl " << e << " " << bl.length() << " bytes" << dendl; + // cache a contiguous buffer + if (bl.get_num_buffers() > 1) { + bl.rebuild(); + } + bl.try_assign_to_mempool(mempool::mempool_osd_mapbl); map_bl_cache.add(e, bl); } void OSDService::_add_map_inc_bl(epoch_t e, bufferlist& bl) { dout(10) << "add_map_inc_bl " << e << " " << bl.length() << " bytes" << dendl; + // cache a contiguous buffer + if (bl.get_num_buffers() > 1) { + bl.rebuild(); + } + bl.try_assign_to_mempool(mempool::mempool_osd_mapbl); map_bl_inc_cache.add(e, bl); } void OSDService::pin_map_inc_bl(epoch_t e, bufferlist &bl) { Mutex::Locker l(map_cache_lock); + // cache a contiguous buffer + if (bl.get_num_buffers() > 1) { + bl.rebuild(); + } map_bl_inc_cache.pin(e, bl); } void OSDService::pin_map_bl(epoch_t e, bufferlist &bl) { Mutex::Locker l(map_cache_lock); + // cache a contiguous buffer + if (bl.get_num_buffers() > 1) { + bl.rebuild(); + } map_bl_cache.pin(e, bl); } @@ -1528,6 +1615,10 @@ void OSDService::reply_op_error(OpRequestRef op, int err, eversion_t v, void OSDService::handle_misdirected_op(PG *pg, OpRequestRef op) { + if (!cct->_conf->osd_debug_misdirected_ops) { + return; + } + const MOSDOp *m = static_cast(op->get_req()); assert(m->get_type() == CEPH_MSG_OSD_OP); @@ -1575,9 +1666,6 @@ void OSDService::handle_misdirected_op(PG *pg, OpRequestRef op) << " to osd." << whoami << " not " << pg->acting << " in e" << m->get_map_epoch() << "/" << osdmap->get_epoch(); - if (g_conf->osd_enxio_on_misdirected_op) { - reply_op_error(op, -ENXIO); - } } void OSDService::enqueue_back(spg_t pgid, PGQueueable qi) @@ -1645,7 +1733,7 @@ int OSD::mkfs(CephContext *cct, ObjectStore *store, const string &dev, goto free_store; } - store->set_cache_shards(cct->_conf->osd_op_num_shards); + store->set_cache_shards(1); // doesn't matter for mkfs! ret = store->mount(); if (ret) { @@ -1813,12 +1901,15 @@ OSD::OSD(CephContext *cct_, ObjectStore *store_, clog(log_client.create_channel()), whoami(id), dev_path(dev), journal_path(jdev), + store_is_rotational(store->is_rotational()), trace_endpoint("0.0.0.0", 0, "osd"), asok_hook(NULL), osd_compat(get_osd_compat_set()), - osd_tp(cct, "OSD::osd_tp", "tp_osd", cct->_conf->osd_op_threads, "osd_op_threads"), + peering_tp(cct, "OSD::peering_tp", "tp_peering", + cct->_conf->osd_peering_wq_threads, + "osd_peering_tp_threads"), osd_op_tp(cct, "OSD::osd_op_tp", "tp_osd_tp", - cct->_conf->osd_op_num_threads_per_shard * cct->_conf->osd_op_num_shards), + get_num_op_threads()), disk_tp(cct, "OSD::disk_tp", "tp_osd_disk", cct->_conf->osd_disk_threads, "osd_disk_threads"), command_tp(cct, "OSD::command_tp", "tp_osd_cmd", 1), session_waiting_lock("OSD::session_waiting_lock"), @@ -1838,7 +1929,7 @@ OSD::OSD(CephContext *cct_, ObjectStore *store_, op_queue(get_io_queue()), op_prio_cutoff(get_io_prio_cut()), op_shardedwq( - cct->_conf->osd_op_num_shards, + get_num_op_shards(), this, cct->_conf->osd_op_thread_timeout, cct->_conf->osd_op_thread_suicide_timeout, @@ -1847,7 +1938,7 @@ OSD::OSD(CephContext *cct_, ObjectStore *store_, this, cct->_conf->osd_op_thread_timeout, cct->_conf->osd_op_thread_suicide_timeout, - &osd_tp), + &peering_tp), map_lock("OSD::map_lock"), pg_map_lock("OSD::pg_map_lock"), last_pg_create_epoch(0), @@ -2215,6 +2306,26 @@ int OSD::enable_disable_fuse(bool stop) return 0; } +int OSD::get_num_op_shards() +{ + if (cct->_conf->osd_op_num_shards) + return cct->_conf->osd_op_num_shards; + if (store_is_rotational) + return cct->_conf->osd_op_num_shards_hdd; + else + return cct->_conf->osd_op_num_shards_ssd; +} + +int OSD::get_num_op_threads() +{ + if (cct->_conf->osd_op_num_threads_per_shard) + return get_num_op_shards() * cct->_conf->osd_op_num_threads_per_shard; + if (store_is_rotational) + return get_num_op_shards() * cct->_conf->osd_op_num_threads_per_shard_hdd; + else + return get_num_op_shards() * cct->_conf->osd_op_num_threads_per_shard_ssd; +} + int OSD::init() { CompatSet initial, diff; @@ -2225,13 +2336,15 @@ int OSD::init() tick_timer.init(); tick_timer_without_osd_lock.init(); service.recovery_request_timer.init(); + service.recovery_sleep_timer.init(); // mount. - dout(2) << "mounting " << dev_path << " " - << (journal_path.empty() ? "(no journal)" : journal_path) << dendl; + dout(2) << "init " << dev_path + << " (looks like " << (store_is_rotational ? "hdd" : "ssd") << ")" + << dendl; assert(store); // call pre_init() first! - store->set_cache_shards(cct->_conf->osd_op_num_shards); + store->set_cache_shards(get_num_op_shards()); int r = store->mount(); if (r < 0) { @@ -2438,7 +2551,7 @@ int OSD::init() monc->set_log_client(&log_client); update_log_config(); - osd_tp.start(); + peering_tp.start(); osd_op_tp.start(); disk_tp.start(); command_tp.start(); @@ -2797,7 +2910,7 @@ void OSD::create_logger() osd_plb.add_time_avg( l_osd_op_r_lat, "op_r_latency", "Latency of read operation (including queue time)"); - osd_plb.add_histogram( + osd_plb.add_u64_counter_histogram( l_osd_op_r_lat_outb_hist, "op_r_latency_out_bytes_histogram", op_hist_x_axis_config, op_hist_y_axis_config, "Histogram of operation latency (including queue time) + data read"); @@ -2814,7 +2927,7 @@ void OSD::create_logger() osd_plb.add_time_avg( l_osd_op_w_lat, "op_w_latency", "Latency of write operation (including queue time)"); - osd_plb.add_histogram( + osd_plb.add_u64_counter_histogram( l_osd_op_w_lat_inb_hist, "op_w_latency_in_bytes_histogram", op_hist_x_axis_config, op_hist_y_axis_config, "Histogram of operation latency (including queue time) + data written"); @@ -2836,11 +2949,11 @@ void OSD::create_logger() osd_plb.add_time_avg( l_osd_op_rw_lat, "op_rw_latency", "Latency of read-modify-write operation (including queue time)"); - osd_plb.add_histogram( + osd_plb.add_u64_counter_histogram( l_osd_op_rw_lat_inb_hist, "op_rw_latency_in_bytes_histogram", op_hist_x_axis_config, op_hist_y_axis_config, "Histogram of rw operation latency (including queue time) + data written"); - osd_plb.add_histogram( + osd_plb.add_u64_counter_histogram( l_osd_op_rw_lat_outb_hist, "op_rw_latency_out_bytes_histogram", op_hist_x_axis_config, op_hist_y_axis_config, "Histogram of rw operation latency (including queue time) + data read"); @@ -2914,6 +3027,7 @@ void OSD::create_logger() osd_plb.add_u64_counter( l_osd_waiting_for_map, "messages_delayed_for_map", "Operations waiting for OSD map"); + osd_plb.add_u64_counter( l_osd_map_cache_hit, "osd_map_cache_hit", "osdmap cache hit"); osd_plb.add_u64_counter( @@ -2924,6 +3038,12 @@ void OSD::create_logger() osd_plb.add_u64_avg( l_osd_map_cache_miss_low_avg, "osd_map_cache_miss_low_avg", "osdmap cache miss, avg distance below cache lower bound"); + osd_plb.add_u64_counter( + l_osd_map_bl_cache_hit, "osd_map_bl_cache_hit", + "OSDMap buffer cache hits"); + osd_plb.add_u64_counter( + l_osd_map_bl_cache_miss, "osd_map_bl_cache_miss", + "OSDMap buffer cache misses"); osd_plb.add_u64(l_osd_stat_bytes, "stat_bytes", "OSD size"); osd_plb.add_u64(l_osd_stat_bytes_used, "stat_bytes_used", "Used space"); @@ -3126,9 +3246,9 @@ int OSD::shutdown() heartbeat_lock.Unlock(); heartbeat_thread.join(); - osd_tp.drain(); + peering_tp.drain(); peering_wq.clear(); - osd_tp.stop(); + peering_tp.stop(); dout(10) << "osd tp stopped" << dendl; osd_op_tp.drain(); @@ -3175,6 +3295,8 @@ int OSD::shutdown() assert(pg_stat_queue.empty()); } + service.shutdown_reserver(); + // Remove PGs #ifdef PG_DEBUG_REFS service.dump_live_pgids(); @@ -3192,7 +3314,9 @@ int OSD::shutdown() #ifdef PG_DEBUG_REFS p->second->dump_live_ids(); #endif - ceph_abort(); + if (cct->_conf->osd_shutdown_pgref_assert) { + ceph_abort(); + } } p->second->unlock(); p->second->put("PGMap"); @@ -3644,6 +3768,11 @@ PG *OSD::_lookup_lock_pg(spg_t pgid) return pg; } +PG *OSD::lookup_lock_pg(spg_t pgid) +{ + return _lookup_lock_pg(pgid); +} + PG *OSD::_lookup_lock_pg_with_map_lock_held(spg_t pgid) { assert(pg_map.count(pgid)); @@ -4164,6 +4293,7 @@ void OSD::build_initial_pg_history( { dout(10) << __func__ << " " << pgid << " created " << created << dendl; h->epoch_created = created; + h->epoch_pool_created = created; h->same_interval_since = created; h->same_up_since = created; h->same_primary_since = created; @@ -4306,7 +4436,7 @@ bool OSD::project_pg_history(spg_t pgid, pg_history_t& h, epoch_t from, break; } - // base case: these floors should be the creation epoch if we didn't + // base case: these floors should be the pg creation epoch if we didn't // find any changes. if (e == h.epoch_created) { if (!h.same_interval_since) @@ -4563,8 +4693,8 @@ void OSD::handle_osd_ping(MOSDPing *m) Message *r = new MOSDPing(monc->get_fsid(), curmap->get_epoch(), - MOSDPing::PING_REPLY, - m->stamp); + MOSDPing::PING_REPLY, m->stamp, + cct->_conf->osd_heartbeat_min_size); m->get_connection()->send_message(r); if (curmap->is_up(from)) { @@ -4581,7 +4711,8 @@ void OSD::handle_osd_ping(MOSDPing *m) Message *r = new MOSDPing(monc->get_fsid(), curmap->get_epoch(), MOSDPing::YOU_DIED, - m->stamp); + m->stamp, + cct->_conf->osd_heartbeat_min_size); m->get_connection()->send_message(r); } } @@ -4759,14 +4890,14 @@ void OSD::heartbeat() dout(30) << "heartbeat sending ping to osd." << peer << dendl; i->second.con_back->send_message(new MOSDPing(monc->get_fsid(), service.get_osdmap()->get_epoch(), - MOSDPing::PING, - now)); + MOSDPing::PING, now, + cct->_conf->osd_heartbeat_min_size)); if (i->second.con_front) i->second.con_front->send_message(new MOSDPing(monc->get_fsid(), service.get_osdmap()->get_epoch(), - MOSDPing::PING, - now)); + MOSDPing::PING, now, + cct->_conf->osd_heartbeat_min_size)); } logger->set(l_osd_hb_to, heartbeat_peers.size()); @@ -4935,7 +5066,9 @@ void OSD::tick_without_osd_lock() // do any pending reports send_full_update(); send_failures(); - send_pg_stats(now); + if (osdmap->require_osd_release < CEPH_RELEASE_LUMINOUS) { + send_pg_stats(now); + } } map_lock.put_read(); } @@ -5325,7 +5458,9 @@ void OSD::ms_handle_connect(Connection *con) service.send_pg_temp(); requeue_failures(); send_failures(); - send_pg_stats(now); + if (osdmap->require_osd_release < CEPH_RELEASE_LUMINOUS) { + send_pg_stats(now); + } map_lock.put_read(); if (is_active()) { @@ -5472,12 +5607,14 @@ void OSD::_preboot(epoch_t oldest, epoch_t newest) heartbeat(); // if our map within recent history, try to add ourselves to the osdmap. - if (osdmap->test_flag(CEPH_OSDMAP_NOUP)) { + if (osdmap->get_epoch() == 0) { + derr << "waiting for initial osdmap" << dendl; + } else if (osdmap->test_flag(CEPH_OSDMAP_NOUP) || osdmap->is_noup(whoami)) { derr << "osdmap NOUP flag is set, waiting for it to clear" << dendl; } else if (!osdmap->test_flag(CEPH_OSDMAP_SORTBITWISE)) { derr << "osdmap SORTBITWISE OSDMap flag is NOT set; please set it" << dendl; - } else if (!osdmap->test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + } else if (osdmap->require_osd_release < CEPH_RELEASE_JEWEL) { derr << "osdmap REQUIRE_JEWEL OSDMap flag is NOT set; please set it" << dendl; } else if (!monc->monmap.get_required_features().contains_all( @@ -5630,6 +5767,7 @@ void OSD::_collect_metadata(map *pm) // backend (*pm)["osd_objectstore"] = store->get_type(); + (*pm)["rotational"] = store_is_rotational ? "1" : "0"; store->collect_metadata(pm); collect_sys_info(pm, cct); @@ -5746,8 +5884,8 @@ void OSD::send_failures() utime_t now = ceph_clock_now(); while (!failure_queue.empty()) { int osd = failure_queue.begin()->first; - entity_inst_t i = osdmap->get_inst(osd); if (!failure_pending.count(osd)) { + entity_inst_t i = osdmap->get_inst(osd); int failed_for = (int)(double)(now - failure_queue.begin()->second); monc->send_mon_message(new MOSDFailure(monc->get_fsid(), i, failed_for, osdmap->get_epoch())); @@ -5766,6 +5904,7 @@ void OSD::send_still_alive(epoch_t epoch, const entity_inst_t &i) void OSD::send_pg_stats(const utime_t &now) { assert(map_lock.is_locked()); + assert(osdmap->require_osd_release < CEPH_RELEASE_LUMINOUS); dout(20) << "send_pg_stats" << dendl; osd_stat_t cur_stat = service.get_osd_stat(); @@ -6012,6 +6151,11 @@ COMMAND("list_missing " \ "name=offset,type=CephString,req=false", "list missing objects on this pg, perhaps starting at an offset given in JSON", "osd", "r", "cli,rest") +COMMAND("perf histogram dump " + "name=logger,type=CephString,req=false " + "name=counter,type=CephString,req=false", + "Get histogram data", + "osd", "r", "cli,rest") // tell commands. Validation of osd.n must be special-cased in client COMMAND("version", "report version of OSD", "osd", "r", "cli,rest") @@ -6361,7 +6505,12 @@ void OSD::do_command(Connection *con, ceph_tid_t tid, vector& cmd, buffe } else if (prefix == "flush_pg_stats") { - flush_pg_stats(); + if (osdmap->require_osd_release >= CEPH_RELEASE_LUMINOUS) { + mgrc.send_pgstats(); + ds << service.get_osd_stat_seq() << "\n"; + } else { + flush_pg_stats(); + } } else if (prefix == "heap") { @@ -6448,6 +6597,18 @@ void OSD::do_command(Connection *con, ceph_tid_t tid, vector& cmd, buffe pg_recovery_stats.reset(); } + else if (prefix == "perf histogram dump") { + std::string logger; + std::string counter; + cmd_getval(cct, cmdmap, "logger", logger); + cmd_getval(cct, cmdmap, "counter", counter); + if (f) { + cct->get_perfcounters_collection()->dump_formatted_histograms( + f.get(), false, logger, counter); + f->flush(ds); + } + } + else { ss << "unrecognized command! " << cmd; r = -EINVAL; @@ -6654,6 +6815,11 @@ bool OSD::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool for { dout(10) << "OSD::ms_get_authorizer type=" << ceph_entity_type_name(dest_type) << dendl; + if (is_stopping()) { + dout(10) << __func__ << " bailing, we are shutting down" << dendl; + return false; + } + if (dest_type == CEPH_ENTITY_TYPE_MON) return true; @@ -7364,12 +7530,6 @@ void OSD::handle_osd_map(MOSDMap *m) rerequest_full_maps(); } - if (last <= superblock.newest_map) { - dout(10) << " no new maps here, dropping" << dendl; - m->put(); - return; - } - if (superblock.oldest_map) { // make sure we at least keep pace with incoming maps trim_maps(m->oldest_map, last - first + 1, skip_maps); @@ -7405,6 +7565,10 @@ void OSD::_committed_osd_maps(epoch_t first, epoch_t last, MOSDMap *m) return; } Mutex::Locker l(osd_lock); + if (is_stopping()) { + dout(10) << __func__ << " bailing, we are shutting down" << dendl; + return; + } map_lock.get_write(); bool do_shutdown = false; @@ -7444,8 +7608,9 @@ void OSD::_committed_osd_maps(epoch_t first, epoch_t last, MOSDMap *m) } } - if (osdmap->test_flag(CEPH_OSDMAP_NOUP) != - newmap->test_flag(CEPH_OSDMAP_NOUP)) { + if ((osdmap->test_flag(CEPH_OSDMAP_NOUP) != + newmap->test_flag(CEPH_OSDMAP_NOUP)) || + (osdmap->is_noup(whoami) != newmap->is_noup(whoami))) { dout(10) << __func__ << " NOUP flag changed in " << newmap->get_epoch() << dendl; if (is_booting()) { @@ -7458,6 +7623,13 @@ void OSD::_committed_osd_maps(epoch_t first, epoch_t last, MOSDMap *m) do_restart = true; } } + if (osdmap->require_osd_release < CEPH_RELEASE_LUMINOUS && + newmap->require_osd_release >= CEPH_RELEASE_LUMINOUS) { + dout(10) << __func__ << " require_osd_release reached luminous in " + << newmap->get_epoch() << dendl; + clear_pg_stat_queue(); + outstanding_pg_stats.clear(); + } osdmap = newmap; epoch_t up_epoch; @@ -7632,12 +7804,7 @@ void OSD::_committed_osd_maps(epoch_t first, epoch_t last, MOSDMap *m) activate_map(); } - if (m->newest_map && m->newest_map > last) { - dout(10) << " msg say newest map is " << m->newest_map - << ", requesting more" << dendl; - osdmap_subscribe(osdmap->get_epoch()+1, false); - } - else if (do_shutdown) { + if (do_shutdown) { if (network_error) { Mutex::Locker l(heartbeat_lock); map>::iterator it = @@ -7653,6 +7820,11 @@ void OSD::_committed_osd_maps(epoch_t first, epoch_t last, MOSDMap *m) dout(0) << __func__ << " shutdown OSD via async signal" << dendl; queue_async_signal(SIGINT); } + else if (m->newest_map && m->newest_map > last) { + dout(10) << " msg say newest map is " << m->newest_map + << ", requesting more" << dendl; + osdmap_subscribe(osdmap->get_epoch()+1, false); + } else if (is_preboot()) { if (m->get_source().is_mon()) _preboot(m->oldest_map, m->newest_map); @@ -7726,7 +7898,7 @@ bool OSD::advance_pg( epoch_t osd_epoch, PG *pg, ThreadPool::TPHandle &handle, PG::RecoveryCtx *rctx, - set > *new_pgs) + set *new_pgs) { assert(pg->is_locked()); epoch_t next_epoch = pg->get_osdmap()->get_epoch() + 1; @@ -8031,7 +8203,7 @@ bool OSD::require_same_or_newer_map(OpRequestRef& op, epoch_t epoch, void OSD::split_pgs( PG *parent, - const set &childpgids, set > *out_pgs, + const set &childpgids, set *out_pgs, OSDMapRef curmap, OSDMapRef nextmap, PG::RecoveryCtx *rctx) @@ -8881,18 +9053,41 @@ void OSD::do_recovery( ThreadPool::TPHandle &handle) { uint64_t started = 0; - if (cct->_conf->osd_recovery_sleep > 0) { - handle.suspend_tp_timeout(); - pg->unlock(); - utime_t t; - t.set_from_double(cct->_conf->osd_recovery_sleep); - t.sleep(); - dout(20) << __func__ << " slept for " << t << dendl; - pg->lock(); - handle.reset_tp_timeout(); + + /* + * When the value of osd_recovery_sleep is set greater than zero, recovery + * ops are scheduled after osd_recovery_sleep amount of time from the previous + * recovery event's schedule time. This is done by adding a + * recovery_requeue_callback event, which re-queues the recovery op using + * queue_recovery_after_sleep. + */ + if (cct->_conf->osd_recovery_sleep > 0 && service.recovery_needs_sleep) { + PGRef pgref(pg); + auto recovery_requeue_callback = new FunctionContext([this, pgref, queued, reserved_pushes](int r) { + dout(20) << "do_recovery wake up at " + << ceph_clock_now() + << ", re-queuing recovery" << dendl; + service.recovery_needs_sleep = false; + service.queue_recovery_after_sleep(pgref.get(), queued, reserved_pushes); + }); + Mutex::Locker l(service.recovery_sleep_lock); + + // This is true for the first recovery op and when the previous recovery op + // has been scheduled in the past. The next recovery op is scheduled after + // completing the sleep from now. + if (service.recovery_schedule_time < ceph_clock_now()) { + service.recovery_schedule_time = ceph_clock_now(); + } + service.recovery_schedule_time += cct->_conf->osd_recovery_sleep; + service.recovery_sleep_timer.add_event_at(service.recovery_schedule_time, + recovery_requeue_callback); + dout(20) << "Recovery event scheduled at " + << service.recovery_schedule_time << dendl; + return; } { + service.recovery_needs_sleep = true; if (pg->pg_has_reset_since(queued)) { goto out; } @@ -9063,27 +9258,28 @@ void OSD::dequeue_op( struct C_CompleteSplits : public Context { OSD *osd; - set > pgs; - C_CompleteSplits(OSD *osd, const set > &in) + set pgs; + C_CompleteSplits(OSD *osd, const set &in) : osd(osd), pgs(in) {} void finish(int r) override { Mutex::Locker l(osd->osd_lock); if (osd->is_stopping()) return; PG::RecoveryCtx rctx = osd->create_context(); - for (set >::iterator i = pgs.begin(); + for (set::iterator i = pgs.begin(); i != pgs.end(); ++i) { osd->pg_map_lock.get_write(); (*i)->lock(); - osd->add_newly_split_pg(&**i, &rctx); + PG *pg = i->get(); + osd->add_newly_split_pg(pg, &rctx); if (!((*i)->deleting)) { set to_complete; to_complete.insert((*i)->info.pgid); osd->service.complete_split(to_complete); } osd->pg_map_lock.put_write(); - osd->dispatch_context_transaction(rctx, &**i); + osd->dispatch_context_transaction(rctx, pg); osd->wake_pg_waiters(*i); (*i)->unlock(); } @@ -9105,7 +9301,7 @@ void OSD::process_peering_events( for (list::const_iterator i = pgs.begin(); i != pgs.end(); ++i) { - set > split_pgs; + set split_pgs; PG *pg = *i; pg->lock_suspend_timeout(handle); curmap = service.get_osdmap(); @@ -9170,6 +9366,8 @@ const char** OSD::get_tracked_conf_keys() const "osd_recovery_delay_start", "osd_client_message_size_cap", "osd_client_message_cap", + "osd_heartbeat_min_size", + "osd_heartbeat_interval", NULL }; return KEYS; diff --git a/ceph/src/osd/OSD.h b/ceph/src/osd/OSD.h index cad51ed92..12a9d774c 100644 --- a/ceph/src/osd/OSD.h +++ b/ceph/src/osd/OSD.h @@ -131,6 +131,8 @@ enum { l_osd_map_cache_miss, l_osd_map_cache_miss_low, l_osd_map_cache_miss_low_avg, + l_osd_map_bl_cache_hit, + l_osd_map_bl_cache_miss, l_osd_stat_bytes, l_osd_stat_bytes_used, @@ -923,6 +925,13 @@ public: Mutex recovery_request_lock; SafeTimer recovery_request_timer; + // For async recovery sleep + bool recovery_needs_sleep = true; + utime_t recovery_schedule_time = utime_t(); + + Mutex recovery_sleep_lock; + SafeTimer recovery_sleep_timer; + // -- tids -- // for ops i issue std::atomic_uint last_tid{0}; @@ -954,16 +963,23 @@ public: Mutex snap_sleep_lock; SafeTimer snap_sleep_timer; + Mutex scrub_sleep_lock; + SafeTimer scrub_sleep_timer; + AsyncReserver snap_reserver; void queue_for_snap_trim(PG *pg); - void queue_for_scrub(PG *pg) { + void queue_for_scrub(PG *pg, bool with_high_priority) { + unsigned scrub_queue_priority = pg->scrubber.priority; + if (with_high_priority && scrub_queue_priority < cct->_conf->osd_client_op_priority) { + scrub_queue_priority = cct->_conf->osd_client_op_priority; + } enqueue_back( pg->info.pgid, PGQueueable( PGScrub(pg->get_osdmap()->get_epoch()), cct->_conf->osd_scrub_cost, - pg->scrubber.priority, + scrub_queue_priority, ceph_clock_now(), entity_inst_t(), pg->get_osdmap()->get_epoch())); @@ -1050,6 +1066,10 @@ public: } _maybe_queue_recovery(); } + void queue_recovery_after_sleep(PG *pg, epoch_t queued, uint64_t reserved_pushes) { + Mutex::Locker l(recovery_lock); + _queue_for_recovery(make_pair(queued, pg), reserved_pushes); + } // osd map cache (past osd maps) @@ -1100,6 +1120,7 @@ public: void init(); void final_init(); void start_shutdown(); + void shutdown_reserver(); void shutdown(); private: @@ -1130,12 +1151,20 @@ public: // -- stats -- Mutex stat_lock; osd_stat_t osd_stat; + uint32_t seq = 0; void update_osd_stat(vector& hb_peers); osd_stat_t get_osd_stat() { Mutex::Locker l(stat_lock); + ++seq; + osd_stat.up_from = up_epoch; + osd_stat.seq = ((uint64_t)osd_stat.up_from << 32) + seq; return osd_stat; } + uint64_t get_osd_stat_seq() { + Mutex::Locker l(stat_lock); + return osd_stat.seq; + } // -- OSD Full Status -- private: @@ -1248,33 +1277,9 @@ public: Mutex pgid_lock; map pgid_tracker; map live_pgs; - void add_pgid(spg_t pgid, PG *pg) { - Mutex::Locker l(pgid_lock); - if (!pgid_tracker.count(pgid)) { - live_pgs[pgid] = pg; - } - pgid_tracker[pgid]++; - } - void remove_pgid(spg_t pgid, PG *pg) { - Mutex::Locker l(pgid_lock); - assert(pgid_tracker.count(pgid)); - assert(pgid_tracker[pgid] > 0); - pgid_tracker[pgid]--; - if (pgid_tracker[pgid] == 0) { - pgid_tracker.erase(pgid); - live_pgs.erase(pgid); - } - } - void dump_live_pgids() { - Mutex::Locker l(pgid_lock); - derr << "live pgids:" << dendl; - for (map::const_iterator i = pgid_tracker.cbegin(); - i != pgid_tracker.cend(); - ++i) { - derr << "\t" << *i << dendl; - live_pgs[i->first]->dump_live_ids(); - } - } + void add_pgid(spg_t pgid, PG *pg); + void remove_pgid(spg_t pgid, PG *pg); + void dump_live_pgids(); #endif explicit OSDService(OSD *osd); @@ -1322,6 +1327,8 @@ protected: int whoami; std::string dev_path, journal_path; + bool store_is_rotational = true; + ZTracer::Endpoint trace_endpoint; void create_logger(); void create_recoverystate_perf(); @@ -1472,7 +1479,7 @@ public: private: - ThreadPool osd_tp; + ThreadPool peering_tp; ShardedThreadPool osd_op_tp; ThreadPool disk_tp; ThreadPool command_tp; @@ -1993,7 +2000,7 @@ private: epoch_t advance_to, PG *pg, ThreadPool::TPHandle &handle, PG::RecoveryCtx *rctx, - set > *split_pgs + set *split_pgs ); void consume_map(); void activate_map(); @@ -2033,6 +2040,11 @@ protected: PG *_lookup_lock_pg_with_map_lock_held(spg_t pgid); PG *_lookup_lock_pg(spg_t pgid); + +public: + PG *lookup_lock_pg(spg_t pgid); + +protected: PG *_open_lock_pg(OSDMapRef createmap, spg_t pg, bool no_lockdep_check=false); enum res_result { @@ -2097,7 +2109,7 @@ protected: void split_pgs( PG *parent, - const set &childpgids, set > *out_pgs, + const set &childpgids, set *out_pgs, OSDMapRef curmap, OSDMapRef nextmap, PG::RecoveryCtx *rctx); @@ -2467,6 +2479,9 @@ private: int init_op_flags(OpRequestRef& op); + int get_num_op_shards(); + int get_num_op_threads(); + public: static int peek_meta(ObjectStore *store, string& magic, uuid_d& cluster_fsid, uuid_d& osd_fsid, int& whoami); diff --git a/ceph/src/osd/OSDCap.cc b/ceph/src/osd/OSDCap.cc index c8cfbfab1..25da5e2b6 100644 --- a/ceph/src/osd/OSDCap.cc +++ b/ceph/src/osd/OSDCap.cc @@ -24,7 +24,7 @@ using std::ostream; using std::vector; -ostream& operator<<(ostream& out, osd_rwxa_t p) +ostream& operator<<(ostream& out, const osd_rwxa_t& p) { if (p == OSD_CAP_ANY) return out << "*"; diff --git a/ceph/src/osd/OSDCap.h b/ceph/src/osd/OSDCap.h index 3a1a722aa..8ce808052 100644 --- a/ceph/src/osd/OSDCap.h +++ b/ceph/src/osd/OSDCap.h @@ -54,7 +54,7 @@ struct osd_rwxa_t { } }; -ostream& operator<<(ostream& out, osd_rwxa_t p); +ostream& operator<<(ostream& out, const osd_rwxa_t& p); struct OSDCapSpec { osd_rwxa_t allow; diff --git a/ceph/src/osd/OSDMap.cc b/ceph/src/osd/OSDMap.cc index 5043ff417..594ff82fa 100644 --- a/ceph/src/osd/OSDMap.cc +++ b/ceph/src/osd/OSDMap.cc @@ -27,6 +27,7 @@ #include "crush/CrushTreeDumper.h" #include "common/Clock.h" +#include "mon/PGStatService.h" #define dout_subsys ceph_subsys_osd @@ -293,6 +294,40 @@ bool OSDMap::containing_subtree_is_down(CephContext *cct, int id, int subtree_ty } } +bool OSDMap::subtree_type_is_down(CephContext *cct, int id, int subtree_type, set *down_in_osds, set *up_in_osds, + set *subtree_up, unordered_map > *subtree_type_down) const +{ + if (id >= 0) { + bool is_down_ret = is_down(id); + if (!is_out(id)) { + if (is_down_ret) { + down_in_osds->insert(id); + } else { + up_in_osds->insert(id); + } + } + return is_down_ret; + } + + if (subtree_type_down && + (*subtree_type_down)[subtree_type].count(id)) { + return true; + } + + list children; + crush->get_children(id, &children); + for (const auto &child : children) { + if (!subtree_type_is_down(cct, child, crush->get_bucket_type(child), down_in_osds, up_in_osds, subtree_up, subtree_type_down)) { + subtree_up->insert(id); + return false; + } + } + if (subtree_type_down) { + (*subtree_type_down)[subtree_type].insert(id); + } + return true; +} + void OSDMap::Incremental::encode_client_old(bufferlist& bl) const { __u16 v = 5; @@ -332,7 +367,15 @@ void OSDMap::Incremental::encode_client_old(bufferlist& bl) const ::encode(n, bl); } ::encode(new_up_client, bl, 0); - ::encode(new_state, bl); + { + // legacy is map + uint32_t n = new_state.size(); + ::encode(n, bl); + for (auto p : new_state) { + ::encode(p.first, bl); + ::encode((uint8_t)p.second, bl); + } + } ::encode(new_weight, bl); // for ::encode(new_pg_temp, bl); n = new_pg_temp.size(); @@ -368,7 +411,14 @@ void OSDMap::Incremental::encode_classic(bufferlist& bl, uint64_t features) cons ::encode(new_pool_names, bl); ::encode(old_pools, bl); ::encode(new_up_client, bl, features); - ::encode(new_state, bl); + { + uint32_t n = new_state.size(); + ::encode(n, bl); + for (auto p : new_state) { + ::encode(p.first, bl); + ::encode((uint8_t)p.second, bl); + } + } ::encode(new_weight, bl); ::encode(new_pg_temp, bl); @@ -410,7 +460,7 @@ void OSDMap::Incremental::encode(bufferlist& bl, uint64_t features) const ENCODE_START(8, 7, bl); { - uint8_t v = 4; + uint8_t v = 5; if (!HAVE_FEATURE(features, SERVER_LUMINOUS)) { v = 3; } @@ -428,7 +478,16 @@ void OSDMap::Incremental::encode(bufferlist& bl, uint64_t features) const ::encode(new_pool_names, bl); ::encode(old_pools, bl); ::encode(new_up_client, bl, features); - ::encode(new_state, bl); + if (v >= 5) { + ::encode(new_state, bl); + } else { + uint32_t n = new_state.size(); + ::encode(n, bl); + for (auto p : new_state) { + ::encode(p.first, bl); + ::encode((uint8_t)p.second, bl); + } + } ::encode(new_weight, bl); ::encode(new_pg_temp, bl); ::encode(new_primary_temp, bl); @@ -445,7 +504,7 @@ void OSDMap::Incremental::encode(bufferlist& bl, uint64_t features) const } { - uint8_t target_v = 5; + uint8_t target_v = 6; if (!HAVE_FEATURE(features, SERVER_LUMINOUS)) { target_v = 2; } @@ -466,7 +525,11 @@ void OSDMap::Incremental::encode(bufferlist& bl, uint64_t features) const ::encode(new_nearfull_ratio, bl); ::encode(new_full_ratio, bl); ::encode(new_backfillfull_ratio, bl); + } + // 5 was string-based new_require_min_compat_client + if (target_v >= 6) { ::encode(new_require_min_compat_client, bl); + ::encode(new_require_osd_release, bl); } ENCODE_FINISH(bl); // osd-only data } @@ -543,7 +606,13 @@ void OSDMap::Incremental::decode_classic(bufferlist::iterator &p) ::decode(old_pools, p); } ::decode(new_up_client, p); - ::decode(new_state, p); + { + map ns; + ::decode(ns, p); + for (auto q : ns) { + new_state[q.first] = q.second; + } + } ::decode(new_weight, p); if (v < 6) { @@ -612,7 +681,7 @@ void OSDMap::Incremental::decode(bufferlist::iterator& bl) return; } { - DECODE_START(4, bl); // client-usable data + DECODE_START(5, bl); // client-usable data ::decode(fsid, bl); ::decode(epoch, bl); ::decode(modified, bl); @@ -626,7 +695,15 @@ void OSDMap::Incremental::decode(bufferlist::iterator& bl) ::decode(new_pool_names, bl); ::decode(old_pools, bl); ::decode(new_up_client, bl); - ::decode(new_state, bl); + if (struct_v >= 5) { + ::decode(new_state, bl); + } else { + map ns; + ::decode(ns, bl); + for (auto q : ns) { + new_state[q.first] = q.second; + } + } ::decode(new_weight, bl); ::decode(new_pg_temp, bl); ::decode(new_primary_temp, bl); @@ -651,7 +728,7 @@ void OSDMap::Incremental::decode(bufferlist::iterator& bl) } { - DECODE_START(5, bl); // extended, osd-only data + DECODE_START(6, bl); // extended, osd-only data ::decode(new_hb_back_up, bl); ::decode(new_up_thru, bl); ::decode(new_last_clean_interval, bl); @@ -679,8 +756,29 @@ void OSDMap::Incremental::decode(bufferlist::iterator& bl) } else { new_backfillfull_ratio = -1; } - if (struct_v >= 5) + if (struct_v == 5) { + string r; + ::decode(r, bl); + if (r.length()) { + new_require_min_compat_client = ceph_release_from_name(r.c_str()); + } + } + if (struct_v >= 6) { ::decode(new_require_min_compat_client, bl); + ::decode(new_require_osd_release, bl); + } else { + if (new_flags >= 0 && (new_flags & CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + // only for compat with post-kraken pre-luminous test clusters + new_require_osd_release = CEPH_RELEASE_LUMINOUS; + new_flags &= ~(CEPH_OSDMAP_LEGACY_REQUIRE_FLAGS); + } else if (new_flags >= 0 && (new_flags & CEPH_OSDMAP_REQUIRE_KRAKEN)) { + new_require_osd_release = CEPH_RELEASE_KRAKEN; + } else if (new_flags >= 0 && (new_flags & CEPH_OSDMAP_REQUIRE_JEWEL)) { + new_require_osd_release = CEPH_RELEASE_JEWEL; + } else { + new_require_osd_release = -1; + } + } DECODE_FINISH(bl); // osd-only data } @@ -725,7 +823,8 @@ void OSDMap::Incremental::dump(Formatter *f) const f->dump_float("new_full_ratio", new_full_ratio); f->dump_float("new_nearfull_ratio", new_nearfull_ratio); f->dump_float("new_backfillfull_ratio", new_backfillfull_ratio); - f->dump_string("new_require_min_compat_client", new_require_min_compat_client); + f->dump_int("new_require_min_compat_client", new_require_min_compat_client); + f->dump_int("new_require_osd_release", new_require_osd_release); if (fullmap.length()) { f->open_object_section("full_map"); @@ -985,6 +1084,13 @@ void OSDMap::get_blacklist(list > *bl) const std::copy(blacklist.begin(), blacklist.end(), std::back_inserter(*bl)); } +void OSDMap::get_blacklist(std::set *bl) const +{ + for (const auto &i : blacklist) { + bl->insert(i.first); + } +} + void OSDMap::set_max_osd(int m) { int o = max_osd; @@ -1044,19 +1150,22 @@ void OSDMap::count_full_nearfull_osds(int *full, int *backfill, int *nearfull) c } } -static bool get_osd_utilization(const ceph::unordered_map &osd_stat, - int id, int64_t* kb, int64_t* kb_used, int64_t* kb_avail) { - auto p = osd_stat.find(id); - if (p == osd_stat.end()) - return false; - *kb = p->second.kb; - *kb_used = p->second.kb_used; - *kb_avail = p->second.kb_avail; - return *kb > 0; +static bool get_osd_utilization( + const mempool::pgmap::unordered_map &osd_stat, + int id, int64_t* kb, int64_t* kb_used, int64_t* kb_avail) +{ + auto p = osd_stat.find(id); + if (p == osd_stat.end()) + return false; + *kb = p->second.kb; + *kb_used = p->second.kb_used; + *kb_avail = p->second.kb_avail; + return *kb > 0; } -void OSDMap::get_full_osd_util(const ceph::unordered_map &osd_stat, - map *full, map *backfill, map *nearfull) const +void OSDMap::get_full_osd_util( + const mempool::pgmap::unordered_map &osd_stat, + map *full, map *backfill, map *nearfull) const { full->clear(); backfill->clear(); @@ -1078,6 +1187,24 @@ void OSDMap::get_full_osd_util(const ceph::unordered_map &os } } +void OSDMap::get_full_osd_counts(set *full, set *backfill, + set *nearfull) const +{ + full->clear(); + backfill->clear(); + nearfull->clear(); + for (int i = 0; i < max_osd; ++i) { + if (exists(i) && is_up(i) && is_in(i)) { + if (osd_state[i] & CEPH_OSD_FULL) + full->emplace(i); + else if (osd_state[i] & CEPH_OSD_BACKFILLFULL) + backfill->emplace(i); + else if (osd_state[i] & CEPH_OSD_NEARFULL) + nearfull->emplace(i); + } + } +} + void OSDMap::get_all_osds(set& ls) const { for (int i=0; i& ls) const } } +void OSDMap::get_out_osds(set& ls) const +{ + for (int i = 0; i < max_osd; i++) { + if (is_out(i)) + ls.insert(i); + } +} + void OSDMap::calc_state_set(int state, set& st) { unsigned t = state; @@ -1166,8 +1301,8 @@ uint64_t OSDMap::get_features(int entity_type, uint64_t *pmask) const features |= CEPH_FEATURE_CRUSH_V4; if (crush->has_nondefault_tunables5()) features |= CEPH_FEATURE_CRUSH_TUNABLES5; - if (crush->has_incompat_chooseargs()) - features |= CEPH_FEATURE_CRUSH_CHOOSEARGS; + if (crush->has_incompat_choose_args()) + features |= CEPH_FEATURE_CRUSH_CHOOSE_ARGS; mask |= CEPH_FEATURES_CRUSH; if (!pg_upmap.empty() || !pg_upmap_items.empty()) @@ -1186,7 +1321,7 @@ uint64_t OSDMap::get_features(int entity_type, uint64_t *pmask) const pool.second.is_tier()) { features |= CEPH_FEATURE_OSD_CACHEPOOL; } - int ruleid = crush->find_rule(pool.second.get_crush_ruleset(), + int ruleid = crush->find_rule(pool.second.get_crush_rule(), pool.second.get_type(), pool.second.get_size()); if (ruleid >= 0) { @@ -1226,14 +1361,14 @@ uint64_t OSDMap::get_features(int entity_type, uint64_t *pmask) const if (entity_type == CEPH_ENTITY_TYPE_OSD) { const uint64_t jewel_features = CEPH_FEATURE_SERVER_JEWEL; - if (test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + if (require_osd_release >= CEPH_RELEASE_JEWEL) { features |= jewel_features; } mask |= jewel_features; const uint64_t kraken_features = CEPH_FEATUREMASK_SERVER_KRAKEN | CEPH_FEATURE_MSG_ADDR2; - if (test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + if (require_osd_release >= CEPH_RELEASE_KRAKEN) { features |= kraken_features; } mask |= kraken_features; @@ -1244,34 +1379,34 @@ uint64_t OSDMap::get_features(int entity_type, uint64_t *pmask) const return features; } -pair OSDMap::get_min_compat_client() const +uint8_t OSDMap::get_min_compat_client() const { uint64_t f = get_features(CEPH_ENTITY_TYPE_CLIENT, nullptr); if (HAVE_FEATURE(f, OSDMAP_PG_UPMAP) || // v12.0.0-1733-g27d6f43 - HAVE_FEATURE(f, CRUSH_CHOOSEARGS)) { // v12.0.1-2172-gef1ef28 - return make_pair("luminous", "12.2.0"); + HAVE_FEATURE(f, CRUSH_CHOOSE_ARGS)) { // v12.0.1-2172-gef1ef28 + return CEPH_RELEASE_LUMINOUS; // v12.2.0 } if (HAVE_FEATURE(f, CRUSH_TUNABLES5)) { // v10.0.0-612-g043a737 - return make_pair("jewel", "10.2.0"); + return CEPH_RELEASE_JEWEL; // v10.2.0 } if (HAVE_FEATURE(f, CRUSH_V4)) { // v0.91-678-g325fc56 - return make_pair("hammer", "0.94"); + return CEPH_RELEASE_HAMMER; // v0.94.0 } if (HAVE_FEATURE(f, OSD_PRIMARY_AFFINITY) || // v0.76-553-gf825624 HAVE_FEATURE(f, CRUSH_TUNABLES3) || // v0.76-395-ge20a55d HAVE_FEATURE(f, OSD_ERASURE_CODES) || // v0.73-498-gbfc86a8 HAVE_FEATURE(f, OSD_CACHEPOOL)) { // v0.67-401-gb91c1c5 - return make_pair("firefly", "0.80"); + return CEPH_RELEASE_FIREFLY; // v0.80.0 } if (HAVE_FEATURE(f, CRUSH_TUNABLES2) || // v0.54-684-g0cc47ff HAVE_FEATURE(f, OSDHASHPSPOOL)) { // v0.57-398-g8cc2b0f - return make_pair("dumpling", "0.67"); + return CEPH_RELEASE_DUMPLING; // v0.67.0 } if (HAVE_FEATURE(f, CRUSH_TUNABLES)) { // v0.48argonaut-206-g6f381af - return make_pair("argonaut", "0.48argonaut-207"); + return CEPH_RELEASE_ARGONAUT; // v0.48argonaut-206-g6f381af } - return make_pair("argonaut", "0.48"); + return CEPH_RELEASE_ARGONAUT; // v0.48argonaut-206-g6f381af } void OSDMap::_calc_up_osd_features() @@ -1342,10 +1477,8 @@ void OSDMap::dedup(const OSDMap *o, OSDMap *n) } // does pg_temp match? - if (o->pg_temp->size() == n->pg_temp->size()) { - if (*o->pg_temp == *n->pg_temp) - n->pg_temp = o->pg_temp; - } + if (*o->pg_temp == *n->pg_temp) + n->pg_temp = o->pg_temp; // does primary_temp match? if (o->primary_temp->size() == n->primary_temp->size()) { @@ -1452,8 +1585,22 @@ int OSDMap::apply_incremental(const Incremental &inc) } // nope, incremental. - if (inc.new_flags >= 0) + if (inc.new_flags >= 0) { flags = inc.new_flags; + // the below is just to cover a newly-upgraded luminous mon + // cluster that has to set require_jewel_osds or + // require_kraken_osds before the osds can be upgraded to + // luminous. + if (flags & CEPH_OSDMAP_REQUIRE_KRAKEN) { + if (require_osd_release < CEPH_RELEASE_KRAKEN) { + require_osd_release = CEPH_RELEASE_KRAKEN; + } + } else if (flags & CEPH_OSDMAP_REQUIRE_JEWEL) { + if (require_osd_release < CEPH_RELEASE_JEWEL) { + require_osd_release = CEPH_RELEASE_JEWEL; + } + } + } if (inc.new_max_osd >= 0) set_max_osd(inc.new_max_osd); @@ -1577,7 +1724,11 @@ int OSDMap::apply_incremental(const Incremental &inc) if (pg.second.empty()) pg_temp->erase(pg.first); else - (*pg_temp)[pg.first] = pg.second; + pg_temp->set(pg.first, pg.second); + } + if (!inc.new_pg_temp.empty()) { + // make sure pg_temp is efficiently stored + pg_temp->rebuild(); } for (const auto &pg : inc.new_primary_temp) { @@ -1626,9 +1777,15 @@ int OSDMap::apply_incremental(const Incremental &inc) if (inc.new_full_ratio >= 0) { full_ratio = inc.new_full_ratio; } - if (inc.new_require_min_compat_client.length()) { + if (inc.new_require_min_compat_client > 0) { require_min_compat_client = inc.new_require_min_compat_client; } + if (inc.new_require_osd_release >= 0) { + require_osd_release = inc.new_require_osd_release; + if (require_osd_release >= CEPH_RELEASE_LUMINOUS) { + flags &= ~(CEPH_OSDMAP_LEGACY_REQUIRE_FLAGS); + } + } // do new crush map last (after up/down stuff) if (inc.crush.length()) { @@ -1636,6 +1793,13 @@ int OSDMap::apply_incremental(const Incremental &inc) auto blp = bl.begin(); crush.reset(new CrushWrapper); crush->decode(blp); + if (require_osd_release >= CEPH_RELEASE_LUMINOUS) { + // only increment if this is a luminous-encoded osdmap, lest + // the mon's crush_version diverge from what the osds or others + // are decoding and applying on their end. if we won't encode + // it in the canonical version, don't change it. + ++crush_version; + } } calc_num_osds(); @@ -1713,7 +1877,7 @@ void OSDMap::_remove_nonexistent_osds(const pg_pool_t& pool, } } -int OSDMap::_pg_to_raw_osds( +void OSDMap::_pg_to_raw_osds( const pg_pool_t& pool, pg_t pg, vector *osds, ps_t *ppps) const @@ -1723,7 +1887,7 @@ int OSDMap::_pg_to_raw_osds( unsigned size = pool.get_size(); // what crush rule? - int ruleno = crush->find_rule(pool.get_crush_ruleset(), pool.get_type(), size); + int ruleno = crush->find_rule(pool.get_crush_rule(), pool.get_type(), size); if (ruleno >= 0) crush->do_rule(ruleno, pps, *osds, size, osd_weight, pg.pool()); @@ -1731,8 +1895,6 @@ int OSDMap::_pg_to_raw_osds( if (ppps) *ppps = pps; - - return osds->size(); } int OSDMap::_pick_primary(const vector& osds) const @@ -1905,17 +2067,16 @@ void OSDMap::_get_temp_osds(const pg_pool_t& pool, pg_t pg, } } -int OSDMap::pg_to_raw_osds(pg_t pg, vector *raw, int *primary) const +void OSDMap::pg_to_raw_osds(pg_t pg, vector *raw, int *primary) const { *primary = -1; raw->clear(); const pg_pool_t *pool = get_pg_pool(pg.pool()); if (!pool) - return 0; - int r = _pg_to_raw_osds(*pool, pg, raw, NULL); + return; + _pg_to_raw_osds(*pool, pg, raw, NULL); if (primary) *primary = _pick_primary(*raw); - return r; } void OSDMap::pg_to_raw_up(pg_t pg, vector *up, int *primary) const @@ -1936,7 +2097,7 @@ void OSDMap::pg_to_raw_up(pg_t pg, vector *up, int *primary) const *primary = _pick_primary(raw); _apply_primary_affinity(pps, *pool, up, primary); } - + void OSDMap::_pg_to_up_acting_osds( const pg_t& pg, vector *up, int *up_primary, vector *acting, int *acting_primary, @@ -2057,7 +2218,13 @@ void OSDMap::encode_client_old(bufferlist& bl) const ::encode(flags, bl); ::encode(max_osd, bl); - ::encode(osd_state, bl); + { + uint32_t n = osd_state.size(); + ::encode(n, bl); + for (auto s : osd_state) { + ::encode((uint8_t)s, bl); + } + } ::encode(osd_weight, bl); ::encode(osd_addrs->client_addr, bl, 0); @@ -2099,7 +2266,13 @@ void OSDMap::encode_classic(bufferlist& bl, uint64_t features) const ::encode(flags, bl); ::encode(max_osd, bl); - ::encode(osd_state, bl); + { + uint32_t n = osd_state.size(); + ::encode(n, bl); + for (auto s : osd_state) { + ::encode((uint8_t)s, bl); + } + } ::encode(osd_weight, bl); ::encode(osd_addrs->client_addr, bl, features); @@ -2146,8 +2319,8 @@ void OSDMap::encode(bufferlist& bl, uint64_t features) const ENCODE_START(8, 7, bl); { - uint8_t v = 4; - if (!HAVE_FEATURE(features, OSDMAP_PG_UPMAP)) { + uint8_t v = 6; + if (!HAVE_FEATURE(features, SERVER_LUMINOUS)) { v = 3; } ENCODE_START(v, 1, bl); // client-usable data @@ -2161,10 +2334,29 @@ void OSDMap::encode(bufferlist& bl, uint64_t features) const ::encode(pool_name, bl); ::encode(pool_max, bl); - ::encode(flags, bl); + if (v < 4) { + decltype(flags) f = flags; + if (require_osd_release >= CEPH_RELEASE_LUMINOUS) + f |= CEPH_OSDMAP_REQUIRE_LUMINOUS; + else if (require_osd_release == CEPH_RELEASE_KRAKEN) + f |= CEPH_OSDMAP_REQUIRE_KRAKEN; + else if (require_osd_release == CEPH_RELEASE_JEWEL) + f |= CEPH_OSDMAP_REQUIRE_JEWEL; + ::encode(f, bl); + } else { + ::encode(flags, bl); + } ::encode(max_osd, bl); - ::encode(osd_state, bl); + if (v >= 5) { + ::encode(osd_state, bl); + } else { + uint32_t n = osd_state.size(); + ::encode(n, bl); + for (auto s : osd_state) { + ::encode((uint8_t)s, bl); + } + } ::encode(osd_weight, bl); ::encode(osd_addrs->client_addr, bl, features); @@ -2190,11 +2382,14 @@ void OSDMap::encode(bufferlist& bl, uint64_t features) const assert(pg_upmap.empty()); assert(pg_upmap_items.empty()); } + if (v >= 6) { + ::encode(crush_version, bl); + } ENCODE_FINISH(bl); // client-usable data } { - uint8_t target_v = 4; + uint8_t target_v = 5; if (!HAVE_FEATURE(features, SERVER_LUMINOUS)) { target_v = 1; } @@ -2219,7 +2414,11 @@ void OSDMap::encode(bufferlist& bl, uint64_t features) const ::encode(nearfull_ratio, bl); ::encode(full_ratio, bl); ::encode(backfillfull_ratio, bl); + } + // 4 was string-based new_require_min_compat_client + if (target_v >= 5) { ::encode(require_min_compat_client, bl); + ::encode(require_osd_release, bl); } ENCODE_FINISH(bl); // osd-only data } @@ -2302,7 +2501,14 @@ void OSDMap::decode_classic(bufferlist::iterator& p) ::decode(flags, p); ::decode(max_osd, p); - ::decode(osd_state, p); + { + vector os; + ::decode(os, p); + osd_state.resize(os.size()); + for (unsigned i = 0; i < os.size(); ++i) { + osd_state[i] = os[i]; + } + } ::decode(osd_weight, p); ::decode(osd_addrs->client_addr, p); if (v <= 5) { @@ -2311,7 +2517,9 @@ void OSDMap::decode_classic(bufferlist::iterator& p) while (n--) { old_pg_t opg; ::decode_raw(opg, p); - ::decode((*pg_temp)[pg_t(opg)], p); + mempool::osdmap::vector v; + ::decode(v, p); + pg_temp->set(pg_t(opg), v); } } else { ::decode(*pg_temp, p); @@ -2387,7 +2595,7 @@ void OSDMap::decode(bufferlist::iterator& bl) * Since we made it past that hurdle, we can use our normal paths. */ { - DECODE_START(4, bl); // client-usable data + DECODE_START(6, bl); // client-usable data // base ::decode(fsid, bl); ::decode(epoch, bl); @@ -2401,7 +2609,16 @@ void OSDMap::decode(bufferlist::iterator& bl) ::decode(flags, bl); ::decode(max_osd, bl); - ::decode(osd_state, bl); + if (struct_v >= 5) { + ::decode(osd_state, bl); + } else { + vector os; + ::decode(os, bl); + osd_state.resize(os.size()); + for (unsigned i = 0; i < os.size(); ++i) { + osd_state[i] = os[i]; + } + } ::decode(osd_weight, bl); ::decode(osd_addrs->client_addr, bl); @@ -2433,11 +2650,14 @@ void OSDMap::decode(bufferlist::iterator& bl) pg_upmap.clear(); pg_upmap_items.clear(); } + if (struct_v >= 6) { + ::decode(crush_version, bl); + } DECODE_FINISH(bl); // client-usable data } { - DECODE_START(4, bl); // extended, osd-only data + DECODE_START(5, bl); // extended, osd-only data ::decode(osd_addrs->hb_back_addr, bl); ::decode(osd_info, bl); ::decode(blacklist, bl); @@ -2459,8 +2679,31 @@ void OSDMap::decode(bufferlist::iterator& bl) } else { backfillfull_ratio = 0; } - if (struct_v >= 4) + if (struct_v == 4) { + string r; + ::decode(r, bl); + if (r.length()) + require_min_compat_client = ceph_release_from_name(r.c_str()); + } + if (struct_v >= 5) { ::decode(require_min_compat_client, bl); + ::decode(require_osd_release, bl); + if (require_osd_release >= CEPH_RELEASE_LUMINOUS) { + flags &= ~(CEPH_OSDMAP_LEGACY_REQUIRE_FLAGS); + } + } else { + if (flags & CEPH_OSDMAP_REQUIRE_LUMINOUS) { + // only for compat with post-kraken pre-luminous test clusters + require_osd_release = CEPH_RELEASE_LUMINOUS; + flags &= ~(CEPH_OSDMAP_LEGACY_REQUIRE_FLAGS); + } else if (flags & CEPH_OSDMAP_REQUIRE_KRAKEN) { + require_osd_release = CEPH_RELEASE_KRAKEN; + } else if (flags & CEPH_OSDMAP_REQUIRE_JEWEL) { + require_osd_release = CEPH_RELEASE_JEWEL; + } else { + require_osd_release = 0; + } + } DECODE_FINISH(bl); // osd-only data } @@ -2529,16 +2772,19 @@ void OSDMap::dump(Formatter *f) const f->dump_stream("created") << get_created(); f->dump_stream("modified") << get_modified(); f->dump_string("flags", get_flag_string()); + f->dump_unsigned("crush_version", get_crush_version()); f->dump_float("full_ratio", full_ratio); f->dump_float("backfillfull_ratio", backfillfull_ratio); f->dump_float("nearfull_ratio", nearfull_ratio); f->dump_string("cluster_snapshot", get_cluster_snapshot()); f->dump_int("pool_max", get_pool_max()); f->dump_int("max_osd", get_max_osd()); - f->dump_string("require_min_compat_client", require_min_compat_client); - auto mv = get_min_compat_client(); - f->dump_string("min_compat_client", mv.first); - f->dump_string("min_compat_client_version", mv.second); + f->dump_string("require_min_compat_client", + ceph_release_name(require_min_compat_client)); + f->dump_string("min_compat_client", + ceph_release_name(get_min_compat_client())); + f->dump_string("require_osd_release", + ceph_release_name(require_osd_release)); f->open_array_section("pools"); for (const auto &pool : pools) { @@ -2620,15 +2866,7 @@ void OSDMap::dump(Formatter *f) const } f->close_section(); f->open_array_section("pg_temp"); - for (const auto &pg : *pg_temp) { - f->open_object_section("osds"); - f->dump_stream("pgid") << pg.first; - f->open_array_section("osds"); - for (const auto osd : pg.second) - f->dump_int("osd", osd); - f->close_section(); - f->close_section(); - } + pg_temp->dump(f); f->close_section(); f->open_array_section("primary_temp"); @@ -2749,14 +2987,16 @@ void OSDMap::print(ostream& out) const << "modified " << get_modified() << "\n"; out << "flags " << get_flag_string() << "\n"; + out << "crush_version " << get_crush_version() << "\n"; out << "full_ratio " << full_ratio << "\n"; out << "backfillfull_ratio " << backfillfull_ratio << "\n"; out << "nearfull_ratio " << nearfull_ratio << "\n"; - if (require_min_compat_client.length()) { - out << "require_min_compat_client " << require_min_compat_client << "\n"; + if (require_min_compat_client > 0) { + out << "require_min_compat_client " + << ceph_release_name(require_min_compat_client) << "\n"; } - auto mv = get_min_compat_client(); - out << "min_compat_client " << mv.first << " " << mv.second << "\n"; + out << "min_compat_client " << ceph_release_name(get_min_compat_client()) + << "\n"; if (get_cluster_snapshot().length()) out << "cluster_snapshot " << get_cluster_snapshot() << "\n"; out << "\n"; @@ -2808,8 +3048,24 @@ void OSDMap::print(ostream& out) const class OSDTreePlainDumper : public CrushTreeDumper::Dumper { public: typedef CrushTreeDumper::Dumper Parent; - OSDTreePlainDumper(const CrushWrapper *crush, const OSDMap *osdmap_) - : Parent(crush), osdmap(osdmap_) {} + + OSDTreePlainDumper(const CrushWrapper *crush, const OSDMap *osdmap_, + unsigned f) + : Parent(crush), osdmap(osdmap_), filter(f) { } + + bool should_dump_leaf(int i) const override { + if (((filter & OSDMap::DUMP_UP) && !osdmap->is_up(i)) || + ((filter & OSDMap::DUMP_DOWN) && !osdmap->is_down(i)) || + ((filter & OSDMap::DUMP_IN) && !osdmap->is_in(i)) || + ((filter & OSDMap::DUMP_OUT) && !osdmap->is_out(i))) { + return false; + } + return true; + } + + bool should_dump_empty_bucket() const override { + return !filter; + } void dump(TextTable *tbl) { tbl->define_column("ID", TextTable::LEFT, TextTable::RIGHT); @@ -2822,8 +3078,9 @@ public: Parent::dump(tbl); for (int i = 0; i < osdmap->get_max_osd(); i++) { - if (osdmap->exists(i) && !is_touched(i)) + if (osdmap->exists(i) && !is_touched(i) && should_dump_leaf(i)) { dump_item(CrushTreeDumper::Item(i, 0, 0), tbl); + } } } @@ -2859,14 +3116,30 @@ protected: private: const OSDMap *osdmap; + const unsigned filter; }; class OSDTreeFormattingDumper : public CrushTreeDumper::FormattingDumper { public: typedef CrushTreeDumper::FormattingDumper Parent; - OSDTreeFormattingDumper(const CrushWrapper *crush, const OSDMap *osdmap_) - : Parent(crush), osdmap(osdmap_) {} + OSDTreeFormattingDumper(const CrushWrapper *crush, const OSDMap *osdmap_, + unsigned f) + : Parent(crush), osdmap(osdmap_), filter(f) { } + + bool should_dump_leaf(int i) const override { + if (((filter & OSDMap::DUMP_UP) && !osdmap->is_up(i)) || + ((filter & OSDMap::DUMP_DOWN) && !osdmap->is_down(i)) || + ((filter & OSDMap::DUMP_IN) && !osdmap->is_in(i)) || + ((filter & OSDMap::DUMP_OUT) && !osdmap->is_out(i))) { + return false; + } + return true; + } + + bool should_dump_empty_bucket() const override { + return !filter; + } void dump(Formatter *f) { f->open_array_section("nodes"); @@ -2874,7 +3147,7 @@ public: f->close_section(); f->open_array_section("stray"); for (int i = 0; i < osdmap->get_max_osd(); i++) { - if (osdmap->exists(i) && !is_touched(i)) + if (osdmap->exists(i) && !is_touched(i) && should_dump_leaf(i)) dump_item(CrushTreeDumper::Item(i, 0, 0), f); } f->close_section(); @@ -2894,16 +3167,17 @@ protected: private: const OSDMap *osdmap; + const unsigned filter; }; -void OSDMap::print_tree(Formatter *f, ostream *out) const +void OSDMap::print_tree(Formatter *f, ostream *out, unsigned filter) const { - if (f) - OSDTreeFormattingDumper(crush.get(), this).dump(f); - else { + if (f) { + OSDTreeFormattingDumper(crush.get(), this, filter).dump(f); + } else { assert(out); TextTable tbl; - OSDTreePlainDumper(crush.get(), this).dump(&tbl); + OSDTreePlainDumper(crush.get(), this, filter).dump(&tbl); *out << tbl; } } @@ -2921,8 +3195,7 @@ void OSDMap::print_summary(Formatter *f, ostream& out) const f->dump_unsigned("num_remapped_pgs", get_num_pg_temp()); f->close_section(); } else { - out << " osdmap e" << get_epoch() << ": " - << get_num_osds() << " osds: " + out << get_num_osds() << " osds: " << get_num_up_osds() << " up, " << get_num_in_osds() << " in"; if (get_num_pg_temp()) @@ -2937,7 +3210,7 @@ void OSDMap::print_summary(Formatter *f, ostream& out) const void OSDMap::print_oneline_summary(ostream& out) const { out << "e" << get_epoch() << ": " - << get_num_osds() << " osds: " + << get_num_osds() << " total, " << get_num_up_osds() << " up, " << get_num_in_osds() << " in"; if (test_flag(CEPH_OSDMAP_FULL)) @@ -2949,7 +3222,7 @@ void OSDMap::print_oneline_summary(ostream& out) const bool OSDMap::crush_ruleset_in_use(int ruleset) const { for (const auto &pool : pools) { - if (pool.second.crush_ruleset == ruleset) + if (pool.second.crush_rule == ruleset) return true; } return false; @@ -3013,8 +3286,9 @@ int OSDMap::build_simple(CephContext *cct, epoch_t e, uuid_d &fsid, int poolbase = get_max_osd() ? get_max_osd() : 1; - int const default_replicated_ruleset = crush->get_osd_pool_default_crush_replicated_ruleset(cct); - assert(default_replicated_ruleset >= 0); + int const default_replicated_rule = + crush->get_osd_pool_default_crush_replicated_ruleset(cct); + assert(default_replicated_rule >= 0); for (auto &plname : pool_names) { int64_t pool = ++pool_max; @@ -3030,7 +3304,7 @@ int OSDMap::build_simple(CephContext *cct, epoch_t e, uuid_d &fsid, pools[pool].set_flag(pg_pool_t::FLAG_NOSIZECHANGE); pools[pool].size = cct->_conf->osd_pool_default_size; pools[pool].min_size = cct->_conf->get_osd_pool_default_min_size(); - pools[pool].crush_ruleset = default_replicated_ruleset; + pools[pool].crush_rule = default_replicated_rule; pools[pool].object_hash = CEPH_STR_HASH_RJENKINS; pools[pool].set_pg_num(poolbase << pg_bits); pools[pool].set_pgp_num(poolbase << pgp_bits); @@ -3104,7 +3378,7 @@ int OSDMap::build_simple_crush_map(CephContext *cct, CrushWrapper& crush, crush.insert_item(cct, o, 1.0, name, loc); } - build_simple_crush_rulesets(cct, crush, "default", ss); + build_simple_crush_rules(cct, crush, "default", ss); crush.finalize(); @@ -3173,7 +3447,7 @@ int OSDMap::build_simple_crush_map_from_conf(CephContext *cct, crush.insert_item(cct, o, 1.0, section, loc); } - build_simple_crush_rulesets(cct, crush, "default", ss); + build_simple_crush_rules(cct, crush, "default", ss); crush.finalize(); @@ -3181,23 +3455,21 @@ int OSDMap::build_simple_crush_map_from_conf(CephContext *cct, } -int OSDMap::build_simple_crush_rulesets(CephContext *cct, - CrushWrapper& crush, - const string& root, - ostream *ss) +int OSDMap::build_simple_crush_rules( + CephContext *cct, + CrushWrapper& crush, + const string& root, + ostream *ss) { - int crush_ruleset = - crush._get_osd_pool_default_crush_replicated_ruleset(cct, true); + int crush_rule = crush.get_osd_pool_default_crush_replicated_ruleset(cct); string failure_domain = crush.get_type_name(cct->_conf->osd_crush_chooseleaf_type); - if (crush_ruleset == CEPH_DEFAULT_CRUSH_REPLICATED_RULESET) - crush_ruleset = -1; // create ruleset 0 by default - int r; - r = crush.add_simple_ruleset_at("replicated_ruleset", root, failure_domain, - "firstn", pg_pool_t::TYPE_REPLICATED, - crush_ruleset, ss); + r = crush.add_simple_rule_at( + "replicated_rule", root, failure_domain, + "firstn", pg_pool_t::TYPE_REPLICATED, + crush_rule, ss); if (r < 0) return r; // do not add an erasure rule by default or else we will implicitly @@ -3225,20 +3497,18 @@ int OSDMap::summarize_mapping_stats( vector new_by_osd(get_max_osd(), 0); for (int64_t pool_id : ls) { const pg_pool_t *pi = get_pg_pool(pool_id); - vector up, up2, acting; - int up_primary, acting_primary; + vector up, up2; + int up_primary; for (unsigned ps = 0; ps < pi->get_pg_num(); ++ps) { pg_t pgid(ps, pool_id, -1); total_pg += pi->get_size(); - pg_to_up_acting_osds(pgid, &up, &up_primary, - &acting, &acting_primary); + pg_to_up_acting_osds(pgid, &up, &up_primary, nullptr, nullptr); for (int osd : up) { if (osd >= 0 && osd < get_max_osd()) ++base_by_osd[osd]; } if (newmap) { - newmap->pg_to_up_acting_osds(pgid, &up2, &up_primary, - &acting, &acting_primary); + newmap->pg_to_up_acting_osds(pgid, &up2, &up_primary, nullptr, nullptr); for (int osd : up2) { if (osd >= 0 && osd < get_max_osd()) ++new_by_osd[osd]; @@ -3420,7 +3690,7 @@ bool OSDMap::try_pg_upmap( const pg_pool_t *pool = get_pg_pool(pg.pool()); if (!pool) return false; - int rule = crush->find_rule(pool->get_crush_ruleset(), pool->get_type(), + int rule = crush->find_rule(pool->get_crush_rule(), pool->get_type(), pool->get_size()); if (rule < 0) return false; @@ -3456,17 +3726,29 @@ bool OSDMap::try_pg_upmap( int OSDMap::calc_pg_upmaps( CephContext *cct, - float max_deviation, + float max_deviation_ratio, int max, - const set& only_pools, + const set& only_pools_orig, OSDMap::Incremental *pending_inc) { + set only_pools; + if (only_pools_orig.empty()) { + for (auto& i : pools) { + only_pools.insert(i.first); + } + } else { + only_pools = only_pools_orig; + } OSDMap tmp; tmp.deepish_copy_from(*this); + float start_deviation = 0; + float end_deviation = 0; int num_changed = 0; while (true) { map> pgs_by_osd; int total_pgs = 0; + float osd_weight_total = 0; + map osd_weight; for (auto& i : pools) { if (!only_pools.empty() && !only_pools.count(i.first)) continue; @@ -3480,23 +3762,35 @@ int OSDMap::calc_pg_upmaps( } } total_pgs += i.second.get_size() * i.second.get_pg_num(); + + map pmap; + int ruleno = tmp.crush->find_rule(i.second.get_crush_rule(), + i.second.get_type(), + i.second.get_size()); + tmp.crush->get_rule_weight_osd_map(ruleno, &pmap); + ldout(cct,30) << __func__ << " pool " << i.first << " ruleno " << ruleno << dendl; + for (auto p : pmap) { + osd_weight[p.first] += p.second; + osd_weight_total += p.second; + } } - float osd_weight_total = 0; - map osd_weight; - for (auto& i : pgs_by_osd) { - float w = crush->get_item_weightf(i.first); - osd_weight[i.first] = w; - osd_weight_total += w; - ldout(cct, 20) << " osd." << i.first << " weight " << w - << " pgs " << i.second.size() << dendl; + for (auto& i : osd_weight) { + int pgs = 0; + auto p = pgs_by_osd.find(i.first); + if (p != pgs_by_osd.end()) + pgs = p->second.size(); + else + pgs_by_osd.emplace(i.first, set()); + ldout(cct, 20) << " osd." << i.first << " weight " << i.second + << " pgs " << pgs << dendl; } - // NOTE: we assume we touch all osds with CRUSH! float pgs_per_weight = total_pgs / osd_weight_total; ldout(cct, 10) << " osd_weight_total " << osd_weight_total << dendl; ldout(cct, 10) << " pgs_per_weight " << pgs_per_weight << dendl; // osd deviation + float total_deviation = 0; map osd_deviation; // osd, deviation(pgs) multimap deviation_osd; // deviation(pgs), osd set overfull; @@ -3510,9 +3804,14 @@ int OSDMap::calc_pg_upmaps( << dendl; osd_deviation[i.first] = deviation; deviation_osd.insert(make_pair(deviation, i.first)); - if (deviation > 0) + if (deviation >= 1.0) overfull.insert(i.first); + total_deviation += abs(deviation); + } + if (num_changed == 0) { + start_deviation = total_deviation; } + end_deviation = total_deviation; // build underfull, sorted from least-full to most-average vector underfull; @@ -3523,7 +3822,8 @@ int OSDMap::calc_pg_upmaps( break; underfull.push_back(i->second); } - ldout(cct, 10) << " overfull " << overfull + ldout(cct, 10) << " total_deviation " << total_deviation + << " overfull " << overfull << " underfull " << underfull << dendl; if (overfull.empty() || underfull.empty()) break; @@ -3532,14 +3832,14 @@ int OSDMap::calc_pg_upmaps( bool restart = false; for (auto p = deviation_osd.rbegin(); p != deviation_osd.rend(); ++p) { int osd = p->second; + float deviation = p->first; float target = osd_weight[osd] * pgs_per_weight; - float deviation = deviation_osd.rbegin()->first; - if (deviation/target < max_deviation) { + if (deviation/target < max_deviation_ratio) { ldout(cct, 10) << " osd." << osd << " target " << target << " deviation " << deviation - << " -> " << deviation/target - << " < max " << max_deviation << dendl; + << " -> ratio " << deviation/target + << " < max ratio " << max_deviation_ratio << dendl; break; } int num_to_move = deviation; @@ -3611,5 +3911,332 @@ int OSDMap::calc_pg_upmaps( break; } } + ldout(cct, 10) << " start deviation " << start_deviation << dendl; + ldout(cct, 10) << " end deviation " << end_deviation << dendl; return num_changed; } + +int OSDMap::get_osds_by_bucket_name(const string &name, set *osds) const +{ + return crush->get_leaves(name, osds); +} + +template +class OSDUtilizationDumper : public CrushTreeDumper::Dumper { +public: + typedef CrushTreeDumper::Dumper Parent; + + OSDUtilizationDumper(const CrushWrapper *crush, const OSDMap *osdmap_, + const PGStatService *pgs_, bool tree_) : + Parent(crush), + osdmap(osdmap_), + pgs(pgs_), + tree(tree_), + average_util(average_utilization()), + min_var(-1), + max_var(-1), + stddev(0), + sum(0) { + } + +protected: + void dump_stray(F *f) { + for (int i = 0; i < osdmap->get_max_osd(); i++) { + if (osdmap->exists(i) && !this->is_touched(i)) + dump_item(CrushTreeDumper::Item(i, 0, 0), f); + } + } + + void dump_item(const CrushTreeDumper::Item &qi, F *f) override { + if (!tree && qi.is_bucket()) + return; + + float reweight = qi.is_bucket() ? -1 : osdmap->get_weightf(qi.id); + int64_t kb = 0, kb_used = 0, kb_avail = 0; + double util = 0; + if (get_bucket_utilization(qi.id, &kb, &kb_used, &kb_avail)) + if (kb_used && kb) + util = 100.0 * (double)kb_used / (double)kb; + + double var = 1.0; + if (average_util) + var = util / average_util; + + size_t num_pgs = qi.is_bucket() ? 0 : pgs->get_num_pg_by_osd(qi.id); + + dump_item(qi, reweight, kb, kb_used, kb_avail, util, var, num_pgs, f); + + if (!qi.is_bucket() && reweight > 0) { + if (min_var < 0 || var < min_var) + min_var = var; + if (max_var < 0 || var > max_var) + max_var = var; + + double dev = util - average_util; + dev *= dev; + stddev += reweight * dev; + sum += reweight; + } + } + + virtual void dump_item(const CrushTreeDumper::Item &qi, + float &reweight, + int64_t kb, + int64_t kb_used, + int64_t kb_avail, + double& util, + double& var, + const size_t num_pgs, + F *f) = 0; + + double dev() { + return sum > 0 ? sqrt(stddev / sum) : 0; + } + + double average_utilization() { + int64_t kb = 0, kb_used = 0; + for (int i = 0; i < osdmap->get_max_osd(); i++) { + if (!osdmap->exists(i) || osdmap->get_weight(i) == 0) + continue; + int64_t kb_i, kb_used_i, kb_avail_i; + if (get_osd_utilization(i, &kb_i, &kb_used_i, &kb_avail_i)) { + kb += kb_i; + kb_used += kb_used_i; + } + } + return kb > 0 ? 100.0 * (double)kb_used / (double)kb : 0; + } + + bool get_osd_utilization(int id, int64_t* kb, int64_t* kb_used, + int64_t* kb_avail) const { + const osd_stat_t *p = pgs->get_osd_stat(id); + if (!p) return false; + *kb = p->kb; + *kb_used = p->kb_used; + *kb_avail = p->kb_avail; + return *kb > 0; + } + + bool get_bucket_utilization(int id, int64_t* kb, int64_t* kb_used, + int64_t* kb_avail) const { + if (id >= 0) { + if (osdmap->is_out(id)) { + *kb = 0; + *kb_used = 0; + *kb_avail = 0; + return true; + } + return get_osd_utilization(id, kb, kb_used, kb_avail); + } + + *kb = 0; + *kb_used = 0; + *kb_avail = 0; + + for (int k = osdmap->crush->get_bucket_size(id) - 1; k >= 0; k--) { + int item = osdmap->crush->get_bucket_item(id, k); + int64_t kb_i = 0, kb_used_i = 0, kb_avail_i = 0; + if (!get_bucket_utilization(item, &kb_i, &kb_used_i, &kb_avail_i)) + return false; + *kb += kb_i; + *kb_used += kb_used_i; + *kb_avail += kb_avail_i; + } + return *kb > 0; + } + +protected: + const OSDMap *osdmap; + const PGStatService *pgs; + bool tree; + double average_util; + double min_var; + double max_var; + double stddev; + double sum; +}; + + +class OSDUtilizationPlainDumper : public OSDUtilizationDumper { +public: + typedef OSDUtilizationDumper Parent; + + OSDUtilizationPlainDumper(const CrushWrapper *crush, const OSDMap *osdmap, + const PGStatService *pgs, bool tree) : + Parent(crush, osdmap, pgs, tree) {} + + void dump(TextTable *tbl) { + tbl->define_column("ID", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("WEIGHT", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("REWEIGHT", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("SIZE", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("USE", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("%USE", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("VAR", TextTable::LEFT, TextTable::RIGHT); + tbl->define_column("PGS", TextTable::LEFT, TextTable::RIGHT); + if (tree) + tbl->define_column("TYPE NAME", TextTable::LEFT, TextTable::LEFT); + + Parent::dump(tbl); + + dump_stray(tbl); + + *tbl << "" << "" << "TOTAL" + << si_t(pgs->get_osd_sum().kb << 10) + << si_t(pgs->get_osd_sum().kb_used << 10) + << si_t(pgs->get_osd_sum().kb_avail << 10) + << lowprecision_t(average_util) + << "" + << TextTable::endrow; + } + +protected: + struct lowprecision_t { + float v; + explicit lowprecision_t(float _v) : v(_v) {} + }; + friend std::ostream &operator<<(ostream& out, const lowprecision_t& v); + + using OSDUtilizationDumper::dump_item; + void dump_item(const CrushTreeDumper::Item &qi, + float &reweight, + int64_t kb, + int64_t kb_used, + int64_t kb_avail, + double& util, + double& var, + const size_t num_pgs, + TextTable *tbl) override { + *tbl << qi.id + << weightf_t(qi.weight) + << weightf_t(reweight) + << si_t(kb << 10) + << si_t(kb_used << 10) + << si_t(kb_avail << 10) + << lowprecision_t(util) + << lowprecision_t(var); + + if (qi.is_bucket()) { + *tbl << "-"; + } else { + *tbl << num_pgs; + } + + if (tree) { + ostringstream name; + for (int k = 0; k < qi.depth; k++) + name << " "; + if (qi.is_bucket()) { + int type = crush->get_bucket_type(qi.id); + name << crush->get_type_name(type) << " " + << crush->get_item_name(qi.id); + } else { + name << "osd." << qi.id; + } + *tbl << name.str(); + } + + *tbl << TextTable::endrow; + } + +public: + string summary() { + ostringstream out; + out << "MIN/MAX VAR: " << lowprecision_t(min_var) + << "/" << lowprecision_t(max_var) << " " + << "STDDEV: " << lowprecision_t(dev()); + return out.str(); + } +}; + +ostream& operator<<(ostream& out, + const OSDUtilizationPlainDumper::lowprecision_t& v) +{ + if (v.v < -0.01) { + return out << "-"; + } else if (v.v < 0.001) { + return out << "0"; + } else { + std::streamsize p = out.precision(); + return out << std::fixed << std::setprecision(2) << v.v << std::setprecision(p); + } +} + +class OSDUtilizationFormatDumper : public OSDUtilizationDumper { +public: + typedef OSDUtilizationDumper Parent; + + OSDUtilizationFormatDumper(const CrushWrapper *crush, const OSDMap *osdmap, + const PGStatService *pgs, bool tree) : + Parent(crush, osdmap, pgs, tree) {} + + void dump(Formatter *f) { + f->open_array_section("nodes"); + Parent::dump(f); + f->close_section(); + + f->open_array_section("stray"); + dump_stray(f); + f->close_section(); + } + +protected: + using OSDUtilizationDumper::dump_item; + void dump_item(const CrushTreeDumper::Item &qi, + float &reweight, + int64_t kb, + int64_t kb_used, + int64_t kb_avail, + double& util, + double& var, + const size_t num_pgs, + Formatter *f) override { + f->open_object_section("item"); + CrushTreeDumper::dump_item_fields(crush, qi, f); + f->dump_float("reweight", reweight); + f->dump_int("kb", kb); + f->dump_int("kb_used", kb_used); + f->dump_int("kb_avail", kb_avail); + f->dump_float("utilization", util); + f->dump_float("var", var); + f->dump_unsigned("pgs", num_pgs); + CrushTreeDumper::dump_bucket_children(crush, qi, f); + f->close_section(); + } + +public: + void summary(Formatter *f) { + f->open_object_section("summary"); + f->dump_int("total_kb", pgs->get_osd_sum().kb); + f->dump_int("total_kb_used", pgs->get_osd_sum().kb_used); + f->dump_int("total_kb_avail", pgs->get_osd_sum().kb_avail); + f->dump_float("average_utilization", average_util); + f->dump_float("min_var", min_var); + f->dump_float("max_var", max_var); + f->dump_float("dev", dev()); + f->close_section(); + } +}; + +void print_osd_utilization(const OSDMap& osdmap, + const PGStatService *pgstat, + ostream& out, + Formatter *f, + bool tree) +{ + const CrushWrapper *crush = osdmap.crush.get(); + if (f) { + f->open_object_section("df"); + OSDUtilizationFormatDumper d(crush, &osdmap, pgstat, tree); + d.dump(f); + d.summary(f); + f->close_section(); + f->flush(out); + } else { + OSDUtilizationPlainDumper d(crush, &osdmap, pgstat, tree); + TextTable tbl; + d.dump(&tbl); + out << tbl << d.summary() << "\n"; + } +} diff --git a/ceph/src/osd/OSDMap.h b/ceph/src/osd/OSDMap.h index 1dc67090d..6639b4f65 100644 --- a/ceph/src/osd/OSDMap.h +++ b/ceph/src/osd/OSDMap.h @@ -19,6 +19,8 @@ #ifndef CEPH_OSDMAP_H #define CEPH_OSDMAP_H +#include "include/cpp-btree/btree_map.h" + /* * describe properties of the OSD cluster. * disks, disk groups, total # osds, @@ -114,6 +116,240 @@ WRITE_CLASS_ENCODER(osd_xinfo_t) ostream& operator<<(ostream& out, const osd_xinfo_t& xi); +struct PGTempMap { +#if 1 + bufferlist data; + typedef btree::btree_map map_t; + map_t map; + + void encode(bufferlist& bl) const { + uint32_t n = map.size(); + ::encode(n, bl); + for (auto &p : map) { + ::encode(p.first, bl); + bl.append((char*)p.second, (*p.second + 1) * sizeof(int32_t)); + } + } + void decode(bufferlist::iterator& p) { + data.clear(); + map.clear(); + uint32_t n; + ::decode(n, p); + if (!n) + return; + bufferlist::iterator pstart = p; + size_t start_off = pstart.get_off(); + vector> offsets; + offsets.resize(n); + for (unsigned i=0; i 1) { + data.rebuild(); + } + //map.reserve(n); + char *start = data.c_str(); + for (auto i : offsets) { + map.insert(map.end(), make_pair(i.first, (int32_t*)(start + i.second))); + } + } + void rebuild() { + bufferlist bl; + encode(bl); + auto p = bl.begin(); + decode(p); + } + friend bool operator==(const PGTempMap& l, const PGTempMap& r) { + return + l.map.size() == r.map.size() && + l.data.contents_equal(r.data); + } + + class iterator { + map_t::const_iterator it; + map_t::const_iterator end; + pair> current; + void init_current() { + if (it != end) { + current.first = it->first; + assert(it->second); + current.second.resize(*it->second); + int32_t *p = it->second + 1; + for (int n = 0; n < *it->second; ++n, ++p) { + current.second[n] = *p; + } + } + } + public: + iterator(map_t::const_iterator p, + map_t::const_iterator e) + : it(p), end(e) { + init_current(); + } + + const pair>& operator*() const { + return current; + } + const pair>* operator->() const { + return ¤t; + } + friend bool operator==(const iterator& l, const iterator& r) { + return l.it == r.it; + } + friend bool operator!=(const iterator& l, const iterator& r) { + return l.it != r.it; + } + iterator& operator++() { + ++it; + if (it != end) + init_current(); + return *this; + } + iterator operator++(int) { + iterator r = *this; + ++it; + if (it != end) + init_current(); + return r; + } + }; + iterator begin() const { + return iterator(map.begin(), map.end()); + } + iterator end() const { + return iterator(map.end(), map.end()); + } + iterator find(pg_t pgid) const { + return iterator(map.find(pgid), map.end()); + } + size_t size() const { + return map.size(); + } + size_t count(pg_t pgid) const { + return map.count(pgid); + } + void erase(pg_t pgid) { + map.erase(pgid); + } + void clear() { + map.clear(); + data.clear(); + } + void set(pg_t pgid, const mempool::osdmap::vector& v) { + size_t need = sizeof(int32_t) * (1 + v.size()); + if (need < data.get_append_buffer_unused_tail_length()) { + bufferptr z(data.get_append_buffer_unused_tail_length()); + z.zero(); + data.append(z.c_str(), z.length()); + } + ::encode(v, data); + map[pgid] = (int32_t*)(data.back().end_c_str()) - (1 + v.size()); + } + mempool::osdmap::vector get(pg_t pgid) { + mempool::osdmap::vector v; + int32_t *p = map[pgid]; + size_t n = *p++; + v.resize(n); + for (size_t i = 0; i < n; ++i, ++p) { + v[i] = *p; + } + return v; + } +#else + // trivial implementation + mempool::osdmap::map > pg_temp; + + void encode(bufferlist& bl) const { + ::encode(pg_temp, bl); + } + void decode(bufferlist::iterator& p) { + ::decode(pg_temp, p); + } + friend bool operator==(const PGTempMap& l, const PGTempMap& r) { + return + l.pg_temp.size() == r.pg_temp.size() && + l.pg_temp == r.pg_temp; + } + + class iterator { + mempool::osdmap::map >::const_iterator it; + public: + iterator(mempool::osdmap::map >::const_iterator p) + : it(p) {} + + pair&> operator*() const { + return *it; + } + const pair>* operator->() const { + return &*it; + } + friend bool operator==(const iterator& l, const iterator& r) { + return l.it == r.it; + } + friend bool operator!=(const iterator& l, const iterator& r) { + return l.it != r.it; + } + iterator& operator++() { + ++it; + return *this; + } + iterator operator++(int) { + iterator r = *this; + ++it; + return r; + } + }; + iterator begin() const { + return iterator(pg_temp.cbegin()); + } + iterator end() const { + return iterator(pg_temp.cend()); + } + iterator find(pg_t pgid) const { + return iterator(pg_temp.find(pgid)); + } + size_t size() const { + return pg_temp.size(); + } + size_t count(pg_t pgid) const { + return pg_temp.count(pgid); + } + void erase(pg_t pgid) { + pg_temp.erase(pgid); + } + void clear() { + pg_temp.clear(); + } + void set(pg_t pgid, const mempool::osdmap::vector& v) { + pg_temp[pgid] = v; + } + const mempool::osdmap::vector& get(pg_t pgid) { + return pg_temp.at(pgid); + } +#endif + void dump(Formatter *f) const { + for (const auto &pg : *this) { + f->open_object_section("osds"); + f->dump_stream("pgid") << pg.first; + f->open_array_section("osds"); + for (const auto osd : pg.second) + f->dump_int("osd", osd); + f->close_section(); + f->close_section(); + } + } +}; +WRITE_CLASS_ENCODER(PGTempMap) + /** OSDMap */ class OSDMap { @@ -132,6 +368,7 @@ public: utime_t modified; int64_t new_pool_max; //incremented by the OSDMonitor on each pool create int32_t new_flags; + int8_t new_require_osd_release = -1; // full (rare) bufferlist fullmap; // in lieu of below. @@ -146,7 +383,7 @@ public: mempool::osdmap::vector old_erasure_code_profiles; mempool::osdmap::map new_up_client; mempool::osdmap::map new_up_cluster; - mempool::osdmap::map new_state; // XORed onto previous state. + mempool::osdmap::map new_state; // XORed onto previous state. mempool::osdmap::map new_weight; mempool::osdmap::map > new_pg_temp; // [] to remove mempool::osdmap::map new_primary_temp; // [-1] to remove @@ -172,7 +409,7 @@ public: float new_backfillfull_ratio = -1; float new_full_ratio = -1; - string new_require_min_compat_client; + int8_t new_require_min_compat_client = -1; mutable bool have_crc; ///< crc values are defined uint32_t full_crc; ///< crc of the resulting OSDMap @@ -220,6 +457,39 @@ public: /// propage update pools' snap metadata to any of their tiers int propagate_snaps_to_tiers(CephContext *cct, const OSDMap &base); + + /// filter out osds with any pending state changing + size_t get_pending_state_osds(vector *osds) { + assert(osds); + osds->clear(); + + for (auto &p : new_state) { + osds->push_back(p.first); + } + + return osds->size(); + } + + bool pending_osd_has_state(int osd, unsigned state) { + return new_state.count(osd) && (new_state[osd] & state) != 0; + } + + void pending_osd_state_set(int osd, unsigned state) { + new_state[osd] |= state; + } + + // cancel the specified pending osd state if there is any + // return ture on success, false otherwise. + bool pending_osd_state_clear(int osd, unsigned state) { + if (!pending_osd_has_state(osd, state)) { + // never has been set or already has been cancelled. + return false; + } + + new_state[osd] &= ~state; + return true; + } + }; private: @@ -235,7 +505,7 @@ private: int num_in_osd; // not saved; see calc_num_osds int32_t max_osd; - vector osd_state; + vector osd_state; struct addrs_s { mempool::osdmap::vector > client_addr; @@ -248,7 +518,7 @@ private: mempool::osdmap::vector<__u32> osd_weight; // 16.16 fixed point, 0x10000 = "in", 0 = "out" mempool::osdmap::vector osd_info; - ceph::shared_ptr< mempool::osdmap::map > > pg_temp; // temp pg mapping (e.g. while we rebuild) + ceph::shared_ptr pg_temp; // temp pg mapping (e.g. while we rebuild) ceph::shared_ptr< mempool::osdmap::map > primary_temp; // temp primary mapping (e.g. while we rebuild) ceph::shared_ptr< mempool::osdmap::vector<__u32> > osd_primary_affinity; ///< 16.16 fixed point, 0x10000 = baseline @@ -273,8 +543,13 @@ private: float full_ratio = 0, backfillfull_ratio = 0, nearfull_ratio = 0; /// min compat client we want to support - string require_min_compat_client; + uint8_t require_min_compat_client = 0; // CEPH_RELEASE_* +public: + /// require osds to run at least this release + uint8_t require_osd_release = 0; // CEPH_RELEASE_* + +private: mutable uint64_t cached_up_osd_features; mutable bool crc_defined; @@ -287,6 +562,8 @@ private: uint32_t get_crc() const { return crc; } ceph::shared_ptr crush; // hierarchical map +private: + uint32_t crush_version = 1; friend class OSDMonitor; @@ -297,7 +574,7 @@ private: num_osd(0), num_up_osd(0), num_in_osd(0), max_osd(0), osd_addrs(std::make_shared()), - pg_temp(std::make_shared>>()), + pg_temp(std::make_shared()), primary_temp(std::make_shared>()), osd_uuid(std::make_shared>()), cluster_snapshot_epoch(0), @@ -317,7 +594,7 @@ public: void deepish_copy_from(const OSDMap& o) { *this = o; primary_temp.reset(new mempool::osdmap::map(*o.primary_temp)); - pg_temp.reset(new mempool::osdmap::map >(*o.pg_temp)); + pg_temp.reset(new PGTempMap(*o.pg_temp)); osd_uuid.reset(new mempool::osdmap::vector(*o.osd_uuid)); if (o.osd_primary_affinity) @@ -339,12 +616,17 @@ public: void set_epoch(epoch_t e); + uint32_t get_crush_version() const { + return crush_version; + } + /* stamps etc */ const utime_t& get_created() const { return created; } const utime_t& get_modified() const { return modified; } bool is_blacklisted(const entity_addr_t& a) const; void get_blacklist(list > *bl) const; + void get_blacklist(std::set *bl) const; string get_cluster_snapshot() const { if (cluster_snapshot_epoch == epoch) @@ -363,11 +645,15 @@ public: } void count_full_nearfull_osds(int *full, int *backfill, int *nearfull) const; void get_full_osd_util( - const ceph::unordered_map &osd_stat, + const mempool::pgmap::unordered_map &osd_stat, map *full, map *backfill, map *nearfull) const; + void get_full_osd_counts(set *full, set *backfill, + set *nearfull) const; + + /***** cluster state *****/ /* osds */ int get_max_osd() const { return max_osd; } @@ -387,6 +673,7 @@ public: void get_all_osds(set& ls) const; void get_up_osds(set& ls) const; + void get_out_osds(set& ls) const; unsigned get_num_pg_temp() const { return pg_temp->size(); } @@ -474,6 +761,10 @@ public: return osd >= 0 && osd < max_osd && (osd_state[osd] & CEPH_OSD_EXISTS); } + bool is_destroyed(int osd) const { + return exists(osd) && (osd_state[osd] & CEPH_OSD_DESTROYED); + } + bool is_up(int osd) const { return exists(osd) && (osd_state[osd] & CEPH_OSD_UP); } @@ -494,12 +785,75 @@ public: return !is_out(osd); } + bool is_noup(int osd) const { + return exists(osd) && (osd_state[osd] & CEPH_OSD_NOUP); + } + + bool is_nodown(int osd) const { + return exists(osd) && (osd_state[osd] & CEPH_OSD_NODOWN); + } + + bool is_noin(int osd) const { + return exists(osd) && (osd_state[osd] & CEPH_OSD_NOIN); + } + + bool is_noout(int osd) const { + return exists(osd) && (osd_state[osd] & CEPH_OSD_NOOUT); + } + + void get_noup_osds(vector *osds) const { + assert(osds); + osds->clear(); + + for (int i = 0; i < max_osd; i++) { + if (is_noup(i)) { + osds->push_back(i); + } + } + } + + void get_nodown_osds(vector *osds) const { + assert(osds); + osds->clear(); + + for (int i = 0; i < max_osd; i++) { + if (is_nodown(i)) { + osds->push_back(i); + } + } + } + + void get_noin_osds(vector *osds) const { + assert(osds); + osds->clear(); + + for (int i = 0; i < max_osd; i++) { + if (is_noin(i)) { + osds->push_back(i); + } + } + } + + void get_noout_osds(vector *osds) const { + assert(osds); + osds->clear(); + + for (int i = 0; i < max_osd; i++) { + if (is_noout(i)) { + osds->push_back(i); + } + } + } + /** * check if an entire crush subtree is down */ bool subtree_is_down(int id, set *down_cache) const; bool containing_subtree_is_down(CephContext *cct, int osd, int subtree_type, set *down_cache) const; + bool subtree_type_is_down(CephContext *cct, int id, int subtree_type, set *down_in_osds, set *up_in_osds, + set *subtree_up, unordered_map > *subtree_type_down) const; + int identify_osd(const entity_addr_t& addr) const; int identify_osd(const uuid_d& u) const; int identify_osd_on_all_channels(const entity_addr_t& addr) const; @@ -615,7 +969,7 @@ public: * get oldest *client* version (firefly, hammer, etc.) that can connect given * the feature bits required (according to get_features()). */ - pair get_min_compat_client() const; + uint8_t get_min_compat_client() const; /** * get intersection of features supported by up osds @@ -686,7 +1040,7 @@ public: private: /// pg -> (raw osd list) - int _pg_to_raw_osds( + void _pg_to_raw_osds( const pg_pool_t& pool, pg_t pg, vector *osds, ps_t *ppps) const; @@ -727,14 +1081,13 @@ public: * by anybody for data mapping purposes. * raw and primary must be non-NULL */ - int pg_to_raw_osds(pg_t pg, vector *raw, int *primary) const; + void pg_to_raw_osds(pg_t pg, vector *raw, int *primary) const; /// map a pg to its acting set. @return acting set size - int pg_to_acting_osds(const pg_t& pg, vector *acting, + void pg_to_acting_osds(const pg_t& pg, vector *acting, int *acting_primary) const { _pg_to_up_acting_osds(pg, NULL, NULL, acting, acting_primary); - return acting->size(); } - int pg_to_acting_osds(pg_t pg, vector& acting) const { + void pg_to_acting_osds(pg_t pg, vector& acting) const { return pg_to_acting_osds(pg, &acting, NULL); } /** @@ -870,26 +1223,26 @@ public: /* rank is -1 (stray), 0 (primary), 1,2,3,... (replica) */ int get_pg_acting_rank(pg_t pg, int osd) const { vector group; - int nrep = pg_to_acting_osds(pg, group); - return calc_pg_rank(osd, group, nrep); + pg_to_acting_osds(pg, group); + return calc_pg_rank(osd, group, group.size()); } /* role is -1 (stray), 0 (primary), 1 (replica) */ int get_pg_acting_role(const pg_t& pg, int osd) const { vector group; - int nrep = pg_to_acting_osds(pg, group); - return calc_pg_role(osd, group, nrep); + pg_to_acting_osds(pg, group); + return calc_pg_role(osd, group, group.size()); } bool osd_is_valid_op_target(pg_t pg, int osd) const { int primary; vector group; - int nrep = pg_to_acting_osds(pg, &group, &primary); + pg_to_acting_osds(pg, &group, &primary); if (osd == primary) return true; if (pg_is_ec(pg)) return false; - return calc_pg_role(osd, group, nrep) >= 0; + return calc_pg_role(osd, group, group.size()) >= 0; } int clean_pg_upmaps( @@ -912,6 +1265,8 @@ public: Incremental *pending_inc ); + int get_osds_by_bucket_name(const string &name, set *osds) const; + /* * handy helpers to build simple maps... */ @@ -935,9 +1290,10 @@ public: static int build_simple_crush_map_from_conf(CephContext *cct, CrushWrapper& crush, ostream *ss); - static int build_simple_crush_rulesets(CephContext *cct, CrushWrapper& crush, - const string& root, - ostream *ss); + static int build_simple_crush_rules( + CephContext *cct, CrushWrapper& crush, + const string& root, + ostream *ss); bool crush_ruleset_in_use(int ruleset) const; @@ -953,7 +1309,14 @@ public: void print_pools(ostream& out) const; void print_summary(Formatter *f, ostream& out) const; void print_oneline_summary(ostream& out) const; - void print_tree(Formatter *f, ostream *out) const; + + enum { + DUMP_IN = 1, // only 'in' osds + DUMP_OUT = 2, // only 'out' osds + DUMP_UP = 4, // only 'up' osds + DUMP_DOWN = 8, // only 'down' osds + }; + void print_tree(Formatter *f, ostream *out, unsigned dump_flags=0) const; int summarize_mapping_stats( OSDMap *newmap, @@ -980,5 +1343,12 @@ inline ostream& operator<<(ostream& out, const OSDMap& m) { return out; } +class PGStatService; + +void print_osd_utilization(const OSDMap& osdmap, + const PGStatService *pgstat, + ostream& out, + Formatter *f, + bool tree); #endif diff --git a/ceph/src/osd/PG.cc b/ceph/src/osd/PG.cc index 6c762db53..e75331053 100644 --- a/ceph/src/osd/PG.cc +++ b/ceph/src/osd/PG.cc @@ -167,7 +167,7 @@ void PG::put(const char* tag) { Mutex::Locker l(_ref_id_lock); auto tag_counts_entry = _tag_counts.find(tag); - assert(_tag_counts_entry != _tag_counts.end()); + assert(tag_counts_entry != _tag_counts.end()); --tag_counts_entry->second; if (tag_counts_entry->second == 0) { _tag_counts.erase(tag_counts_entry); @@ -187,7 +187,7 @@ uint64_t PG::get_with_id() BackTrace bt(0); stringstream ss; bt.print(ss); - dout(20) << __func__ << ": " << info.pgid << " got id " << id << dendl; + dout(20) << __func__ << ": " << info.pgid << " got id " << id << " (new) ref==" << ref << dendl; assert(!_live_ids.count(id)); _live_ids.insert(make_pair(id, ss.str())); return id; @@ -195,7 +195,7 @@ uint64_t PG::get_with_id() void PG::put_with_id(uint64_t id) { - dout(20) << __func__ << ": " << info.pgid << " put id " << id << dendl; + dout(20) << __func__ << ": " << info.pgid << " put id " << id << " (current) ref==" << ref << dendl; { Mutex::Locker l(_ref_id_lock); assert(_live_ids.count(id)); @@ -326,9 +326,7 @@ PG::PG(OSDService *o, OSDMapRef curmap, peer_features(CEPH_FEATURES_SUPPORTED_DEFAULT), acting_features(CEPH_FEATURES_SUPPORTED_DEFAULT), upacting_features(CEPH_FEATURES_SUPPORTED_DEFAULT), - last_epoch(0), - scrub_sleep_lock("PG::scrub_sleep_lock"), - scrub_sleep_timer(o->cct, scrub_sleep_lock, false /* relax locking */) + last_epoch(0) { #ifdef PG_DEBUG_REFS osd->add_pgid(p, this); @@ -344,8 +342,6 @@ PG::PG(OSDService *o, OSDMapRef curmap, PG::~PG() { pgstate_history.set_pg_in_destructor(); - Mutex::Locker l(scrub_sleep_lock); - scrub_sleep_timer.shutdown(); #ifdef PG_DEBUG_REFS osd->remove_pgid(info.pgid, this); #endif @@ -803,7 +799,6 @@ void PG::check_past_interval_bounds() const derr << info.pgid << " required past_interval bounds are" << " empty [" << rpib << ") but past_intervals is not: " << past_intervals << dendl; - assert(past_intervals.empty()); } } else { if (past_intervals.empty()) { @@ -1122,7 +1117,6 @@ void PG::calc_ec_acting( const vector &up, pg_shard_t up_primary, const map &all_info, - bool compat_mode, bool restrict_to_up_acting, vector *_want, set *backfill, @@ -1210,7 +1204,6 @@ void PG::calc_replicated_acting( const vector &up, pg_shard_t up_primary, const map &all_info, - bool compat_mode, bool restrict_to_up_acting, vector *want, set *backfill, @@ -1264,16 +1257,8 @@ void PG::calc_replicated_acting( * as far backwards as necessary to pick up any peers which can * be log recovered by auth_log_shard's log */ ss << " shard " << up_cand << " (up) backfill " << cur_info << std::endl; - if (compat_mode) { - if (backfill->empty()) { - backfill->insert(up_cand); - want->push_back(*i); - acting_backfill->insert(up_cand); - } - } else { - backfill->insert(up_cand); - acting_backfill->insert(up_cand); - } + backfill->insert(up_cand); + acting_backfill->insert(up_cand); } else { want->push_back(*i); acting_backfill->insert(up_cand); @@ -1393,27 +1378,6 @@ bool PG::choose_acting(pg_shard_t &auth_log_shard_id, assert(!auth_log_shard->second.is_incomplete()); auth_log_shard_id = auth_log_shard->first; - // Determine if compatibility needed - bool compat_mode = !cct->_conf->osd_debug_override_acting_compat; - if (compat_mode) { - bool all_support = true; - OSDMapRef osdmap = get_osdmap(); - - for (map::iterator it = all_info.begin(); - it != all_info.end(); - ++it) { - pg_shard_t peer = it->first; - - const osd_xinfo_t& xi = osdmap->get_xinfo(peer.osd); - if (!(xi.features & CEPH_FEATURE_OSD_ERASURE_CODES)) { - all_support = false; - break; - } - } - if (all_support) - compat_mode = false; - } - set want_backfill, want_acting_backfill; vector want; pg_shard_t want_primary; @@ -1427,7 +1391,6 @@ bool PG::choose_acting(pg_shard_t &auth_log_shard_id, up, up_primary, all_info, - compat_mode, restrict_to_up_acting, &want, &want_backfill, @@ -1443,7 +1406,6 @@ bool PG::choose_acting(pg_shard_t &auth_log_shard_id, up, up_primary, all_info, - compat_mode, restrict_to_up_acting, &want, &want_backfill, @@ -1492,7 +1454,7 @@ bool PG::choose_acting(pg_shard_t &auth_log_shard_id, if (want_acting == up) { // There can't be any pending backfill if // want is the same as crush map up OSDs. - assert(compat_mode || want_backfill.empty()); + assert(want_backfill.empty()); vector empty; osd->queue_want_pg_temp(info.pgid.pgid, empty); } else @@ -1763,7 +1725,8 @@ void PG::activate(ObjectStore::Transaction& t, for (list::iterator p = m->log.log.begin(); p != m->log.log.end(); ++p) - if (p->soid <= pi.last_backfill) + if (p->soid <= pi.last_backfill && + !p->is_error()) pm.add_next_event(*p); } @@ -1972,7 +1935,7 @@ void PG::all_activated_and_committed() AllReplicasActivated()))); } -bool PG::requeue_scrub() +bool PG::requeue_scrub(bool high_priority) { assert(is_locked()); if (scrub_queued) { @@ -1981,7 +1944,7 @@ bool PG::requeue_scrub() } else { dout(10) << __func__ << ": queueing" << dendl; scrub_queued = true; - osd->queue_for_scrub(this); + osd->queue_for_scrub(this, high_priority); return true; } } @@ -2751,7 +2714,10 @@ void PG::publish_stats_to_osd() if ((info.stats.state & PG_STATE_UNDERSIZED) == 0) info.stats.last_fullsized = now; - publish = true; + // do not send pgstat to mon anymore once we are luminous, since mgr takes + // care of this by sending MMonMgrReport to mon. + publish = + osd->osd->get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS; pg_stats_publish_valid = true; pg_stats_publish = pre_publish; @@ -2832,8 +2798,6 @@ void PG::init( dirty_info = true; dirty_big_info = true; write_if_dirty(*t); - - scrub_sleep_timer.init(); } #pragma GCC diagnostic ignored "-Wpragmas" @@ -3700,7 +3664,11 @@ void PG::do_replica_scrub_map(OpRequestRef op) --scrubber.waiting_on; scrubber.waiting_on_whom.erase(m->from); if (scrubber.waiting_on == 0) { - requeue_scrub(); + if (ops_blocked_by_scrub()) { + requeue_scrub(true); + } else { + requeue_scrub(false); + } } } @@ -3736,7 +3704,11 @@ void PG::sub_op_scrub_map(OpRequestRef op) scrubber.waiting_on_whom.erase(m->from); if (scrubber.waiting_on == 0) { - requeue_scrub(); + if (ops_blocked_by_scrub()) { + requeue_scrub(true); + } else { + requeue_scrub(false); + } } } @@ -4240,24 +4212,39 @@ void PG::scrub(epoch_t queued, ThreadPool::TPHandle &handle) { if (cct->_conf->osd_scrub_sleep > 0 && (scrubber.state == PG::Scrubber::NEW_CHUNK || - scrubber.state == PG::Scrubber::INACTIVE) && scrubber.needs_sleep) { + scrubber.state == PG::Scrubber::INACTIVE) && + scrubber.needs_sleep) { ceph_assert(!scrubber.sleeping); dout(20) << __func__ << " state is INACTIVE|NEW_CHUNK, sleeping" << dendl; + // Do an async sleep so we don't block the op queue - auto scrub_requeue_callback = new FunctionContext([this](int r) { - lock(); - scrubber.sleeping = false; - scrubber.needs_sleep = false; - dout(20) << __func__ << " slept for " - << ceph_clock_now() - scrubber.sleep_start - << ", re-queuing scrub" << dendl; - scrub_queued = false; - requeue_scrub(); - scrubber.sleep_start = utime_t(); - unlock(); - }); - Mutex::Locker l(scrub_sleep_lock); - scrub_sleep_timer.add_event_after(cct->_conf->osd_scrub_sleep, scrub_requeue_callback); + OSDService *osds = osd; + spg_t pgid = get_pgid(); + int state = scrubber.state; + auto scrub_requeue_callback = + new FunctionContext([osds, pgid, state](int r) { + PG *pg = osds->osd->lookup_lock_pg(pgid); + if (pg == nullptr) { + lgeneric_dout(osds->osd->cct, 20) + << "scrub_requeue_callback: Could not find " + << "PG " << pgid << " can't complete scrub requeue after sleep" + << dendl; + return; + } + pg->scrubber.sleeping = false; + pg->scrubber.needs_sleep = false; + lgeneric_dout(pg->cct, 20) + << "scrub_requeue_callback: slept for " + << ceph_clock_now() - pg->scrubber.sleep_start + << ", re-queuing scrub with state " << state << dendl; + pg->scrub_queued = false; + pg->requeue_scrub(); + pg->scrubber.sleep_start = utime_t(); + pg->unlock(); + }); + Mutex::Locker l(osd->scrub_sleep_lock); + osd->scrub_sleep_timer.add_event_after(cct->_conf->osd_scrub_sleep, + scrub_requeue_callback); scrubber.sleeping = true; scrubber.sleep_start = ceph_clock_now(); return; @@ -4818,6 +4805,10 @@ bool PG::scrub_process_inconsistent() return (!scrubber.authoritative.empty() && repair); } +bool PG::ops_blocked_by_scrub() const { + return (waiting_for_scrub.size() != 0); +} + // the part that actually finalizes a scrub void PG::scrub_finish() { @@ -4949,7 +4940,7 @@ void PG::share_pg_info() } bool PG::append_log_entries_update_missing( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, ObjectStore::Transaction &t) { assert(!entries.empty()); @@ -4976,7 +4967,7 @@ bool PG::append_log_entries_update_missing( void PG::merge_new_log_entries( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, ObjectStore::Transaction &t) { dout(10) << __func__ << " " << entries << dendl; diff --git a/ceph/src/osd/PG.h b/ceph/src/osd/PG.h index 5493a5004..e93549e9f 100644 --- a/ceph/src/osd/PG.h +++ b/ceph/src/osd/PG.h @@ -942,7 +942,6 @@ protected: public: void clear_primary_state(); - public: bool is_actingbackfill(pg_shard_t osd) const { return actingbackfill.count(osd); } @@ -976,11 +975,11 @@ public: epoch_t oldest_map) { epoch_t start = MAX( info.history.last_epoch_clean ? info.history.last_epoch_clean : - info.history.epoch_created, + info.history.epoch_pool_created, oldest_map); epoch_t end = MAX( info.history.same_interval_since, - info.history.epoch_created); + info.history.epoch_pool_created); return make_pair(start, end); } void check_past_interval_bounds() const; @@ -1080,7 +1079,6 @@ public: const vector &up, pg_shard_t up_primary, const map &all_info, - bool compat_mode, bool restrict_to_up_acting, vector *want, set *backfill, @@ -1095,7 +1093,6 @@ public: const vector &up, pg_shard_t up_primary, const map &all_info, - bool compat_mode, bool restrict_to_up_acting, vector *want, set *backfill, @@ -1347,6 +1344,7 @@ public: * return true if any inconsistency/missing is repaired, false otherwise */ bool scrub_process_inconsistent(); + bool ops_blocked_by_scrub() const; void scrub_finish(); void scrub_clear_state(); void _scan_snaps(ScrubMap &map); @@ -2199,9 +2197,6 @@ public: epoch_t last_epoch; - Mutex scrub_sleep_lock; - SafeTimer scrub_sleep_timer; - public: const spg_t& get_pgid() const { return pg_id; } @@ -2378,7 +2373,7 @@ public: virtual void kick_snap_trim() = 0; virtual void snap_trimmer_scrub_complete() = 0; - bool requeue_scrub(); + bool requeue_scrub(bool high_priority = false); void queue_recovery(bool front = false); bool queue_scrub(); unsigned get_scrub_priority(); @@ -2388,7 +2383,7 @@ public: bool append_log_entries_update_missing( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, ObjectStore::Transaction &t); /** @@ -2396,7 +2391,7 @@ public: * actingbackfill logs and missings (also missing_loc) */ void merge_new_log_entries( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, ObjectStore::Transaction &t); void reset_interval_flush(); diff --git a/ceph/src/osd/PGBackend.cc b/ceph/src/osd/PGBackend.cc index fab9ee826..97a7f07ba 100644 --- a/ceph/src/osd/PGBackend.cc +++ b/ceph/src/osd/PGBackend.cc @@ -620,10 +620,21 @@ map::const_iterator eversion_t auth_version; bufferlist auth_bl; - map::const_iterator auth = maps.end(); + // Create list of shards with primary last so it will be auth copy all + // other things being equal. + list shards; for (map::const_iterator j = maps.begin(); j != maps.end(); ++j) { + if (j->first == get_parent()->whoami_shard()) + continue; + shards.push_back(j->first); + } + shards.push_back(get_parent()->whoami_shard()); + + map::const_iterator auth = maps.end(); + for (auto &l : shards) { + map::const_iterator j = maps.find(l); map::iterator i = j->second->objects.find(obj); if (i == j->second->objects.end()) { @@ -647,6 +658,8 @@ map::const_iterator object_info_t oi; bufferlist bl; map::iterator k; + SnapSet ss; + bufferlist ss_bl; if (i->second.stat_error) { shard_info.set_stat_error(); @@ -674,6 +687,12 @@ map::const_iterator goto out; } + if (oi.soid != obj) { + shard_info.set_oi_attr_corrupted(); + error_string += " oi_attr_corrupted"; + goto out; + } + if (auth_version != eversion_t()) { if (!object_error.has_object_info_inconsistency() && !(bl == auth_bl)) { object_error.set_object_info_inconsistency(); @@ -686,6 +705,23 @@ map::const_iterator if (i->second.read_error || i->second.ec_hash_mismatch || i->second.ec_size_mismatch) goto out; + // We don't set errors here for snapset, but we won't pick an auth copy if the + // snapset is missing or won't decode. + if (obj.is_head() || obj.is_snapdir()) { + k = i->second.attrs.find(SS_ATTR); + if (k == i->second.attrs.end()) { + goto out; + } + ss_bl.push_back(k->second); + try { + bufferlist::iterator bliter = ss_bl.begin(); + ::decode(ss, bliter); + } catch (...) { + // invalid snapset, probably corrupt + goto out; + } + } + if (auth_version == eversion_t() || oi.version > auth_version || (oi.version == auth_version && dcount(oi) > dcount(*auth_oi))) { auth = j; @@ -750,6 +786,7 @@ void PGBackend::be_compare_scrubmaps( be_select_auth_object(*k, maps, &auth_oi, shard_map, object_error); list auth_list; + set object_errors; if (auth == maps.end()) { object_error.set_version(0); object_error.set_auth_missing(*k, maps, shard_map, shallow_errors, deep_errors); @@ -793,6 +830,10 @@ void PGBackend::be_compare_scrubmaps( if (found) errorstream << pgid << " shard " << j->first << ": soid " << *k << " " << ss.str() << "\n"; + } else if (found) { + // Track possible shard to use as authoritative, if needed + // There are errors, without identifying the shard + object_errors.insert(j->first); } else { // XXX: The auth shard might get here that we don't know // that it has the "correct" data. @@ -810,10 +851,25 @@ void PGBackend::be_compare_scrubmaps( } if (auth_list.empty()) { - errorstream << pgid.pgid << " soid " << *k + if (object_errors.empty()) { + errorstream << pgid.pgid << " soid " << *k << ": failed to pick suitable auth object\n"; - goto out; + goto out; + } + // Object errors exist and nothing in auth_list + // Prefer the auth shard otherwise take first from list. + pg_shard_t shard; + if (object_errors.count(auth->first)) { + shard = auth->first; + } else { + shard = *(object_errors.begin()); + } + auth_list.push_back(shard); + object_errors.erase(shard); } + // At this point auth_list is populated, so we add the object errors shards + // as inconsistent. + cur_inconsistent.insert(object_errors.begin(), object_errors.end()); if (!cur_missing.empty()) { missing[*k] = cur_missing; } diff --git a/ceph/src/osd/PGLog.cc b/ceph/src/osd/PGLog.cc index 63e1cdfc0..e85c6cc33 100644 --- a/ceph/src/osd/PGLog.cc +++ b/ceph/src/osd/PGLog.cc @@ -368,7 +368,7 @@ void PGLog::merge_log(pg_info_t &oinfo, pg_log_t &olog, pg_shard_t fromosd, } log.roll_forward_to(log.head, rollbacker); - mempool::osd::list new_entries; + mempool::osd_pglog::list new_entries; new_entries.splice(new_entries.end(), olog.log, from, to); append_log_entries_update_missing( info.last_backfill, diff --git a/ceph/src/osd/PGLog.h b/ceph/src/osd/PGLog.h index e4d0fa304..05ff7faf4 100644 --- a/ceph/src/osd/PGLog.h +++ b/ceph/src/osd/PGLog.h @@ -97,7 +97,7 @@ public: * It's a reverse_iterator because rend() is a natural representation for * tail, and rbegin() works nicely for head. */ - mempool::osd::list::reverse_iterator + mempool::osd_pglog::list::reverse_iterator rollback_info_trimmed_to_riter; template @@ -179,7 +179,7 @@ public: advance_can_rollback_to(head, [&](const pg_log_entry_t &entry) {}); } - mempool::osd::list rewind_from_head(eversion_t newhead) { + mempool::osd_pglog::list rewind_from_head(eversion_t newhead) { auto divergent = pg_log_t::rewind_from_head(newhead); index(); reset_rollback_info_trimmed_to_riter(); @@ -284,8 +284,7 @@ public: } p = extra_caller_ops.find(r); if (p != extra_caller_ops.end()) { - for (vector >::const_iterator i = - p->second->extra_reqids.begin(); + for (auto i = p->second->extra_reqids.begin(); i != p->second->extra_reqids.end(); ++i) { if (i->first == r) { @@ -302,7 +301,7 @@ public: /// get a (bounded) list of recent reqids for the given object void get_object_reqids(const hobject_t& oid, unsigned max, - vector > *pls) const { + mempool::osd_pglog::vector > *pls) const { // make sure object is present at least once before we do an // O(n) search. if (!(indexed_data & PGLOG_INDEXED_OBJECTS)) { @@ -351,8 +350,7 @@ public: } if (to_index & PGLOG_INDEXED_EXTRA_CALLER_OPS) { - for (vector >::const_iterator j = - i->extra_reqids.begin(); + for (auto j = i->extra_reqids.begin(); j != i->extra_reqids.end(); ++j) { extra_caller_ops.insert( @@ -389,8 +387,7 @@ public: } } if (indexed_data & PGLOG_INDEXED_EXTRA_CALLER_OPS) { - for (vector >::const_iterator j = - e.extra_reqids.begin(); + for (auto j = e.extra_reqids.begin(); j != e.extra_reqids.end(); ++j) { extra_caller_ops.insert(make_pair(j->first, &e)); @@ -417,8 +414,7 @@ public: } } if (indexed_data & PGLOG_INDEXED_EXTRA_CALLER_OPS) { - for (vector >::const_iterator j = - e.extra_reqids.begin(); + for (auto j = e.extra_reqids.begin(); j != e.extra_reqids.end(); ++j) { for (ceph::unordered_multimap::iterator k = @@ -440,6 +436,9 @@ public: assert(get_can_rollback_to() == head); } + // make sure our buffers don't pin bigger buffers + e.mod_desc.trim_bl(); + // add to log log.push_back(e); @@ -462,8 +461,7 @@ public: } if (indexed_data & PGLOG_INDEXED_EXTRA_CALLER_OPS) { - for (vector >::const_iterator j = - e.extra_reqids.begin(); + for (auto j = e.extra_reqids.begin(); j != e.extra_reqids.end(); ++j) { extra_caller_ops.insert(make_pair(j->first, &(log.back()))); @@ -586,10 +584,6 @@ public: missing.add(oid, need, have); } - void missing_add_event(const pg_log_entry_t &e) { - missing.add_next_event(e); - } - //////////////////// get or set log //////////////////// const IndexedLog &get_log() const { return log; } @@ -709,10 +703,10 @@ public: protected: static void split_by_object( - mempool::osd::list &entries, - map> *out_entries) { + mempool::osd_pglog::list &entries, + map> *out_entries) { while (!entries.empty()) { - mempool::osd::list &out_list = (*out_entries)[entries.front().soid]; + auto &out_list = (*out_entries)[entries.front().soid]; out_list.splice(out_list.end(), entries, entries.begin()); } } @@ -741,7 +735,7 @@ protected: static void _merge_object_divergent_entries( const IndexedLog &log, ///< [in] log to merge against const hobject_t &hoid, ///< [in] object we are merging - const mempool::osd::list &entries, ///< [in] entries for hoid to merge + const mempool::osd_pglog::list &orig_entries, ///< [in] entries for hoid to merge const pg_info_t &info, ///< [in] info for merging entries eversion_t olog_can_rollback_to, ///< [in] rollback boundary missing_type &missing, ///< [in,out] missing to adjust, use @@ -749,7 +743,7 @@ protected: const DoutPrefixProvider *dpp ///< [in] logging provider ) { ldpp_dout(dpp, 20) << __func__ << ": merging hoid " << hoid - << " entries: " << entries << dendl; + << " entries: " << orig_entries << dendl; if (hoid > info.last_backfill) { ldpp_dout(dpp, 10) << __func__ << ": hoid " << hoid << " after last_backfill" @@ -758,20 +752,32 @@ protected: } // entries is non-empty - assert(!entries.empty()); + assert(!orig_entries.empty()); + // strip out and ignore ERROR entries + mempool::osd_pglog::list entries; eversion_t last; - for (list::const_iterator i = entries.begin(); - i != entries.end(); + for (list::const_iterator i = orig_entries.begin(); + i != orig_entries.end(); ++i) { // all entries are on hoid assert(i->soid == hoid); - if (i != entries.begin() && i->prior_version != eversion_t()) { + if (i != orig_entries.begin() && i->prior_version != eversion_t()) { // in increasing order of version assert(i->version > last); - // prior_version correct - assert(i->prior_version == last); + // prior_version correct (unless it is an ERROR entry) + assert(i->prior_version == last || i->is_error()); } last = i->version; + if (i->is_error()) { + ldpp_dout(dpp, 20) << __func__ << ": ignoring " << *i << dendl; + } else { + ldpp_dout(dpp, 20) << __func__ << ": keeping " << *i << dendl; + entries.push_back(*i); + } + } + if (entries.empty()) { + ldpp_dout(dpp, 10) << __func__ << ": no non-ERROR entries" << dendl; + return; } const eversion_t prior_version = entries.begin()->prior_version; @@ -923,16 +929,16 @@ protected: template static void _merge_divergent_entries( const IndexedLog &log, ///< [in] log to merge against - mempool::osd::list &entries, ///< [in] entries to merge + mempool::osd_pglog::list &entries, ///< [in] entries to merge const pg_info_t &oinfo, ///< [in] info for merging entries eversion_t olog_can_rollback_to, ///< [in] rollback boundary missing_type &omissing, ///< [in,out] missing to adjust, use LogEntryHandler *rollbacker, ///< [in] optional rollbacker object const DoutPrefixProvider *dpp ///< [in] logging provider ) { - map > split; + map > split; split_by_object(entries, &split); - for (map>::iterator i = split.begin(); + for (map>::iterator i = split.begin(); i != split.end(); ++i) { _merge_object_divergent_entries( @@ -956,7 +962,7 @@ protected: const pg_log_entry_t& oe, const pg_info_t& info, LogEntryHandler *rollbacker) { - mempool::osd::list entries; + mempool::osd_pglog::list entries; entries.push_back(oe); _merge_object_divergent_entries( log, @@ -985,7 +991,7 @@ public: static bool append_log_entries_update_missing( const hobject_t &last_backfill, bool last_backfill_bitwise, - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, bool maintain_rollback, IndexedLog *log, missing_type &missing, @@ -1021,7 +1027,7 @@ public: bool append_new_log_entries( const hobject_t &last_backfill, bool last_backfill_bitwise, - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, LogEntryHandler *rollbacker) { bool invalidate_stats = append_log_entries_update_missing( last_backfill, diff --git a/ceph/src/osd/PrimaryLogPG.cc b/ceph/src/osd/PrimaryLogPG.cc index 8c4f08c70..b50624963 100644 --- a/ceph/src/osd/PrimaryLogPG.cc +++ b/ceph/src/osd/PrimaryLogPG.cc @@ -1877,15 +1877,15 @@ void PrimaryLogPG::do_op(OpRequestRef& op) } } - if (op->includes_pg_op()) { - return do_pg_op(op); - } - if (!op_has_sufficient_caps(op)) { osd->reply_op_error(op, -EPERM); return; } + if (op->includes_pg_op()) { + return do_pg_op(op); + } + // object name too long? if (m->get_oid().name.size() > cct->_conf->osd_max_object_name_len) { dout(4) << "do_op name is longer than " @@ -2150,6 +2150,13 @@ void PrimaryLogPG::do_op(OpRequestRef& op) return; } + if (obc.get() && obc->obs.exists && obc->obs.oi.has_manifest()) { + if (maybe_handle_manifest(op, + write_ordered, + obc)) + return; + } + if (maybe_handle_cache(op, write_ordered, obc, @@ -2168,7 +2175,7 @@ void PrimaryLogPG::do_op(OpRequestRef& op) } dout(20) << __func__ << "find_object_context got error " << r << dendl; if (op->may_write() && - get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + get_osdmap()->require_osd_release >= CEPH_RELEASE_KRAKEN) { record_write_error(op, oid, nullptr, r); } else { osd->reply_op_error(op, r); @@ -2245,7 +2252,7 @@ void PrimaryLogPG::do_op(OpRequestRef& op) dout(20) << __func__ << " returned an error: " << r << dendl; close_op_ctx(ctx); if (op->may_write() && - get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + get_osdmap()->require_osd_release >= CEPH_RELEASE_KRAKEN) { record_write_error(op, oid, nullptr, r); } else { osd->reply_op_error(op, r); @@ -2296,6 +2303,53 @@ void PrimaryLogPG::do_op(OpRequestRef& op) // force recovery of the oldest missing object if too many logs maybe_force_recovery(); } +PrimaryLogPG::cache_result_t PrimaryLogPG::maybe_handle_manifest_detail( + OpRequestRef op, + bool write_ordered, + ObjectContextRef obc) +{ + if (static_cast(op->get_req())->get_flags() & + CEPH_OSD_FLAG_IGNORE_REDIRECT) { + dout(20) << __func__ << ": ignoring redirect due to flag" << dendl; + return cache_result_t::NOOP; + } + + if (obc) + dout(10) << __func__ << " " << obc->obs.oi << " " + << (obc->obs.exists ? "exists" : "DNE") + << dendl; + + // if it is write-ordered and blocked, stop now + if (obc.get() && obc->is_blocked() && write_ordered) { + // we're already doing something with this object + dout(20) << __func__ << " blocked on " << obc->obs.oi.soid << dendl; + return cache_result_t::NOOP; + } + + vector ops = static_cast(op->get_req())->ops; + for (vector::iterator p = ops.begin(); p != ops.end(); ++p) { + OSDOp& osd_op = *p; + ceph_osd_op& op = osd_op.op; + if (op.op == CEPH_OSD_OP_SET_REDIRECT) { + return cache_result_t::NOOP; + } + } + + switch (obc->obs.oi.manifest.type) { + case object_manifest_t::TYPE_REDIRECT: + if (op->may_write() || write_ordered) { + do_proxy_write(op, obc->obs.oi.soid, obc); + } else { + do_proxy_read(op, obc); + } + return cache_result_t::HANDLED_PROXY; + case object_manifest_t::TYPE_CHUNKED: + default: + assert(0 == "unrecognized manifest type"); + } + + return cache_result_t::NOOP; +} void PrimaryLogPG::record_write_error(OpRequestRef op, const hobject_t &soid, MOSDOpReply *orig_reply, int r) @@ -2304,7 +2358,7 @@ void PrimaryLogPG::record_write_error(OpRequestRef op, const hobject_t &soid, assert(op->may_write()); const osd_reqid_t &reqid = static_cast(op->get_req())->get_reqid(); ObjectContextRef obc; - mempool::osd::list entries; + mempool::osd_pglog::list entries; entries.push_back(pg_log_entry_t(pg_log_entry_t::ERROR, soid, get_next_version(), eversion_t(), 0, reqid, utime_t(), r)); @@ -2657,15 +2711,30 @@ struct C_ProxyRead : public Context { } }; -void PrimaryLogPG::do_proxy_read(OpRequestRef op) +void PrimaryLogPG::do_proxy_read(OpRequestRef op, ObjectContextRef obc) { // NOTE: non-const here because the ProxyReadOp needs mutable refs to // stash the result in the request's OSDOp vector MOSDOp *m = static_cast(op->get_nonconst_req()); - object_locator_t oloc(m->get_object_locator()); - oloc.pool = pool.info.tier_of; - - const hobject_t& soid = m->get_hobj(); + object_locator_t oloc; + hobject_t soid; + /* extensible tier */ + if (obc && obc->obs.exists && obc->obs.oi.has_manifest()) { + switch (obc->obs.oi.manifest.type) { + case object_manifest_t::TYPE_REDIRECT: + oloc = object_locator_t(obc->obs.oi.manifest.redirect_target); + soid = obc->obs.oi.manifest.redirect_target; + break; + case object_manifest_t::TYPE_CHUNKED: + default: + assert(0 == "unrecognized manifest type"); + } + } else { + /* proxy */ + soid = m->get_hobj(); + oloc = object_locator_t(m->get_object_locator()); + oloc.pool = pool.info.tier_of; + } unsigned flags = CEPH_OSD_FLAG_IGNORE_CACHE | CEPH_OSD_FLAG_IGNORE_OVERLAY; // pass through some original flags that make sense. @@ -2849,16 +2918,35 @@ struct C_ProxyWrite_Commit : public Context { } }; -void PrimaryLogPG::do_proxy_write(OpRequestRef op, const hobject_t& missing_oid) +void PrimaryLogPG::do_proxy_write(OpRequestRef op, const hobject_t& missing_oid, ObjectContextRef obc) { // NOTE: non-const because ProxyWriteOp takes a mutable ref MOSDOp *m = static_cast(op->get_nonconst_req()); - object_locator_t oloc(m->get_object_locator()); - oloc.pool = pool.info.tier_of; + object_locator_t oloc; SnapContext snapc(m->get_snap_seq(), m->get_snaps()); + hobject_t soid; + /* extensible tier */ + if (obc && obc->obs.exists && obc->obs.oi.has_manifest()) { + switch (obc->obs.oi.manifest.type) { + case object_manifest_t::TYPE_REDIRECT: + oloc = object_locator_t(obc->obs.oi.manifest.redirect_target); + soid = obc->obs.oi.manifest.redirect_target; + break; + case object_manifest_t::TYPE_CHUNKED: + default: + assert(0 == "unrecognized manifest type"); + } + } else { + /* proxy */ + soid = m->get_hobj(); + oloc = object_locator_t(m->get_object_locator()); + oloc.pool = pool.info.tier_of; + } - const hobject_t& soid = m->get_hobj(); unsigned flags = CEPH_OSD_FLAG_IGNORE_CACHE | CEPH_OSD_FLAG_IGNORE_OVERLAY; + if (!(op->may_write() || op->may_cache())) { + flags |= CEPH_OSD_FLAG_RWORDERED; + } dout(10) << __func__ << " Start proxy write for " << *m << dendl; ProxyWriteOpRef pwop(std::make_shared(op, soid, m->ops, m->get_reqid())); @@ -3546,7 +3634,7 @@ PrimaryLogPG::OpContextUPtr PrimaryLogPG::trim_object( SnapSet& snapset = obc->ssc->snapset; bool legacy = snapset.is_legacy() || - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS); + get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS; object_info_t &coi = obc->obs.oi; set old_snaps; @@ -3679,6 +3767,9 @@ PrimaryLogPG::OpContextUPtr PrimaryLogPG::trim_object( coid, old_snaps, new_snaps); + + coi = object_info_t(coid); + ctx->at_version.version++; } else { // save adjusted snaps for this object @@ -3747,20 +3838,19 @@ PrimaryLogPG::OpContextUPtr PrimaryLogPG::trim_object( ctx->delta_stats.num_objects--; if (oi.is_dirty()) { ctx->delta_stats.num_objects_dirty--; - oi.clear_flag(object_info_t::FLAG_DIRTY); } if (oi.is_omap()) ctx->delta_stats.num_objects_omap--; if (oi.is_whiteout()) { dout(20) << __func__ << " trimming whiteout on " << oi.soid << dendl; ctx->delta_stats.num_whiteouts--; - oi.clear_flag(object_info_t::FLAG_WHITEOUT); } - if (oi.is_cache_pinned()) + if (oi.is_cache_pinned()) { ctx->delta_stats.num_objects_pinned--; + } } ctx->snapset_obc->obs.exists = false; - + ctx->snapset_obc->obs.oi = object_info_t(snapoid); t->remove(snapoid); } else { dout(10) << coid << " filtering snapset on " << snapoid << dendl; @@ -4576,6 +4666,7 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector& ops) case CEPH_OSD_OP_COPY_FROM: // we handle user_version update explicitly case CEPH_OSD_OP_CACHE_PIN: case CEPH_OSD_OP_CACHE_UNPIN: + case CEPH_OSD_OP_SET_REDIRECT: break; default: if (op.op & CEPH_OSD_OP_MODE_WR) @@ -5831,6 +5922,75 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector& ops) } break; + case CEPH_OSD_OP_SET_REDIRECT: + ++ctx->num_write; + { + if (pool.info.is_tier()) { + result = -EINVAL; + break; + } + if (!obs.exists) { + result = -ENOENT; + break; + } + if (get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS) { + result = -EOPNOTSUPP; + break; + } + + object_t target_name; + object_locator_t target_oloc; + snapid_t target_snapid = (uint64_t)op.copy_from.snapid; + version_t target_version = op.copy_from.src_version; + try { + ::decode(target_name, bp); + ::decode(target_oloc, bp); + } + catch (buffer::error& e) { + result = -EINVAL; + goto fail; + } + pg_t raw_pg; + get_osdmap()->object_locator_to_pg(target_name, target_oloc, raw_pg); + hobject_t target(target_name, target_oloc.key, target_snapid, + raw_pg.ps(), raw_pg.pool(), + target_oloc.nspace); + if (target == soid) { + dout(20) << " set-redirect self is invalid" << dendl; + result = -EINVAL; + break; + } + oi.set_flag(object_info_t::FLAG_MANIFEST); + oi.manifest.redirect_target = target; + oi.manifest.type = object_manifest_t::TYPE_REDIRECT; + t->truncate(soid, 0); + if (oi.is_omap() && pool.info.supports_omap()) { + t->omap_clear(soid); + obs.oi.clear_omap_digest(); + obs.oi.clear_flag(object_info_t::FLAG_OMAP); + } + ctx->delta_stats.num_bytes -= oi.size; + oi.size = 0; + oi.new_object(); + oi.user_version = target_version; + ctx->user_at_version = target_version; + /* rm_attrs */ + map rmattrs; + result = getattrs_maybe_cache(ctx->obc, + &rmattrs, + true); + if (result < 0) { + return result; + } + map::iterator iter; + for (iter = rmattrs.begin(); iter != rmattrs.end(); ++iter) { + const string& name = iter->first; + t->rmattr(soid, name); + } + dout(10) << "set-redirect oid:" << oi.soid << " user_version: " << oi.user_version << dendl; + } + + break; // -- object attrs -- @@ -6476,7 +6636,7 @@ inline int PrimaryLogPG::_delete_oid( whiteout = true; } bool legacy; - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_LUMINOUS) { legacy = false; // in luminous or later, we can't delete the head if there are // clones. we trust the caller passing no_whiteout has already @@ -6586,16 +6746,26 @@ int PrimaryLogPG::_rollback_to(OpContext *ctx, ceph_osd_op& op) } { ObjectContextRef promote_obc; - switch ( - maybe_handle_cache_detail( - ctx->op, - true, - rollback_to, - ret, - missing_oid, - true, - false, - &promote_obc)) { + cache_result_t tier_mode_result; + if (obs.exists && obs.oi.has_manifest()) { + tier_mode_result = + maybe_handle_manifest_detail( + ctx->op, + true, + rollback_to); + } else { + tier_mode_result = + maybe_handle_cache_detail( + ctx->op, + true, + rollback_to, + ret, + missing_oid, + true, + false, + &promote_obc); + } + switch (tier_mode_result) { case cache_result_t::NOOP: break; case cache_result_t::BLOCKED_PROMOTE: @@ -6807,7 +6977,7 @@ void PrimaryLogPG::make_writeable(OpContext *ctx) snap_oi->copy_user_bits(ctx->obs->oi); bool legacy = ctx->new_snapset.is_legacy() || - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS); + get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS; if (legacy) { snap_oi->legacy_snaps = snaps; } @@ -6868,7 +7038,7 @@ void PrimaryLogPG::make_writeable(OpContext *ctx) // update snapset with latest snap context ctx->new_snapset.seq = snapc.seq; ctx->new_snapset.snaps = snapc.snaps; - if (!get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS) { // pessimistic assumption that this is a net-new legacy SnapSet ctx->delta_stats.num_legacy_snapsets++; ctx->new_snapset.head_exists = ctx->new_obs.exists; @@ -7056,7 +7226,7 @@ int PrimaryLogPG::prepare_transaction(OpContext *ctx) int result = do_osd_ops(ctx, ctx->ops); if (result < 0) { if (ctx->op->may_write() && - get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + get_osdmap()->require_osd_release >= CEPH_RELEASE_KRAKEN) { // need to save the error code in the pg log, to detect dup ops, // but do nothing else ctx->update_log_only = true; @@ -7068,7 +7238,7 @@ int PrimaryLogPG::prepare_transaction(OpContext *ctx) if (ctx->op_t->empty() && !ctx->modify) { unstable_stats.add(ctx->delta_stats); if (ctx->op->may_write() && - get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + get_osdmap()->require_osd_release >= CEPH_RELEASE_KRAKEN) { ctx->update_log_only = true; } return result; @@ -7147,7 +7317,7 @@ void PrimaryLogPG::finish_ctx(OpContext *ctx, int log_op_type, bool maintain_ssc info.pgid.pool(), soid.get_namespace()); dout(10) << " final snapset " << ctx->new_snapset << " in " << snapoid << dendl; - assert(!get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)); + assert(get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS); ctx->log.push_back(pg_log_entry_t(pg_log_entry_t::MODIFY, snapoid, ctx->at_version, eversion_t(), @@ -7235,7 +7405,7 @@ void PrimaryLogPG::finish_ctx(OpContext *ctx, int log_op_type, bool maintain_ssc } bool legacy_snapset = ctx->new_snapset.is_legacy() || - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS); + get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS; // append to log ctx->log.push_back(pg_log_entry_t(log_op_type, soid, ctx->at_version, @@ -8147,7 +8317,7 @@ void PrimaryLogPG::finish_promote(int r, CopyResults *results, tctx->extra_reqids = results->reqids; bool legacy_snapset = tctx->new_snapset.is_legacy() || - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS); + get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS; if (whiteout) { // create a whiteout @@ -8200,7 +8370,7 @@ void PrimaryLogPG::finish_promote(int r, CopyResults *results, assert(tctx->new_obs.oi.soid.snap == CEPH_NOSNAP); tctx->new_snapset.from_snap_set( results->snapset, - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)); + get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS); } tctx->new_snapset.head_exists = true; dout(20) << __func__ << " new_snapset " << tctx->new_snapset << dendl; @@ -8785,7 +8955,12 @@ void PrimaryLogPG::op_applied(const eversion_t &applied_version) if (is_primary()) { if (scrubber.active) { if (last_update_applied == scrubber.subset_last_update) { - requeue_scrub(); + if (ops_blocked_by_scrub()) { + requeue_scrub(true); + } else { + requeue_scrub(false); + } + } } else { assert(scrubber.start == scrubber.end); @@ -9045,7 +9220,7 @@ void PrimaryLogPG::simple_opc_submit(OpContextUPtr ctx) void PrimaryLogPG::submit_log_entries( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, ObcLockManager &&manager, boost::optional > &&_on_complete, OpRequestRef op, @@ -9062,7 +9237,7 @@ void PrimaryLogPG::submit_log_entries( boost::intrusive_ptr repop; boost::optional > on_complete; - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_JEWEL) { repop = new_repop( version, r, @@ -9088,7 +9263,7 @@ void PrimaryLogPG::submit_log_entries( if (peer == pg_whoami) continue; assert(peer_missing.count(peer)); assert(peer_info.count(peer)); - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_JEWEL) { assert(repop); MOSDPGUpdateLogMissing *m = new MOSDPGUpdateLogMissing( entries, @@ -9112,7 +9287,7 @@ void PrimaryLogPG::submit_log_entries( peer.osd, m, get_osdmap()->get_epoch()); } } - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_JEWEL) { ceph_tid_t rep_tid = repop->rep_tid; waiting_on.insert(pg_whoami); log_entry_update_waiting_on.insert( @@ -10016,7 +10191,11 @@ void PrimaryLogPG::_applied_recovered_object(ObjectContextRef obc) // requeue an active chunky scrub waiting on recovery ops if (!deleting && active_pushes == 0 && scrubber.is_chunky_scrub_active()) { - requeue_scrub(); + if (ops_blocked_by_scrub()) { + requeue_scrub(true); + } else { + requeue_scrub(false); + } } unlock(); @@ -10149,7 +10328,7 @@ void PrimaryLogPG::do_update_log_missing(OpRequestRef &op) unlock(); }); - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_KRAKEN) { t.register_on_commit(complete); } else { /* Hack to work around the fact that ReplicatedBackend sends @@ -10215,7 +10394,7 @@ void PrimaryLogPG::mark_all_unfound_lost( pg_log.get_log().print(*_dout); *_dout << dendl; - mempool::osd::list log_entries; + mempool::osd_pglog::list log_entries; utime_t mtime = ceph_clock_now(); map::const_iterator m = @@ -10265,7 +10444,7 @@ void PrimaryLogPG::mark_all_unfound_lost( { pg_log_entry_t e(pg_log_entry_t::LOST_DELETE, oid, v, m->second.need, 0, osd_reqid_t(), mtime, 0); - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_JEWEL) { if (pool.info.require_rollback()) { e.mod_desc.try_rmobject(v.version); } else { @@ -10444,6 +10623,10 @@ void PrimaryLogPG::on_shutdown() cancel_proxy_ops(false); apply_and_flush_repops(false); cancel_log_updates(); + // we must remove PGRefs, so do this this prior to release_backoffs() callers + clear_backoffs(); + // clean up snap trim references + snap_trimmer_machine.process_event(Reset()); pgbackend->on_change(); @@ -13329,7 +13512,7 @@ void PrimaryLogPG::scrub_snapshot_metadata( head_error.set_head_mismatch(); } - if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)) { + if (get_osdmap()->require_osd_release >= CEPH_RELEASE_LUMINOUS) { if (soid.is_snapdir()) { dout(10) << " will move snapset to head from " << soid << dendl; snapset_to_repair[soid.get_head()] = *snapset; diff --git a/ceph/src/osd/PrimaryLogPG.h b/ceph/src/osd/PrimaryLogPG.h index c7263d6b5..f6c1b97d8 100644 --- a/ceph/src/osd/PrimaryLogPG.h +++ b/ceph/src/osd/PrimaryLogPG.h @@ -91,7 +91,7 @@ public: uint32_t flags; // object_copy_data_t::FLAG_* uint32_t source_data_digest, source_omap_digest; uint32_t data_digest, omap_digest; - vector > reqids; // [(reqid, user_version)] + mempool::osd_pglog::vector > reqids; // [(reqid, user_version)] map attrs; // xattrs uint64_t truncate_seq; uint64_t truncate_size; @@ -530,7 +530,7 @@ public: int num_read; ///< count read ops int num_write; ///< count update ops - vector > extra_reqids; + mempool::osd_pglog::vector > extra_reqids; CopyFromCallback *copy_cb; @@ -864,7 +864,7 @@ protected: * Also used to store error log entries for dup detection. */ void submit_log_entries( - const mempool::osd::list &entries, + const mempool::osd_pglog::list &entries, ObcLockManager &&manager, boost::optional > &&on_complete, OpRequestRef op = OpRequestRef(), @@ -1117,6 +1117,18 @@ protected: bool must_promote, bool in_hit_set, ObjectContextRef *promote_obc); + cache_result_t maybe_handle_manifest_detail(OpRequestRef op, + bool write_ordered, + ObjectContextRef obc); + bool maybe_handle_manifest(OpRequestRef op, + bool write_ordered, + ObjectContextRef obc) { + return cache_result_t::NOOP != maybe_handle_manifest_detail( + op, + write_ordered, + obc); + } + /** * This helper function is called from do_op if the ObjectContext lookup fails. * @returns true if the caching code is handling the Op, false otherwise. @@ -1329,7 +1341,7 @@ protected: // -- proxyread -- map proxyread_ops; - void do_proxy_read(OpRequestRef op); + void do_proxy_read(OpRequestRef op, ObjectContextRef obc = NULL); void finish_proxy_read(hobject_t oid, ceph_tid_t tid, int r); void cancel_proxy_read(ProxyReadOpRef prdop); @@ -1338,7 +1350,7 @@ protected: // -- proxywrite -- map proxywrite_ops; - void do_proxy_write(OpRequestRef op, const hobject_t& missing_oid); + void do_proxy_write(OpRequestRef op, const hobject_t& missing_oid, ObjectContextRef obc = NULL); void finish_proxy_write(hobject_t oid, ceph_tid_t tid, int r); void cancel_proxy_write(ProxyWriteOpRef pwop); diff --git a/ceph/src/osd/ReplicatedBackend.cc b/ceph/src/osd/ReplicatedBackend.cc index def68de42..07c0d316c 100644 --- a/ceph/src/osd/ReplicatedBackend.cc +++ b/ceph/src/osd/ReplicatedBackend.cc @@ -358,10 +358,10 @@ void generate_transaction( le.mark_unrollbackable(); auto oiter = pgt->op_map.find(le.soid); if (oiter != pgt->op_map.end() && oiter->second.updated_snaps) { - vector snaps( - oiter->second.updated_snaps->second.begin(), - oiter->second.updated_snaps->second.end()); - ::encode(snaps, le.snaps); + bufferlist bl(oiter->second.updated_snaps->second.size() * 8 + 8); + ::encode(oiter->second.updated_snaps->second, bl); + le.snaps.swap(bl); + le.snaps.reassign_to_mempool(mempool::mempool_osd_pglog); } } @@ -514,7 +514,7 @@ void ReplicatedBackend::submit_transaction( generate_transaction( t, coll, - !get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_KRAKEN), + (get_osdmap()->require_osd_release < CEPH_RELEASE_KRAKEN), log_entries, &op_t, &added, diff --git a/ceph/src/osd/Session.h b/ceph/src/osd/Session.h index 5abcb0da3..8e26a7262 100644 --- a/ceph/src/osd/Session.h +++ b/ceph/src/osd/Session.h @@ -27,7 +27,12 @@ typedef boost::intrusive_ptr SessionRef; struct Backoff; typedef boost::intrusive_ptr BackoffRef; class PG; +#ifdef PG_DEBUG_REFS +#include "common/tracked_int_ptr.hpp" +typedef TrackedIntPtr PGRef; +#else typedef boost::intrusive_ptr PGRef; +#endif /* * A Backoff represents one instance of either a PG or an OID diff --git a/ceph/src/osd/SnapMapper.cc b/ceph/src/osd/SnapMapper.cc index d4c393120..81c548510 100644 --- a/ceph/src/osd/SnapMapper.cc +++ b/ceph/src/osd/SnapMapper.cc @@ -166,6 +166,11 @@ void SnapMapper::clear_snaps( assert(check(oid)); set to_remove; to_remove.insert(to_object_key(oid)); + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_remove) { + dout(20) << __func__ << " rm " << i << dendl; + } + } backend.remove_keys(to_remove, t); } @@ -180,6 +185,11 @@ void SnapMapper::set_snaps( ::encode(in, bl); to_set[to_object_key(oid)] = bl; dout(20) << __func__ << " " << oid << " " << in.snaps << dendl; + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_set) { + dout(20) << __func__ << " set " << i.first << dendl; + } + } backend.set_keys(to_set, t); } @@ -214,6 +224,11 @@ int SnapMapper::update_snaps( to_remove.insert(to_raw_key(make_pair(*i, oid))); } } + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_remove) { + dout(20) << __func__ << " rm " << i << dendl; + } + } backend.remove_keys(to_remove, t); return 0; } @@ -240,6 +255,11 @@ void SnapMapper::add_oid( ++i) { to_add.insert(to_raw(make_pair(*i, oid))); } + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_add) { + dout(20) << __func__ << " set " << i.first << dendl; + } + } backend.set_keys(to_add, t); } @@ -259,6 +279,8 @@ int SnapMapper::get_next_objects_to_trim( while (out->size() < max) { pair next; r = backend.get_next(pos, &next); + dout(20) << __func__ << " get_next(" << pos << ") returns " << r + << " " << next << dendl; if (r != 0) { break; // Done } @@ -270,6 +292,7 @@ int SnapMapper::get_next_objects_to_trim( assert(is_mapping(next.first)); + dout(20) << __func__ << " " << next.first << dendl; pair next_decoded(from_raw(next)); assert(next_decoded.first == snap); assert(check(next_decoded.second)); @@ -313,6 +336,11 @@ int SnapMapper::_remove_oid( ++i) { to_remove.insert(to_raw_key(make_pair(*i, oid))); } + if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) { + for (auto& i : to_remove) { + dout(20) << __func__ << " rm " << i << dendl; + } + } backend.remove_keys(to_remove, t); return 0; } diff --git a/ceph/src/osd/osd_types.cc b/ceph/src/osd/osd_types.cc index 6245bfff0..40d3138f4 100644 --- a/ceph/src/osd/osd_types.cc +++ b/ceph/src/osd/osd_types.cc @@ -306,6 +306,8 @@ void objectstore_perf_stat_t::generate_test_instances(std::listdump_unsigned("up_from", up_from); + f->dump_unsigned("seq", seq); f->dump_unsigned("kb", kb); f->dump_unsigned("kb_used", kb_used); f->dump_unsigned("kb_avail", kb_avail); @@ -325,7 +327,7 @@ void osd_stat_t::dump(Formatter *f) const void osd_stat_t::encode(bufferlist &bl) const { - ENCODE_START(5, 2, bl); + ENCODE_START(6, 2, bl); ::encode(kb, bl); ::encode(kb_used, bl); ::encode(kb_avail, bl); @@ -335,12 +337,14 @@ void osd_stat_t::encode(bufferlist &bl) const ::encode((uint32_t)0, bl); ::encode(op_queue_age_hist, bl); ::encode(os_perf_stat, bl); + ::encode(up_from, bl); + ::encode(seq, bl); ENCODE_FINISH(bl); } void osd_stat_t::decode(bufferlist::iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(5, 2, 2, bl); + DECODE_START_LEGACY_COMPAT_LEN(6, 2, 2, bl); ::decode(kb, bl); ::decode(kb_used, bl); ::decode(kb_avail, bl); @@ -353,6 +357,10 @@ void osd_stat_t::decode(bufferlist::iterator &bl) ::decode(op_queue_age_hist, bl); if (struct_v >= 4) ::decode(os_perf_stat, bl); + if (struct_v >= 6) { + ::decode(up_from, bl); + ::decode(seq, bl); + } DECODE_FINISH(bl); } @@ -830,7 +838,7 @@ std::string pg_state_string(int state) if (ret.length() > 0) ret.resize(ret.length() - 1); else - ret = "inactive"; + ret = "unknown"; return ret; } @@ -1131,7 +1139,7 @@ void pg_pool_t::dump(Formatter *f) const f->dump_int("type", get_type()); f->dump_int("size", get_size()); f->dump_int("min_size", get_min_size()); - f->dump_int("crush_ruleset", get_crush_ruleset()); + f->dump_int("crush_rule", get_crush_rule()); f->dump_int("object_hash", get_object_hash()); f->dump_unsigned("pg_num", get_pg_num()); f->dump_unsigned("pg_placement_num", get_pgp_num()); @@ -1397,7 +1405,7 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const ::encode(struct_v, bl); ::encode(type, bl); ::encode(size, bl); - ::encode(crush_ruleset, bl); + ::encode(crush_rule, bl); ::encode(object_hash, bl); ::encode(pg_num, bl); ::encode(pgp_num, bl); @@ -1425,7 +1433,7 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const ::encode(struct_v, bl); ::encode(type, bl); ::encode(size, bl); - ::encode(crush_ruleset, bl); + ::encode(crush_rule, bl); ::encode(object_hash, bl); ::encode(pg_num, bl); ::encode(pgp_num, bl); @@ -1452,7 +1460,7 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const ENCODE_START(14, 5, bl); ::encode(type, bl); ::encode(size, bl); - ::encode(crush_ruleset, bl); + ::encode(crush_rule, bl); ::encode(object_hash, bl); ::encode(pg_num, bl); ::encode(pgp_num, bl); @@ -1507,7 +1515,7 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const ENCODE_START(v, 5, bl); ::encode(type, bl); ::encode(size, bl); - ::encode(crush_ruleset, bl); + ::encode(crush_rule, bl); ::encode(object_hash, bl); ::encode(pg_num, bl); ::encode(pgp_num, bl); @@ -1573,10 +1581,10 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const void pg_pool_t::decode(bufferlist::iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(24, 5, 5, bl); + DECODE_START_LEGACY_COMPAT_LEN(25, 5, 5, bl); ::decode(type, bl); ::decode(size, bl); - ::decode(crush_ruleset, bl); + ::decode(crush_rule, bl); ::decode(object_hash, bl); ::decode(pg_num, bl); ::decode(pgp_num, bl); @@ -1612,7 +1620,7 @@ void pg_pool_t::decode(bufferlist::iterator& bl) // crash_replay_interval appropriately. unfortunately, we can't // be precise here. this should be good enough to preserve replay // on the data pool for the majority of cluster upgrades, though. - if (crush_ruleset == 0 && auid == 0) + if (crush_rule == 0 && auid == 0) crash_replay_interval = 60; else crash_replay_interval = 0; @@ -1732,7 +1740,7 @@ void pg_pool_t::generate_test_instances(list& o) a.type = TYPE_REPLICATED; a.size = 2; - a.crush_ruleset = 3; + a.crush_rule = 3; a.object_hash = 4; a.pg_num = 6; a.pgp_num = 5; @@ -1791,7 +1799,7 @@ ostream& operator<<(ostream& out, const pg_pool_t& p) out << p.get_type_name() << " size " << p.get_size() << " min_size " << p.get_min_size() - << " crush_ruleset " << p.get_crush_ruleset() + << " crush_rule " << p.get_crush_rule() << " object_hash " << p.get_object_hash_name() << " pg_num " << p.get_pg_num() << " pgp_num " << p.get_pgp_num() @@ -2549,7 +2557,7 @@ void pool_stat_t::generate_test_instances(list& o) void pg_history_t::encode(bufferlist &bl) const { - ENCODE_START(8, 4, bl); + ENCODE_START(9, 4, bl); ::encode(epoch_created, bl); ::encode(last_epoch_started, bl); ::encode(last_epoch_clean, bl); @@ -2565,12 +2573,13 @@ void pg_history_t::encode(bufferlist &bl) const ::encode(last_epoch_marked_full, bl); ::encode(last_interval_started, bl); ::encode(last_interval_clean, bl); + ::encode(epoch_pool_created, bl); ENCODE_FINISH(bl); } void pg_history_t::decode(bufferlist::iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(8, 4, 4, bl); + DECODE_START_LEGACY_COMPAT_LEN(9, 4, 4, bl); ::decode(epoch_created, bl); ::decode(last_epoch_started, bl); if (struct_v >= 3) @@ -2610,12 +2619,18 @@ void pg_history_t::decode(bufferlist::iterator &bl) last_interval_clean = last_epoch_clean; // best guess } } + if (struct_v >= 9) { + ::decode(epoch_pool_created, bl); + } else { + epoch_pool_created = epoch_created; + } DECODE_FINISH(bl); } void pg_history_t::dump(Formatter *f) const { f->dump_int("epoch_created", epoch_created); + f->dump_int("epoch_pool_created", epoch_pool_created); f->dump_int("last_epoch_started", last_epoch_started); f->dump_int("last_interval_started", last_interval_started); f->dump_int("last_epoch_clean", last_epoch_clean); @@ -2637,6 +2652,7 @@ void pg_history_t::generate_test_instances(list& o) o.push_back(new pg_history_t); o.push_back(new pg_history_t); o.back()->epoch_created = 1; + o.back()->epoch_pool_created = 1; o.back()->last_epoch_started = 2; o.back()->last_interval_started = 2; o.back()->last_epoch_clean = 3; @@ -3259,7 +3275,7 @@ PastIntervals::PastIntervals(const PastIntervals &rhs) PastIntervals &PastIntervals::operator=(const PastIntervals &rhs) { PastIntervals other(rhs); - ::swap(other, *this); + swap(other); return *this; } @@ -3355,7 +3371,7 @@ void PastIntervals::update_type(bool ec_pool, bool compact) void PastIntervals::update_type_from_map(bool ec_pool, const OSDMap &osdmap) { - update_type(ec_pool, osdmap.test_flag(CEPH_OSDMAP_REQUIRE_LUMINOUS)); + update_type(ec_pool, osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS); } bool PastIntervals::is_new_interval( @@ -3862,6 +3878,7 @@ void ObjectModDesc::decode(bufferlist::iterator &_bl) ::decode(bl, _bl); // ensure bl does not pin a larger buffer in memory bl.rebuild(); + bl.reassign_to_mempool(mempool::mempool_osd_pglog); DECODE_FINISH(_bl); } @@ -3965,6 +3982,7 @@ void pg_log_entry_t::decode(bufferlist::iterator &bl) ::decode(snaps, bl); // ensure snaps does not pin a larger buffer in memory snaps.rebuild(); + snaps.reassign_to_mempool(mempool::mempool_osd_pglog); } if (struct_v >= 8) @@ -3991,8 +4009,7 @@ void pg_log_entry_t::dump(Formatter *f) const f->dump_stream("prior_version") << prior_version; f->dump_stream("reqid") << reqid; f->open_array_section("extra_reqids"); - for (vector >::const_iterator p = - extra_reqids.begin(); + for (auto p = extra_reqids.begin(); p != extra_reqids.end(); ++p) { f->open_object_section("extra_reqid"); @@ -4426,7 +4443,7 @@ void object_copy_data_t::dump(Formatter *f) const f->dump_unsigned("snap", *p); f->close_section(); f->open_array_section("reqids"); - for (vector >::const_iterator p = reqids.begin(); + for (auto p = reqids.begin(); p != reqids.end(); ++p) { f->open_object_section("extra_reqid"); @@ -4918,6 +4935,56 @@ void watch_info_t::generate_test_instances(list& o) o.back()->addr = ea; } +// -- object_manifest_t -- + +void object_manifest_t::encode(bufferlist& bl) const +{ + ENCODE_START(1, 1, bl); + ::encode(type, bl); + switch (type) { + case TYPE_NONE: break; + case TYPE_REDIRECT: + ::encode(redirect_target, bl); + break; + default: + ceph_abort(); + } + ENCODE_FINISH(bl); +} + +void object_manifest_t::decode(bufferlist::iterator& bl) +{ + DECODE_START(1, bl); + ::decode(type, bl); + switch (type) { + case TYPE_NONE: break; + case TYPE_REDIRECT: + ::decode(redirect_target, bl); + break; + default: + ceph_abort(); + } + DECODE_FINISH(bl); +} + +void object_manifest_t::dump(Formatter *f) const +{ + f->dump_unsigned("type", type); + f->open_object_section("redirect_target"); + redirect_target.dump(f); + f->close_section(); +} + +void object_manifest_t::generate_test_instances(list& o) +{ + o.push_back(new object_manifest_t()); + o.back()->type = TYPE_REDIRECT; +} + +ostream& operator<<(ostream& out, const object_manifest_t& om) +{ + return out << "type:" << om.type << " redirect_target:" << om.redirect_target; +} // -- object_info_t -- @@ -4959,7 +5026,7 @@ void object_info_t::encode(bufferlist& bl, uint64_t features) const ++i) { old_watchers.insert(make_pair(i->first.second, i->second)); } - ENCODE_START(16, 8, bl); + ENCODE_START(17, 8, bl); ::encode(soid, bl); ::encode(myoloc, bl); //Retained for compatibility ::encode((__u32)0, bl); // was category, no longer used @@ -4990,13 +5057,16 @@ void object_info_t::encode(bufferlist& bl, uint64_t features) const ::encode(expected_object_size, bl); ::encode(expected_write_size, bl); ::encode(alloc_hint_flags, bl); + if (has_manifest()) { + ::encode(manifest, bl); + } ENCODE_FINISH(bl); } void object_info_t::decode(bufferlist::iterator& bl) { object_locator_t myoloc; - DECODE_START_LEGACY_COMPAT_LEN(16, 8, 8, bl); + DECODE_START_LEGACY_COMPAT_LEN(17, 8, 8, bl); map old_watchers; ::decode(soid, bl); ::decode(myoloc, bl); @@ -5078,6 +5148,11 @@ void object_info_t::decode(bufferlist::iterator& bl) expected_write_size = 0; alloc_hint_flags = 0; } + if (struct_v >= 17) { + if (has_manifest()) { + ::decode(manifest, bl); + } + } DECODE_FINISH(bl); } @@ -5107,6 +5182,7 @@ void object_info_t::dump(Formatter *f) const f->dump_unsigned("expected_object_size", expected_object_size); f->dump_unsigned("expected_write_size", expected_write_size); f->dump_unsigned("alloc_hint_flags", alloc_hint_flags); + f->dump_object("manifest", manifest); f->open_object_section("watchers"); for (map,watch_info_t>::const_iterator p = watchers.begin(); p != watchers.end(); ++p) { @@ -5144,6 +5220,8 @@ ostream& operator<<(ostream& out, const object_info_t& oi) out << " alloc_hint [" << oi.expected_object_size << " " << oi.expected_write_size << " " << oi.alloc_hint_flags << "]"; + if (oi.has_manifest()) + out << " " << oi.manifest; out << ")"; return out; diff --git a/ceph/src/osd/osd_types.h b/ceph/src/osd/osd_types.h index 68804cad1..92cc7c569 100644 --- a/ceph/src/osd/osd_types.h +++ b/ceph/src/osd/osd_types.h @@ -892,6 +892,9 @@ struct osd_stat_t { objectstore_perf_stat_t os_perf_stat; + epoch_t up_from = 0; + uint64_t seq = 0; + osd_stat_t() : kb(0), kb_used(0), kb_avail(0), snap_trim_queue_len(0), num_snap_trimming(0) {} @@ -1244,7 +1247,7 @@ struct pg_pool_t { uint64_t flags; ///< FLAG_* __u8 type; ///< TYPE_* __u8 size, min_size; ///< number of osds in each pg - __u8 crush_ruleset; ///< crush placement rule set + __u8 crush_rule; ///< crush placement rule __u8 object_hash; ///< hash mapping object name to ps private: __u32 pg_num, pgp_num; ///< number of pgs @@ -1367,7 +1370,7 @@ public: pg_pool_t() : flags(0), type(0), size(0), min_size(0), - crush_ruleset(0), object_hash(0), + crush_rule(0), object_hash(0), pg_num(0), pgp_num(0), last_change(0), last_force_op_resend(0), @@ -1421,7 +1424,7 @@ public: unsigned get_type() const { return type; } unsigned get_size() const { return size; } unsigned get_min_size() const { return min_size; } - int get_crush_ruleset() const { return crush_ruleset; } + int get_crush_rule() const { return crush_rule; } int get_object_hash() const { return object_hash; } const char *get_object_hash_name() const { return ceph_str_hash_name(get_object_hash()); @@ -2104,12 +2107,15 @@ WRITE_CLASS_ENCODER(pg_hit_set_history_t) * history they need to worry about. */ struct pg_history_t { - epoch_t epoch_created; // epoch in which PG was created + epoch_t epoch_created; // epoch in which *pg* was created (pool or pg) + epoch_t epoch_pool_created; // epoch in which *pool* was created + // (note: may be pg creation epoch for + // pre-luminous clusters) epoch_t last_epoch_started; // lower bound on last epoch started (anywhere, not necessarily locally) epoch_t last_interval_started; // first epoch of last_epoch_started interval epoch_t last_epoch_clean; // lower bound on last epoch the PG was completely clean. epoch_t last_interval_clean; // first epoch of last_epoch_clean interval - epoch_t last_epoch_split; // as parent + epoch_t last_epoch_split; // as parent or child epoch_t last_epoch_marked_full; // pool or cluster /** @@ -2132,6 +2138,7 @@ struct pg_history_t { friend bool operator==(const pg_history_t& l, const pg_history_t& r) { return l.epoch_created == r.epoch_created && + l.epoch_pool_created == r.epoch_pool_created && l.last_epoch_started == r.last_epoch_started && l.last_interval_started == r.last_interval_started && l.last_epoch_clean == r.last_epoch_clean && @@ -2150,6 +2157,7 @@ struct pg_history_t { pg_history_t() : epoch_created(0), + epoch_pool_created(0), last_epoch_started(0), last_interval_started(0), last_epoch_clean(0), @@ -2165,6 +2173,12 @@ struct pg_history_t { epoch_created = other.epoch_created; modified = true; } + if (epoch_pool_created < other.epoch_pool_created) { + // FIXME: for jewel compat only; this should either be 0 or always the + // same value across all pg instances. + epoch_pool_created = other.epoch_pool_created; + modified = true; + } if (last_epoch_started < other.last_epoch_started) { last_epoch_started = other.last_epoch_started; modified = true; @@ -2220,7 +2234,7 @@ struct pg_history_t { WRITE_CLASS_ENCODER(pg_history_t) inline ostream& operator<<(ostream& out, const pg_history_t& h) { - return out << "ec=" << h.epoch_created + return out << "ec=" << h.epoch_created << "/" << h.epoch_pool_created << " lis/c " << h.last_interval_started << "/" << h.last_interval_clean << " les/c/f " << h.last_epoch_started << "/" << h.last_epoch_clean @@ -2739,7 +2753,8 @@ public: } void swap(PastIntervals &other) { - ::swap(other.past_intervals, past_intervals); + using std::swap; + swap(other.past_intervals, past_intervals); } /** @@ -3111,7 +3126,9 @@ public: TRY_DELETE = 6, ROLLBACK_EXTENTS = 7 }; - ObjectModDesc() : can_local_rollback(true), rollback_info_completed(false) {} + ObjectModDesc() : can_local_rollback(true), rollback_info_completed(false) { + bl.reassign_to_mempool(mempool::mempool_osd_pglog); + } void claim(ObjectModDesc &other) { bl.clear(); bl.claim(other.bl); @@ -3131,9 +3148,10 @@ public: void swap(ObjectModDesc &other) { bl.swap(other.bl); - ::swap(other.can_local_rollback, can_local_rollback); - ::swap(other.rollback_info_completed, rollback_info_completed); - ::swap(other.max_required_version, max_required_version); + using std::swap; + swap(other.can_local_rollback, can_local_rollback); + swap(other.rollback_info_completed, rollback_info_completed); + swap(other.max_required_version, max_required_version); } void append_id(ModID id) { uint8_t _id(id); @@ -3225,7 +3243,7 @@ public: * in the case that bl contains ptrs which point into a much larger * message buffer */ - void trim_bl() { + void trim_bl() const { if (bl.length() > 0) bl.rebuild(); } @@ -3289,7 +3307,7 @@ struct pg_log_entry_t { bufferlist snaps; // only for clone entries hobject_t soid; osd_reqid_t reqid; // caller+tid to uniquely identify request - vector > extra_reqids; + mempool::osd_pglog::vector > extra_reqids; eversion_t version, prior_version, reverting_to; version_t user_version; // the user version for this entry utime_t mtime; // this is the _user_ mtime, mind you @@ -3301,7 +3319,9 @@ struct pg_log_entry_t { pg_log_entry_t() : user_version(0), return_code(0), op(0), - invalid_hash(false), invalid_pool(false) {} + invalid_hash(false), invalid_pool(false) { + snaps.reassign_to_mempool(mempool::mempool_osd_pglog); + } pg_log_entry_t(int _op, const hobject_t& _soid, const eversion_t& v, const eversion_t& pv, version_t uv, @@ -3309,8 +3329,9 @@ struct pg_log_entry_t { int return_code) : soid(_soid), reqid(rid), version(v), prior_version(pv), user_version(uv), mtime(mt), return_code(return_code), op(_op), - invalid_hash(false), invalid_pool(false) - {} + invalid_hash(false), invalid_pool(false) { + snaps.reassign_to_mempool(mempool::mempool_osd_pglog); + } bool is_clone() const { return op == CLONE; } bool is_modify() const { return op == MODIFY; } @@ -3396,14 +3417,14 @@ protected: eversion_t rollback_info_trimmed_to; public: - mempool::osd::list log; // the actual log. + mempool::osd_pglog::list log; // the actual log. pg_log_t() = default; pg_log_t(const eversion_t &last_update, const eversion_t &log_tail, const eversion_t &can_rollback_to, const eversion_t &rollback_info_trimmed_to, - mempool::osd::list &&entries) + mempool::osd_pglog::list &&entries) : head(last_update), tail(log_tail), can_rollback_to(can_rollback_to), rollback_info_trimmed_to(rollback_info_trimmed_to), log(std::move(entries)) {} @@ -3434,7 +3455,7 @@ public: pg_log_t split_out_child(pg_t child_pgid, unsigned split_bits) { - mempool::osd::list oldlog, childlog; + mempool::osd_pglog::list oldlog, childlog; oldlog.swap(log); eversion_t old_tail; @@ -3458,15 +3479,16 @@ public: std::move(childlog)); } - mempool::osd::list rewind_from_head(eversion_t newhead) { + mempool::osd_pglog::list rewind_from_head(eversion_t newhead) { assert(newhead >= tail); - mempool::osd::list::iterator p = log.end(); - mempool::osd::list divergent; + mempool::osd_pglog::list::iterator p = log.end(); + mempool::osd_pglog::list divergent; while (true) { if (p == log.begin()) { // yikes, the whole thing is divergent! - ::swap(divergent, log); + using std::swap; + swap(divergent, log); break; } --p; @@ -3652,8 +3674,6 @@ public: template pg_missing_set(const missing_type &m) { - for (auto &&i: missing) - tracker.changed(i.first); missing = m.get_items(); rmissing = m.get_rmissing(); for (auto &&i: missing) @@ -4137,7 +4157,7 @@ struct object_copy_data_t { snapid_t snap_seq; ///< recent reqids on this object - vector > reqids; + mempool::osd_pglog::vector > reqids; uint64_t truncate_seq; uint64_t truncate_size; @@ -4400,6 +4420,48 @@ static inline ostream& operator<<(ostream& out, const notify_info_t& n) { << " " << n.timeout << "s)"; } +struct object_info_t; +struct object_manifest_t { + enum { + TYPE_NONE = 0, + TYPE_REDIRECT = 1, // start with this + TYPE_CHUNKED = 2, // do this later + }; + uint8_t type; // redirect, chunked, ... + hobject_t redirect_target; + + object_manifest_t() : type(0) { } + object_manifest_t(uint8_t type, const hobject_t& redirect_target) + : type(type), redirect_target(redirect_target) { } + + bool is_empty() const { + return type == TYPE_NONE; + } + bool is_redirect() const { + return type == TYPE_REDIRECT; + } + bool is_chunked() const { + return type == TYPE_CHUNKED; + } + static const char *get_type_name(uint8_t m) { + switch (m) { + case TYPE_NONE: return "none"; + case TYPE_REDIRECT: return "redirect"; + case TYPE_CHUNKED: return "chunked"; + default: return "unknown"; + } + } + const char *get_type_name() const { + return get_type_name(type); + } + static void generate_test_instances(list& o); + void encode(bufferlist &bl) const; + void decode(bufferlist::iterator &bl); + void dump(Formatter *f) const; + friend ostream& operator<<(ostream& out, const object_info_t& oi); +}; +WRITE_CLASS_ENCODER(object_manifest_t) +ostream& operator<<(ostream& out, const object_manifest_t& oi); struct object_info_t { hobject_t soid; @@ -4421,6 +4483,7 @@ struct object_info_t { FLAG_DATA_DIGEST = 1 << 4, // has data crc FLAG_OMAP_DIGEST = 1 << 5, // has omap crc FLAG_CACHE_PIN = 1 << 6, // pin the object in cache tier + FLAG_MANIFEST = 1 << 7, // has manifest // ... FLAG_USES_TMAP = 1<<8, // deprecated; no longer used. } flag_t; @@ -4445,6 +4508,8 @@ struct object_info_t { s += "|omap_digest"; if (flags & FLAG_CACHE_PIN) s += "|cache_pin"; + if (flags & FLAG_MANIFEST) + s += "|manifest"; if (s.length()) return s.substr(1); return s; @@ -4468,6 +4533,8 @@ struct object_info_t { uint64_t expected_object_size, expected_write_size; uint32_t alloc_hint_flags; + struct object_manifest_t manifest; + void copy_user_bits(const object_info_t& other); static ps_t legacy_object_locator_to_ps(const object_t &oid, @@ -4503,6 +4570,9 @@ struct object_info_t { bool is_cache_pinned() const { return test_flag(FLAG_CACHE_PIN); } + bool has_manifest() const { + return test_flag(FLAG_MANIFEST); + } void set_data_digest(__u32 d) { set_flag(FLAG_DATA_DIGEST); @@ -4705,9 +4775,10 @@ struct ScrubMap { objects.insert(r.objects.begin(), r.objects.end()); } void swap(ScrubMap &r) { - ::swap(objects, r.objects); - ::swap(valid_through, r.valid_through); - ::swap(incr_since, r.incr_since); + using std::swap; + swap(objects, r.objects); + swap(valid_through, r.valid_through); + swap(incr_since, r.incr_since); } void encode(bufferlist& bl) const; diff --git a/ceph/src/osdc/Journaler.cc b/ceph/src/osdc/Journaler.cc index 5949ff3b4..fe9a6e9cd 100644 --- a/ceph/src/osdc/Journaler.cc +++ b/ceph/src/osdc/Journaler.cc @@ -526,11 +526,16 @@ void Journaler::_finish_flush(int r, uint64_t start, ceph::real_time stamp) << dendl; // kick waiters <= safe_pos - while (!waitfor_safe.empty()) { - if (waitfor_safe.begin()->first > safe_pos) - break; - finish_contexts(cct, waitfor_safe.begin()->second); - waitfor_safe.erase(waitfor_safe.begin()); + if (!waitfor_safe.empty()) { + list ls; + while (!waitfor_safe.empty()) { + auto it = waitfor_safe.begin(); + if (it->first > safe_pos) + break; + ls.splice(ls.end(), it->second); + waitfor_safe.erase(it); + } + finish_contexts(cct, ls); } } @@ -568,8 +573,12 @@ uint64_t Journaler::append_entry(bufferlist& bl) ldout(cct, 10) << " flushing completed object(s) (su " << su << " wro " << write_obj << " flo " << flush_obj << ")" << dendl; _do_flush(write_buf.length() - write_off); - if (write_off) { - // current entry isn't being flushed, set next_safe_pos to the end of previous entry + + // if _do_flush() skips flushing some data, it does do a best effort to + // update next_safe_pos. + if (write_buf.length() > 0 && + write_buf.length() <= wrote) { // the unflushed data are within this entry + // set next_safe_pos to end of previous entry next_safe_pos = write_pos - wrote; } } @@ -634,6 +643,17 @@ void Journaler::_do_flush(unsigned amount) next_safe_pos = write_pos; } else { write_buf.splice(0, len, &write_bl); + // Keys of waitfor_safe map are journal entry boundaries. + // Try finding a journal entry that we are actually flushing + // and set next_safe_pos to end of it. This is best effort. + // The one we found may not be the lastest flushing entry. + auto p = waitfor_safe.lower_bound(flush_pos + len); + if (p != waitfor_safe.end()) { + if (p->first > flush_pos + len && p != waitfor_safe.begin()) + --p; + if (p->first <= flush_pos + len && p->first > next_safe_pos) + next_safe_pos = p->first; + } } filer.write(ino, &layout, snapc, @@ -952,7 +972,16 @@ void Journaler::_issue_read(uint64_t len) if (pending_safe.empty()) { _flush(NULL); } - waitfor_safe[flush_pos].push_back(new C_RetryRead(this)); + + // Make sure keys of waitfor_safe map are journal entry boundaries. + // The key we used here is either next_safe_pos or old value of + // next_safe_pos. next_safe_pos is always set to journal entry + // boundary. + auto p = pending_safe.rbegin(); + if (p != pending_safe.rend()) + waitfor_safe[p->second].push_back(new C_RetryRead(this)); + else + waitfor_safe[next_safe_pos].push_back(new C_RetryRead(this)); return; } @@ -1062,6 +1091,7 @@ bool Journaler::_is_readable() // adjust write_pos prezeroing_pos = prezero_pos = write_pos = flush_pos = safe_pos = next_safe_pos = read_pos; assert(write_buf.length() == 0); + assert(waitfor_safe.empty()); // reset read state requested_pos = received_pos = read_pos; @@ -1196,7 +1226,7 @@ void Journaler::wait_for_readable(Context *onreadable) { lock_guard l(lock); if (stopping) { - onreadable->complete(-EAGAIN); + finisher->queue(onreadable, -EAGAIN); return; } diff --git a/ceph/src/osdc/ObjectCacher.cc b/ceph/src/osdc/ObjectCacher.cc index 9a0b6ee28..a77d6b318 100644 --- a/ceph/src/osdc/ObjectCacher.cc +++ b/ceph/src/osdc/ObjectCacher.cc @@ -36,19 +36,21 @@ class ObjectCacher::C_ReadFinish : public Context { xlist::item set_item; bool trust_enoent; ceph_tid_t tid; + ZTracer::Trace trace; public: bufferlist bl; C_ReadFinish(ObjectCacher *c, Object *ob, ceph_tid_t t, loff_t s, - uint64_t l) : + uint64_t l, const ZTracer::Trace &trace) : oc(c), poolid(ob->oloc.pool), oid(ob->get_soid()), start(s), length(l), set_item(this), trust_enoent(true), - tid(t) { + tid(t), trace(trace) { ob->reads.push_back(&set_item); } void finish(int r) override { oc->bh_read_finish(poolid, oid, tid, start, length, bl, r, trust_enoent); + trace.event("finish"); // object destructor clears the list if (set_item.is_on_list()) @@ -65,18 +67,25 @@ class ObjectCacher::C_RetryRead : public Context { OSDRead *rd; ObjectSet *oset; Context *onfinish; + ZTracer::Trace trace; public: - C_RetryRead(ObjectCacher *_oc, OSDRead *r, ObjectSet *os, Context *c) - : oc(_oc), rd(r), oset(os), onfinish(c) {} + C_RetryRead(ObjectCacher *_oc, OSDRead *r, ObjectSet *os, Context *c, + const ZTracer::Trace &trace) + : oc(_oc), rd(r), oset(os), onfinish(c), trace(trace) { + } void finish(int r) override { - if (r < 0) { - if (onfinish) - onfinish->complete(r); + if (r >= 0) { + r = oc->_readx(rd, oset, onfinish, false, &trace); + } + + if (r == 0) { + // read is still in-progress return; } - int ret = oc->_readx(rd, oset, onfinish, false); - if (ret != 0 && onfinish) { - onfinish->complete(ret); + + trace.event("finish"); + if (onfinish) { + onfinish->complete(r); } } }; @@ -274,10 +283,9 @@ int ObjectCacher::Object::map_read(ObjectExtent &ex, map& errors) { assert(oc->lock.is_locked()); - ldout(oc->cct, 10) << "map_read " << ex.oid - << " " << ex.offset << "~" << ex.length - << dendl; - + ldout(oc->cct, 10) << "map_read " << ex.oid << " " + << ex.offset << "~" << ex.length << dendl; + loff_t cur = ex.offset; loff_t left = ex.length; @@ -302,7 +310,7 @@ int ObjectCacher::Object::map_read(ObjectExtent &ex, assert(cur == (loff_t)ex.offset + (loff_t)ex.length); break; // no more. } - + if (p->first <= cur) { // have it (or part of it) BufferHead *e = p->second; @@ -322,13 +330,13 @@ int ObjectCacher::Object::map_read(ObjectExtent &ex, } else { ceph_abort(); } - + loff_t lenfromcur = MIN(e->end() - cur, left); cur += lenfromcur; left -= lenfromcur; ++p; continue; // more? - + } else if (p->first > cur) { // gap.. miss loff_t next = p->first; @@ -396,7 +404,7 @@ void ObjectCacher::Object::audit_buffers() * other dirty data to left and/or right. */ ObjectCacher::BufferHead *ObjectCacher::Object::map_write(ObjectExtent &ex, - ceph_tid_t tid) + ceph_tid_t tid) { assert(oc->lock.is_locked()); BufferHead *final = 0; @@ -612,6 +620,7 @@ ObjectCacher::ObjectCacher(CephContext *cct_, string name, max_size(max_bytes), max_objects(max_objects), max_dirty_age(ceph::make_timespan(max_dirty_age)), block_writes_upfront(block_writes_upfront), + trace_endpoint("ObjectCacher"), flush_set_callback(flush_callback), flush_set_callback_arg(flush_callback_arg), last_read_tid(0), flusher_stop(false), flusher_thread(this),finisher(cct), @@ -724,24 +733,32 @@ void ObjectCacher::close_object(Object *ob) delete ob; } -void ObjectCacher::bh_read(BufferHead *bh, int op_flags) +void ObjectCacher::bh_read(BufferHead *bh, int op_flags, + const ZTracer::Trace &parent_trace) { assert(lock.is_locked()); ldout(cct, 7) << "bh_read on " << *bh << " outstanding reads " << reads_outstanding << dendl; + ZTracer::Trace trace; + if (parent_trace.valid()) { + trace.init("", &trace_endpoint, &parent_trace); + trace.copy_name("bh_read " + bh->ob->get_oid().name); + trace.event("start"); + } + mark_rx(bh); bh->last_read_tid = ++last_read_tid; // finisher C_ReadFinish *onfinish = new C_ReadFinish(this, bh->ob, bh->last_read_tid, - bh->start(), bh->length()); + bh->start(), bh->length(), trace); // go writeback_handler.read(bh->ob->get_oid(), bh->ob->get_object_number(), bh->ob->get_oloc(), bh->start(), bh->length(), bh->ob->get_snap(), &onfinish->bl, bh->ob->truncate_size, bh->ob->truncate_seq, - op_flags, onfinish); + op_flags, trace, onfinish); ++reads_outstanding; } @@ -979,11 +996,12 @@ class ObjectCacher::C_WriteCommit : public Context { int64_t poolid; sobject_t oid; vector > ranges; + ZTracer::Trace trace; public: - ceph_tid_t tid; + ceph_tid_t tid = 0; C_WriteCommit(ObjectCacher *c, int64_t _poolid, sobject_t o, loff_t s, - uint64_t l) : - oc(c), poolid(_poolid), oid(o), tid(0) { + uint64_t l, const ZTracer::Trace &trace) : + oc(c), poolid(_poolid), oid(o), trace(trace) { ranges.push_back(make_pair(s, l)); } C_WriteCommit(ObjectCacher *c, int64_t _poolid, sobject_t o, @@ -993,6 +1011,7 @@ public: } void finish(int r) override { oc->bh_write_commit(poolid, oid, ranges, tid, r); + trace.event("finish"); } }; void ObjectCacher::bh_write_scattered(list& blist) @@ -1048,17 +1067,24 @@ void ObjectCacher::bh_write_scattered(list& blist) perfcounter->inc(l_objectcacher_data_flushed, total_len); } -void ObjectCacher::bh_write(BufferHead *bh) +void ObjectCacher::bh_write(BufferHead *bh, const ZTracer::Trace &parent_trace) { assert(lock.is_locked()); ldout(cct, 7) << "bh_write " << *bh << dendl; bh->ob->get(); + ZTracer::Trace trace; + if (parent_trace.valid()) { + trace.init("", &trace_endpoint, &parent_trace); + trace.copy_name("bh_write " + bh->ob->get_oid().name); + trace.event("start"); + } + // finishers C_WriteCommit *oncommit = new C_WriteCommit(this, bh->ob->oloc.pool, bh->ob->get_soid(), bh->start(), - bh->length()); + bh->length(), trace); // go ceph_tid_t tid = writeback_handler.write(bh->ob->get_oid(), bh->ob->get_oloc(), @@ -1066,7 +1092,7 @@ void ObjectCacher::bh_write(BufferHead *bh) bh->snapc, bh->bl, bh->last_write, bh->ob->truncate_size, bh->ob->truncate_seq, - bh->journal_tid, oncommit); + bh->journal_tid, trace, oncommit); ldout(cct, 20) << " tid " << tid << " on " << bh->ob->get_oid() << dendl; // set bh last_write_tid @@ -1191,8 +1217,9 @@ void ObjectCacher::bh_write_commit(int64_t poolid, sobject_t oid, finish_contexts(cct, ls, r); } -void ObjectCacher::flush(loff_t amount) +void ObjectCacher::flush(ZTracer::Trace *trace, loff_t amount) { + assert(trace != nullptr); assert(lock.is_locked()); ceph::real_time cutoff = ceph::real_clock::now(); @@ -1215,9 +1242,9 @@ void ObjectCacher::flush(loff_t amount) bh_write_adjacencies(bh, cutoff, amount > 0 ? &left : NULL, NULL); } else { left -= bh->length(); - bh_write(bh); + bh_write(bh, *trace); } - } + } } @@ -1290,14 +1317,26 @@ bool ObjectCacher::is_cached(ObjectSet *oset, vector& extents, * must delete it) * returns 0 if doing async read */ -int ObjectCacher::readx(OSDRead *rd, ObjectSet *oset, Context *onfinish) +int ObjectCacher::readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, + ZTracer::Trace *parent_trace) { - return _readx(rd, oset, onfinish, true); + ZTracer::Trace trace; + if (parent_trace != nullptr) { + trace.init("read", &trace_endpoint, parent_trace); + trace.event("start"); + } + + int r =_readx(rd, oset, onfinish, true, &trace); + if (r < 0) { + trace.event("finish"); + } + return r; } int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, - bool external_call) + bool external_call, ZTracer::Trace *trace) { + assert(trace != nullptr); assert(lock.is_locked()); bool success = true; int error = 0; @@ -1350,7 +1389,7 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, if (scattered_write) blist.push_back(bh); else - bh_write(bh); + bh_write(bh, *trace); } } } @@ -1360,7 +1399,7 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, ldout(cct, 10) << "readx waiting on tid " << o->last_write_tid << " on " << *o << dendl; o->waitfor_commit[o->last_write_tid].push_back( - new C_RetryRead(this,rd, oset, onfinish)); + new C_RetryRead(this,rd, oset, onfinish, *trace)); // FIXME: perfcounter! return 0; } @@ -1417,14 +1456,15 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, << waitfor_read.size() << " blocked reads, " << (MAX(rx_bytes, max_size) - max_size) << " read bytes" << dendl; - waitfor_read.push_back(new C_RetryRead(this, rd, oset, onfinish)); + waitfor_read.push_back(new C_RetryRead(this, rd, oset, onfinish, + *trace)); } bh_remove(o, bh_it->second); delete bh_it->second; } else { bh_it->second->set_nocache(nocache); - bh_read(bh_it->second, rd->fadvise_flags); + bh_read(bh_it->second, rd->fadvise_flags, *trace); if ((success && onfinish) || last != missing.end()) last = bh_it; } @@ -1436,7 +1476,7 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, ldout(cct, 10) << "readx missed, waiting on " << *last->second << " off " << last->first << dendl; last->second->waitfor_read[last->first].push_back( - new C_RetryRead(this, rd, oset, onfinish) ); + new C_RetryRead(this, rd, oset, onfinish, *trace) ); } @@ -1449,7 +1489,7 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, ldout(cct, 10) << "readx missed, waiting on " << *bh_it->second << " off " << bh_it->first << dendl; bh_it->second->waitfor_read[bh_it->first].push_back( - new C_RetryRead(this, rd, oset, onfinish) ); + new C_RetryRead(this, rd, oset, onfinish, *trace) ); } bytes_not_in_cache += bh_it->second->length(); success = false; @@ -1616,7 +1656,8 @@ void ObjectCacher::retry_waiting_reads() waitfor_read.splice(waitfor_read.end(), ls); } -int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace) +int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace, + ZTracer::Trace *parent_trace) { assert(lock.is_locked()); ceph::real_time now = ceph::real_clock::now(); @@ -1625,6 +1666,12 @@ int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace) bool dontneed = wr->fadvise_flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED; bool nocache = wr->fadvise_flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE; + ZTracer::Trace trace; + if (parent_trace != nullptr) { + trace.init("write", &trace_endpoint, parent_trace); + trace.event("start"); + } + for (vector::iterator ex_it = wr->extents.begin(); ex_it != wr->extents.end(); ++ex_it) { @@ -1637,7 +1684,7 @@ int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace) BufferHead *bh = o->map_write(*ex_it, wr->journal_tid); bool missing = bh->is_missing(); bh->snapc = wr->snapc; - + bytes_written += ex_it->length; if (bh->is_tx()) { bytes_written_in_flush += ex_it->length; @@ -1696,7 +1743,7 @@ int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace) } } - int r = _wait_for_write(wr, bytes_written, oset, onfreespace); + int r = _wait_for_write(wr, bytes_written, oset, &trace, onfreespace); delete wr; //verify_stats(); @@ -1706,23 +1753,26 @@ int ObjectCacher::writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace) class ObjectCacher::C_WaitForWrite : public Context { public: - C_WaitForWrite(ObjectCacher *oc, uint64_t len, Context *onfinish) : - m_oc(oc), m_len(len), m_onfinish(onfinish) {} + C_WaitForWrite(ObjectCacher *oc, uint64_t len, + const ZTracer::Trace &trace, Context *onfinish) : + m_oc(oc), m_len(len), m_trace(trace), m_onfinish(onfinish) {} void finish(int r) override; private: ObjectCacher *m_oc; uint64_t m_len; + ZTracer::Trace m_trace; Context *m_onfinish; }; void ObjectCacher::C_WaitForWrite::finish(int r) { Mutex::Locker l(m_oc->lock); - m_oc->maybe_wait_for_writeback(m_len); + m_oc->maybe_wait_for_writeback(m_len, &m_trace); m_onfinish->complete(r); } -void ObjectCacher::maybe_wait_for_writeback(uint64_t len) +void ObjectCacher::maybe_wait_for_writeback(uint64_t len, + ZTracer::Trace *trace) { assert(lock.is_locked()); ceph::mono_time start = ceph::mono_clock::now(); @@ -1735,6 +1785,9 @@ void ObjectCacher::maybe_wait_for_writeback(uint64_t len) while (get_stat_dirty() + get_stat_tx() > 0 && (uint64_t) (get_stat_dirty() + get_stat_tx()) >= max_dirty + get_stat_dirty_waiting()) { + if (blocked == 0) { + trace->event("start wait for writeback"); + } ldout(cct, 10) << __func__ << " waiting for dirty|tx " << (get_stat_dirty() + get_stat_tx()) << " >= max " << max_dirty << " + dirty_waiting " @@ -1746,6 +1799,9 @@ void ObjectCacher::maybe_wait_for_writeback(uint64_t len) ++blocked; ldout(cct, 10) << __func__ << " woke up" << dendl; } + if (blocked > 0) { + trace->event("finish wait for writeback"); + } if (blocked && perfcounter) { perfcounter->inc(l_objectcacher_write_ops_blocked); perfcounter->inc(l_objectcacher_write_bytes_blocked, len); @@ -1756,19 +1812,20 @@ void ObjectCacher::maybe_wait_for_writeback(uint64_t len) // blocking wait for write. int ObjectCacher::_wait_for_write(OSDWrite *wr, uint64_t len, ObjectSet *oset, - Context *onfreespace) + ZTracer::Trace *trace, Context *onfreespace) { assert(lock.is_locked()); + assert(trace != nullptr); int ret = 0; if (max_dirty > 0) { if (block_writes_upfront) { - maybe_wait_for_writeback(len); + maybe_wait_for_writeback(len, trace); if (onfreespace) onfreespace->complete(0); } else { assert(onfreespace); - finisher.queue(new C_WaitForWrite(this, len, onfreespace)); + finisher.queue(new C_WaitForWrite(this, len, *trace, onfreespace)); } } else { // write-thru! flush what we just wrote. @@ -1777,7 +1834,7 @@ int ObjectCacher::_wait_for_write(OSDWrite *wr, uint64_t len, ObjectSet *oset, Context *fin = block_writes_upfront ? new C_Cond(&cond, &done, &ret) : onfreespace; assert(fin); - bool flushed = flush_set(oset, wr->extents, fin); + bool flushed = flush_set(oset, wr->extents, trace, fin); assert(!flushed); // we just dirtied it, and didn't drop our lock! ldout(cct, 10) << "wait_for_write waiting on write-thru of " << len << " bytes" << dendl; @@ -1816,12 +1873,19 @@ void ObjectCacher::flusher_entry() << max_dirty << " max)" << dendl; loff_t actual = get_stat_dirty() + get_stat_dirty_waiting(); + + ZTracer::Trace trace; + if (cct->_conf->osdc_blkin_trace_all) { + trace.init("flusher", &trace_endpoint); + trace.event("start"); + } + if (actual > 0 && (uint64_t) actual > target_dirty) { // flush some dirty pages ldout(cct, 10) << "flusher " << get_stat_dirty() << " dirty + " << get_stat_dirty_waiting() << " dirty_waiting > target " << target_dirty << ", flushing some dirty bhs" << dendl; - flush(actual - target_dirty); + flush(&trace, actual - target_dirty); } else { // check tail of lru for old dirty items ceph::real_time cutoff = ceph::real_clock::now(); @@ -1836,17 +1900,20 @@ void ObjectCacher::flusher_entry() if (scattered_write) { bh_write_adjacencies(bh, cutoff, NULL, &max); } else { - bh_write(bh); + bh_write(bh, trace); --max; } } if (!max) { // back off the lock to avoid starving other threads + trace.event("backoff"); lock.Unlock(); lock.Lock(); continue; } } + + trace.event("finish"); if (flusher_stop) break; @@ -1943,8 +2010,10 @@ void ObjectCacher::purge(Object *ob) // true if clean, already flushed. // false if we wrote something. // be sloppy about the ranges and flush any buffer it touches -bool ObjectCacher::flush(Object *ob, loff_t offset, loff_t length) +bool ObjectCacher::flush(Object *ob, loff_t offset, loff_t length, + ZTracer::Trace *trace) { + assert(trace != nullptr); assert(lock.is_locked()); list blist; bool clean = true; @@ -1968,7 +2037,7 @@ bool ObjectCacher::flush(Object *ob, loff_t offset, loff_t length) if (scattered_write) blist.push_back(bh); else - bh_write(bh); + bh_write(bh, *trace); clean = false; } if (scattered_write && !blist.empty()) @@ -2044,7 +2113,7 @@ bool ObjectCacher::flush_set(ObjectSet *oset, Context *onfinish) } blist.push_back(bh); } else { - bh_write(bh); + bh_write(bh, {}); } } } @@ -2070,7 +2139,7 @@ bool ObjectCacher::flush_set(ObjectSet *oset, Context *onfinish) } blist.push_front(bh); } else { - bh_write(bh); + bh_write(bh, {}); } } if (!backwards) @@ -2097,9 +2166,10 @@ bool ObjectCacher::flush_set(ObjectSet *oset, Context *onfinish) // flush. non-blocking, takes callback. // returns true if already flushed bool ObjectCacher::flush_set(ObjectSet *oset, vector& exv, - Context *onfinish) + ZTracer::Trace *trace, Context *onfinish) { assert(lock.is_locked()); + assert(trace != nullptr); assert(onfinish != NULL); if (oset->objects.empty()) { ldout(cct, 10) << "flush_set on " << oset << " dne" << dendl; @@ -2125,7 +2195,7 @@ bool ObjectCacher::flush_set(ObjectSet *oset, vector& exv, ldout(cct, 20) << "flush_set " << oset << " ex " << ex << " ob " << soid << " " << ob << dendl; - if (!flush(ob, ex.offset, ex.length)) { + if (!flush(ob, ex.offset, ex.length, trace)) { // we'll need to gather... ldout(cct, 10) << "flush_set " << oset << " will wait for ack tid " << ob->last_write_tid << " on " << *ob << dendl; @@ -2169,7 +2239,7 @@ bool ObjectCacher::flush_all(Context *onfinish) } blist.push_back(bh); } else { - bh_write(bh); + bh_write(bh, {}); } } diff --git a/ceph/src/osdc/ObjectCacher.h b/ceph/src/osdc/ObjectCacher.h index a0305b652..31201a723 100644 --- a/ceph/src/osdc/ObjectCacher.h +++ b/ceph/src/osdc/ObjectCacher.h @@ -11,6 +11,7 @@ #include "common/Cond.h" #include "common/Finisher.h" #include "common/Thread.h" +#include "common/zipkin_trace.h" #include "Objecter.h" #include "Striper.h" @@ -350,7 +351,7 @@ class ObjectCacher { map& rx, map& errors); BufferHead *map_write(ObjectExtent &ex, ceph_tid_t tid); - + void replace_journal_tid(BufferHead *bh, ceph_tid_t tid); void truncate(loff_t s); void discard(loff_t off, loff_t len); @@ -403,6 +404,8 @@ class ObjectCacher { ceph::timespan max_dirty_age; bool block_writes_upfront; + ZTracer::Endpoint trace_endpoint; + flush_set_callback_t flush_set_callback; void *flush_set_callback_arg; @@ -519,14 +522,15 @@ class ObjectCacher { void bh_remove(Object *ob, BufferHead *bh); // io - void bh_read(BufferHead *bh, int op_flags); - void bh_write(BufferHead *bh); + void bh_read(BufferHead *bh, int op_flags, + const ZTracer::Trace &parent_trace); + void bh_write(BufferHead *bh, const ZTracer::Trace &parent_trace); void bh_write_scattered(list& blist); void bh_write_adjacencies(BufferHead *bh, ceph::real_time cutoff, int64_t *amount, int *max_count); void trim(); - void flush(loff_t amount=0); + void flush(ZTracer::Trace *trace, loff_t amount=0); /** * flush a range of buffers @@ -539,7 +543,8 @@ class ObjectCacher { * @param len extent length, or 0 for entire object * @return true if object was already clean/flushed. */ - bool flush(Object *o, loff_t off, loff_t len); + bool flush(Object *o, loff_t off, loff_t len, + ZTracer::Trace *trace); loff_t release(Object *o); void purge(Object *o); @@ -547,7 +552,7 @@ class ObjectCacher { Cond read_cond; int _readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, - bool external_call); + bool external_call, ZTracer::Trace *trace); void retry_waiting_reads(); public: @@ -597,16 +602,18 @@ class ObjectCacher { * @note total read size must be <= INT_MAX, since * the return value is total bytes read */ - int readx(OSDRead *rd, ObjectSet *oset, Context *onfinish); - int writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace); + int readx(OSDRead *rd, ObjectSet *oset, Context *onfinish, + ZTracer::Trace *parent_trace = nullptr); + int writex(OSDWrite *wr, ObjectSet *oset, Context *onfreespace, + ZTracer::Trace *parent_trace = nullptr); bool is_cached(ObjectSet *oset, vector& extents, snapid_t snapid); private: // write blocking int _wait_for_write(OSDWrite *wr, uint64_t len, ObjectSet *oset, - Context *onfreespace); - void maybe_wait_for_writeback(uint64_t len); + ZTracer::Trace *trace, Context *onfreespace); + void maybe_wait_for_writeback(uint64_t len, ZTracer::Trace *trace); bool _flush_set_finish(C_GatherBuilder *gather, Context *onfinish); public: @@ -616,7 +623,7 @@ public: bool flush_set(ObjectSet *oset, Context *onfinish=0); bool flush_set(ObjectSet *oset, vector& ex, - Context *onfinish = 0); + ZTracer::Trace *trace, Context *onfinish = 0); bool flush_all(Context *onfinish = 0); void purge_set(ObjectSet *oset); @@ -689,7 +696,8 @@ public: vector extents; Striper::file_to_extents(cct, oset->ino, layout, offset, len, oset->truncate_size, extents); - return flush_set(oset, extents, onfinish); + ZTracer::Trace trace; + return flush_set(oset, extents, &trace, onfinish); } }; diff --git a/ceph/src/osdc/Objecter.cc b/ceph/src/osdc/Objecter.cc index 050c762c7..97f97e027 100644 --- a/ceph/src/osdc/Objecter.cc +++ b/ceph/src/osdc/Objecter.cc @@ -237,7 +237,7 @@ void Objecter::update_crush_location() */ void Objecter::init() { - assert(!initialized.read()); + assert(!initialized); if (!logger) { PerfCountersBuilder pcb(cct, "objecter", l_osdc_first, l_osdc_last); @@ -387,7 +387,7 @@ void Objecter::init() cct->_conf->add_observer(this); - initialized.set(1); + initialized = true; } /* @@ -407,11 +407,11 @@ void Objecter::start(const OSDMap* o) void Objecter::shutdown() { - assert(initialized.read()); + assert(initialized); unique_lock wl(rwlock); - initialized.set(0); + initialized = false; cct->_conf->remove_observer(this); @@ -562,7 +562,7 @@ void Objecter::_send_linger(LingerOp *info, o->mtime = info->mtime; o->target = info->target; - o->tid = last_tid.inc(); + o->tid = ++last_tid; // do not resend this; we will send a new op to reregister o->should_resend = false; @@ -694,7 +694,7 @@ void Objecter::_send_linger_ping(LingerOp *info) o->should_resend = false; _send_op_account(o); MOSDOp *m = _prepare_osd_op(o); - o->tid = last_tid.inc(); + o->tid = ++last_tid; _session_op_assign(info->session, o); _send_op(o, m); info->ping_tid = o->tid; @@ -888,7 +888,7 @@ struct C_DoWatchNotify : public Context { void Objecter::handle_watch_notify(MWatchNotify *m) { shared_lock l(rwlock); - if (!initialized.read()) { + if (!initialized) { return; } @@ -931,7 +931,7 @@ void Objecter::_do_watch_notify(LingerOp *info, MWatchNotify *m) ldout(cct, 10) << __func__ << " " << *m << dendl; shared_lock l(rwlock); - assert(initialized.read()); + assert(initialized); if (info->canceled) { l.unlock(); @@ -961,7 +961,7 @@ void Objecter::_do_watch_notify(LingerOp *info, MWatchNotify *m) bool Objecter::ms_dispatch(Message *m) { ldout(cct, 10) << __func__ << " " << cct << " " << *m << dendl; - if (!initialized.read()) + if (!initialized) return false; switch (m->get_type()) { @@ -1134,7 +1134,7 @@ void Objecter::_scan_requests(OSDSession *s, void Objecter::handle_osd_map(MOSDMap *m) { shunique_lock sul(rwlock, acquire_unique); - if (!initialized.read()) + if (!initialized) return; assert(osdmap); @@ -1182,11 +1182,20 @@ void Objecter::handle_osd_map(MOSDMap *m) << dendl; OSDMap::Incremental inc(m->incremental_maps[e]); osdmap->apply_incremental(inc); + + emit_blacklist_events(inc); + logger->inc(l_osdc_map_inc); } else if (m->maps.count(e)) { ldout(cct, 3) << "handle_osd_map decoding full epoch " << e << dendl; - osdmap->decode(m->maps[e]); + OSDMap *new_osdmap = new OSDMap(); + new_osdmap->decode(m->maps[e]); + + emit_blacklist_events(*osdmap, *new_osdmap); + + osdmap = new_osdmap; + logger->inc(l_osdc_map_full); } else { @@ -1361,6 +1370,58 @@ void Objecter::handle_osd_map(MOSDMap *m) } } +void Objecter::enable_blacklist_events() +{ + unique_lock wl(rwlock); + + blacklist_events_enabled = true; +} + +void Objecter::consume_blacklist_events(std::set *events) +{ + unique_lock wl(rwlock); + + if (events->empty()) { + events->swap(blacklist_events); + } else { + for (const auto &i : blacklist_events) { + events->insert(i); + } + blacklist_events.clear(); + } +} + +void Objecter::emit_blacklist_events(const OSDMap::Incremental &inc) +{ + if (!blacklist_events_enabled) { + return; + } + + for (const auto &i : inc.new_blacklist) { + blacklist_events.insert(i.first); + } +} + +void Objecter::emit_blacklist_events(const OSDMap &old_osd_map, + const OSDMap &new_osd_map) +{ + if (!blacklist_events_enabled) { + return; + } + + std::set old_set; + std::set new_set; + + old_osd_map.get_blacklist(&old_set); + new_osd_map.get_blacklist(&new_set); + + std::set delta_set; + std::set_difference( + new_set.begin(), new_set.end(), old_set.begin(), old_set.end(), + std::inserter(delta_set, delta_set.begin())); + blacklist_events.insert(delta_set.begin(), delta_set.end()); +} + // op pool check void Objecter::C_Op_Map_Latest::finish(int r) @@ -2056,7 +2117,7 @@ void Objecter::tick() // we are only called by C_Tick tick_event = 0; - if (!initialized.read()) { + if (!initialized) { // we raced with shutdown ldout(cct, 10) << __func__ << " raced with shutdown" << dendl; return; @@ -2112,7 +2173,7 @@ void Objecter::tick() if (found) toping.insert(s); } - if (num_homeless_ops.read() || !toping.empty()) { + if (num_homeless_ops || !toping.empty()) { _maybe_request_map(); } @@ -2130,7 +2191,7 @@ void Objecter::tick() } // Make sure we don't resechedule if we wake up after shutdown - if (initialized.read()) { + if (initialized) { tick_event = timer.reschedule_me(ceph::make_timespan( cct->_conf->objecter_tick_interval)); } @@ -2195,6 +2256,7 @@ void Objecter::op_submit(Op *op, ceph_tid_t *ptid, int *ctx_budget) ceph_tid_t tid = 0; if (!ptid) ptid = &tid; + op->trace.event("op submit"); _op_submit_with_budget(op, rl, ptid, ctx_budget); } @@ -2202,7 +2264,7 @@ void Objecter::_op_submit_with_budget(Op *op, shunique_lock& sul, ceph_tid_t *ptid, int *ctx_budget) { - assert(initialized.read()); + assert(initialized); assert(op->ops.size() == op->out_bl.size()); assert(op->ops.size() == op->out_rval.size()); @@ -2221,7 +2283,7 @@ void Objecter::_op_submit_with_budget(Op *op, shunique_lock& sul, if (osd_timeout > timespan(0)) { if (op->tid == 0) - op->tid = last_tid.inc(); + op->tid = ++last_tid; auto tid = op->tid; op->ontimeout = timer.add_event(osd_timeout, [this, tid]() { @@ -2233,11 +2295,11 @@ void Objecter::_op_submit_with_budget(Op *op, shunique_lock& sul, void Objecter::_send_op_account(Op *op) { - inflight_ops.inc(); + inflight_ops++; // add to gather set(s) if (op->onfinish) { - num_in_flight.inc(); + num_in_flight++; } else { ldout(cct, 20) << " note: not requesting reply" << dendl; } @@ -2396,7 +2458,7 @@ void Objecter::_op_submit(Op *op, shunique_lock& sul, ceph_tid_t *ptid) OSDSession::unique_lock sl(s->lock); if (op->tid == 0) - op->tid = last_tid.inc(); + op->tid = ++last_tid; ldout(cct, 10) << "_op_submit oid " << op->target.base_oid << " '" << op->target.base_oloc << "' '" @@ -2423,12 +2485,12 @@ void Objecter::_op_submit(Op *op, shunique_lock& sul, ceph_tid_t *ptid) sl.unlock(); put_session(s); - ldout(cct, 5) << num_in_flight.read() << " in flight" << dendl; + ldout(cct, 5) << num_in_flight << " in flight" << dendl; } int Objecter::op_cancel(OSDSession *s, ceph_tid_t tid, int r) { - assert(initialized.read()); + assert(initialized); OSDSession::unique_lock sl(s->lock); @@ -2449,7 +2511,7 @@ int Objecter::op_cancel(OSDSession *s, ceph_tid_t tid, int r) << dendl; Op *op = p->second; if (op->onfinish) { - num_in_flight.dec(); + num_in_flight--; op->onfinish->complete(r); op->onfinish = NULL; } @@ -2886,7 +2948,7 @@ void Objecter::_session_op_assign(OSDSession *to, Op *op) to->ops[op->tid] = op; if (to->is_homeless()) { - num_homeless_ops.inc(); + num_homeless_ops++; } ldout(cct, 15) << __func__ << " " << to->osd << " " << op->tid << dendl; @@ -2898,7 +2960,7 @@ void Objecter::_session_op_remove(OSDSession *from, Op *op) // from->lock is locked if (from->is_homeless()) { - num_homeless_ops.dec(); + num_homeless_ops--; } from->ops.erase(op->tid); @@ -2914,7 +2976,7 @@ void Objecter::_session_linger_op_assign(OSDSession *to, LingerOp *op) assert(op->session == NULL); if (to->is_homeless()) { - num_homeless_ops.inc(); + num_homeless_ops++; } get_session(to); @@ -2931,7 +2993,7 @@ void Objecter::_session_linger_op_remove(OSDSession *from, LingerOp *op) // from->lock is locked unique if (from->is_homeless()) { - num_homeless_ops.dec(); + num_homeless_ops--; } from->linger_ops.erase(op->linger_id); @@ -2948,7 +3010,7 @@ void Objecter::_session_command_op_remove(OSDSession *from, CommandOp *op) // from->lock is locked if (from->is_homeless()) { - num_homeless_ops.dec(); + num_homeless_ops--; } from->command_ops.erase(op->tid); @@ -2965,7 +3027,7 @@ void Objecter::_session_command_op_assign(OSDSession *to, CommandOp *op) assert(op->tid); if (to->is_homeless()) { - num_homeless_ops.inc(); + num_homeless_ops++; } get_session(to); @@ -3013,7 +3075,7 @@ void Objecter::_cancel_linger_op(Op *op) assert(!op->should_resend); if (op->onfinish) { delete op->onfinish; - num_in_flight.dec(); + num_in_flight--; } _finish_op(op, 0); @@ -3039,7 +3101,7 @@ void Objecter::_finish_op(Op *op, int r) assert(check_latest_map_ops.find(op->tid) == check_latest_map_ops.end()); - inflight_ops.dec(); + inflight_ops--; op->put(); } @@ -3078,7 +3140,7 @@ MOSDOp *Objecter::_prepare_osd_op(Op *op) op->stamp = ceph::mono_clock::now(); hobject_t hobj = op->target.get_hobj(); - MOSDOp *m = new MOSDOp(client_inc.read(), op->tid, + MOSDOp *m = new MOSDOp(client_inc, op->tid, hobj, op->target.actual_pgid, osdmap->get_epoch(), flags, op->features); @@ -3090,9 +3152,10 @@ MOSDOp *Objecter::_prepare_osd_op(Op *op) m->ops = op->ops; m->set_mtime(op->mtime); m->set_retry_attempt(op->attempts++); - m->trace = op->trace; - if (!m->trace && cct->_conf->osdc_blkin_trace_all) - m->trace.init("objecter op", &trace_endpoint); + + if (!op->trace.valid() && cct->_conf->osdc_blkin_trace_all) { + op->trace.init("op", &trace_endpoint); + } if (op->priority) m->set_priority(op->priority); @@ -3177,6 +3240,9 @@ void Objecter::_send_op(Op *op, MOSDOp *m) m->set_tid(op->tid); + if (op->trace.valid()) { + m->trace.init("op msg", nullptr, &op->trace); + } op->session->con->send_message(m); } @@ -3235,7 +3301,7 @@ void Objecter::unregister_op(Op *op) put_session(op->session); op->session = NULL; - inflight_ops.dec(); + inflight_ops--; } /* This function DOES put the passed message before returning */ @@ -3247,7 +3313,7 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) ceph_tid_t tid = m->get_tid(); shunique_lock sul(rwlock, ceph::acquire_shared); - if (!initialized.read()) { + if (!initialized) { m->put(); return; } @@ -3285,12 +3351,13 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) << " attempt " << m->get_retry_attempt() << dendl; Op *op = iter->second; + op->trace.event("osd op reply"); if (retry_writes_after_first_reply && op->attempts == 1 && (op->target.flags & CEPH_OSD_FLAG_WRITE)) { ldout(cct, 7) << "retrying write after first reply: " << tid << dendl; if (op->onfinish) { - num_in_flight.dec(); + num_in_flight--; } _session_op_remove(s, op); sl.unlock(); @@ -3326,7 +3393,7 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) if (m->is_redirect_reply()) { ldout(cct, 5) << " got redirect reply; redirecting" << dendl; if (op->onfinish) - num_in_flight.dec(); + num_in_flight--; _session_op_remove(s, op); sl.unlock(); put_session(s); @@ -3347,7 +3414,7 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) // new tid s->ops.erase(op->tid); - op->tid = last_tid.inc(); + op->tid = ++last_tid; _send_op(op); sl.unlock(); @@ -3398,10 +3465,10 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) // set rval before running handlers so that handlers // can change it if e.g. decoding fails if (*pr) - **pr = ceph_to_host_errno(p->rval); + **pr = ceph_to_hostos_errno(p->rval); if (*ph) { ldout(cct, 10) << " op " << i << " handler " << *ph << dendl; - (*ph)->complete(ceph_to_host_errno(p->rval)); + (*ph)->complete(ceph_to_hostos_errno(p->rval)); *ph = NULL; } } @@ -3410,7 +3477,7 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) // only ever get back one (type of) ack ever. if (op->onfinish) { - num_in_flight.dec(); + num_in_flight--; onfinish = op->onfinish; op->onfinish = NULL; } @@ -3422,7 +3489,7 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m) ldout(cct, 15) << "handle_osd_op_reply completed tid " << tid << dendl; _finish_op(op, 0); - ldout(cct, 5) << num_in_flight.read() << " in flight" << dendl; + ldout(cct, 5) << num_in_flight << " in flight" << dendl; // serialize completions if (completion_lock.mutex()) { @@ -3446,7 +3513,7 @@ void Objecter::handle_osd_backoff(MOSDBackoff *m) { ldout(cct, 10) << __func__ << " " << *m << dendl; shunique_lock sul(rwlock, ceph::acquire_shared); - if (!initialized.read()) { + if (!initialized) { m->put(); return; } @@ -3741,7 +3808,7 @@ int Objecter::create_pool_snap(int64_t pool, string& snap_name, PoolOp *op = new PoolOp; if (!op) return -ENOMEM; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = pool; op->name = snap_name; op->onfinish = onfinish; @@ -3774,7 +3841,7 @@ int Objecter::allocate_selfmanaged_snap(int64_t pool, snapid_t *psnapid, ldout(cct, 10) << "allocate_selfmanaged_snap; pool: " << pool << dendl; PoolOp *op = new PoolOp; if (!op) return -ENOMEM; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = pool; C_SelfmanagedSnap *fin = new C_SelfmanagedSnap(psnapid, onfinish); op->onfinish = fin; @@ -3802,7 +3869,7 @@ int Objecter::delete_pool_snap(int64_t pool, string& snap_name, PoolOp *op = new PoolOp; if (!op) return -ENOMEM; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = pool; op->name = snap_name; op->onfinish = onfinish; @@ -3822,7 +3889,7 @@ int Objecter::delete_selfmanaged_snap(int64_t pool, snapid_t snap, << snap << dendl; PoolOp *op = new PoolOp; if (!op) return -ENOMEM; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = pool; op->onfinish = onfinish; op->pool_op = POOL_OP_DELETE_UNMANAGED_SNAP; @@ -3846,7 +3913,7 @@ int Objecter::create_pool(string& name, Context *onfinish, uint64_t auid, PoolOp *op = new PoolOp; if (!op) return -ENOMEM; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = 0; op->name = name; op->onfinish = onfinish; @@ -3888,7 +3955,7 @@ int Objecter::delete_pool(const string &pool_name, Context *onfinish) void Objecter::_do_delete_pool(int64_t pool, Context *onfinish) { PoolOp *op = new PoolOp; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = pool; op->name = "delete"; op->onfinish = onfinish; @@ -3909,7 +3976,7 @@ int Objecter::change_pool_auid(int64_t pool, Context *onfinish, uint64_t auid) ldout(cct, 10) << "change_pool_auid " << pool << " to " << auid << dendl; PoolOp *op = new PoolOp; if (!op) return -ENOMEM; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pool = pool; op->name = "change_pool_auid"; op->onfinish = onfinish; @@ -3961,7 +4028,7 @@ void Objecter::handle_pool_op_reply(MPoolOpReply *m) { FUNCTRACE(); shunique_lock sul(rwlock, acquire_shared); - if (!initialized.read()) { + if (!initialized) { sul.unlock(); m->put(); return; @@ -4024,7 +4091,7 @@ done: int Objecter::pool_op_cancel(ceph_tid_t tid, int r) { - assert(initialized.read()); + assert(initialized); unique_lock wl(rwlock); @@ -4066,7 +4133,7 @@ void Objecter::get_pool_stats(list& pools, ldout(cct, 10) << "get_pool_stats " << pools << dendl; PoolStatOp *op = new PoolStatOp; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->pools = pools; op->pool_stats = result; op->onfinish = onfinish; @@ -4105,7 +4172,7 @@ void Objecter::handle_get_pool_stats_reply(MGetPoolStatsReply *m) ceph_tid_t tid = m->get_tid(); unique_lock wl(rwlock); - if (!initialized.read()) { + if (!initialized) { m->put(); return; } @@ -4129,7 +4196,7 @@ void Objecter::handle_get_pool_stats_reply(MGetPoolStatsReply *m) int Objecter::pool_stat_op_cancel(ceph_tid_t tid, int r) { - assert(initialized.read()); + assert(initialized); unique_lock wl(rwlock); @@ -4167,7 +4234,7 @@ void Objecter::get_fs_stats(ceph_statfs& result, Context *onfinish) unique_lock l(rwlock); StatfsOp *op = new StatfsOp; - op->tid = last_tid.inc(); + op->tid = ++last_tid; op->stats = &result; op->onfinish = onfinish; if (mon_timeout > timespan(0)) { @@ -4200,7 +4267,7 @@ void Objecter::_fs_stats_submit(StatfsOp *op) void Objecter::handle_fs_stats_reply(MStatfsReply *m) { unique_lock wl(rwlock); - if (!initialized.read()) { + if (!initialized) { m->put(); return; } @@ -4225,7 +4292,7 @@ void Objecter::handle_fs_stats_reply(MStatfsReply *m) int Objecter::statfs_op_cancel(ceph_tid_t tid, int r) { - assert(initialized.read()); + assert(initialized); unique_lock wl(rwlock); @@ -4294,7 +4361,7 @@ void Objecter::_sg_read_finish(vector& extents, void Objecter::ms_handle_connect(Connection *con) { ldout(cct, 10) << "ms_handle_connect " << con << dendl; - if (!initialized.read()) + if (!initialized) return; if (con->get_peer_type() == CEPH_ENTITY_TYPE_MON) @@ -4303,7 +4370,7 @@ void Objecter::ms_handle_connect(Connection *con) bool Objecter::ms_handle_reset(Connection *con) { - if (!initialized.read()) + if (!initialized) return false; if (con->get_peer_type() == CEPH_ENTITY_TYPE_OSD) { OSDSession *session = static_cast(con->get_priv()); @@ -4311,7 +4378,7 @@ bool Objecter::ms_handle_reset(Connection *con) ldout(cct, 1) << "ms_handle_reset " << con << " session " << session << " osd." << session->osd << dendl; unique_lock wl(rwlock); - if (!initialized.read()) { + if (!initialized) { wl.unlock(); return false; } @@ -4354,7 +4421,7 @@ bool Objecter::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new) { - if (!initialized.read()) + if (!initialized) return false; if (dest_type == CEPH_ENTITY_TYPE_MON) return true; @@ -4390,7 +4457,7 @@ void Objecter::_dump_active(OSDSession *s) void Objecter::_dump_active() { - ldout(cct, 20) << "dump_active .. " << num_homeless_ops.read() << " homeless" + ldout(cct, 20) << "dump_active .. " << num_homeless_ops << " homeless" << dendl; for (map::iterator siter = osd_sessions.begin(); siter != osd_sessions.end(); ++siter) { @@ -4632,7 +4699,7 @@ void Objecter::blacklist_self(bool set) void Objecter::handle_command_reply(MCommandReply *m) { unique_lock wl(rwlock); - if (!initialized.read()) { + if (!initialized) { m->put(); return; } @@ -4689,7 +4756,7 @@ void Objecter::submit_command(CommandOp *c, ceph_tid_t *ptid) { shunique_lock sul(rwlock, ceph::acquire_unique); - ceph_tid_t tid = last_tid.inc(); + ceph_tid_t tid = ++last_tid; ldout(cct, 10) << "_submit_command " << tid << " " << c->cmd << dendl; c->tid = tid; @@ -4812,7 +4879,7 @@ void Objecter::_send_command(CommandOp *c) int Objecter::command_op_cancel(OSDSession *s, ceph_tid_t tid, int r) { - assert(initialized.read()); + assert(initialized); unique_lock wl(rwlock); @@ -4868,7 +4935,7 @@ Objecter::~Objecter() delete osdmap; assert(homeless_session->get_nref() == 1); - assert(num_homeless_ops.read() == 0); + assert(num_homeless_ops == 0); homeless_session->put(); assert(osd_sessions.empty()); diff --git a/ceph/src/osdc/Objecter.h b/ceph/src/osdc/Objecter.h index 85b947afe..4efdb9d08 100644 --- a/ceph/src/osdc/Objecter.h +++ b/ceph/src/osdc/Objecter.h @@ -727,7 +727,7 @@ struct ObjectOperation { uint32_t *out_flags; uint32_t *out_data_digest; uint32_t *out_omap_digest; - vector > *out_reqids; + mempool::osd_pglog::vector > *out_reqids; uint64_t *out_truncate_seq; uint64_t *out_truncate_size; int *prval; @@ -742,7 +742,7 @@ struct ObjectOperation { uint32_t *flags, uint32_t *dd, uint32_t *od, - vector > *oreqids, + mempool::osd_pglog::vector > *oreqids, uint64_t *otseq, uint64_t *otsize, int *r) @@ -817,7 +817,7 @@ struct ObjectOperation { uint32_t *out_flags, uint32_t *out_data_digest, uint32_t *out_omap_digest, - vector > *out_reqids, + mempool::osd_pglog::vector > *out_reqids, uint64_t *truncate_seq, uint64_t *truncate_size, int *prval) { @@ -1122,6 +1122,18 @@ struct ObjectOperation { add_op(CEPH_OSD_OP_CACHE_EVICT); } + /* + * Extensible tier + */ + void set_redirect(object_t tgt, snapid_t snapid, object_locator_t tgt_oloc, + version_t tgt_version) { + OSDOp& osd_op = add_op(CEPH_OSD_OP_SET_REDIRECT); + osd_op.op.copy_from.snapid = snapid; + osd_op.op.copy_from.src_version = tgt_version; + ::encode(tgt, osd_op.indata); + ::encode(tgt_oloc, osd_op.indata); + } + void set_alloc_hint(uint64_t expected_object_size, uint64_t expected_write_size, uint32_t flags) { @@ -1180,21 +1192,28 @@ public: using Dispatcher::cct; std::multimap crush_location; - atomic_t initialized; + std::atomic initialized{false}; private: - atomic64_t last_tid; - atomic_t inflight_ops; - atomic_t client_inc; + std::atomic last_tid{0}; + std::atomic inflight_ops{0}; + std::atomic client_inc{-1}; uint64_t max_linger_id; - atomic_t num_in_flight; - atomic_t global_op_flags; // flags which are applied to each IO op + std::atomic num_in_flight{0}; + std::atomic global_op_flags{0}; // flags which are applied to each IO op bool keep_balanced_budget; bool honor_osdmap_full; bool osdmap_full_try; + // If this is true, accumulate a set of blacklisted entities + // to be drained by consume_blacklist_events. + bool blacklist_events_enabled; + std::set blacklist_events; + public: void maybe_request_map(); + + void enable_blacklist_events(); private: void _maybe_request_map(); @@ -1384,8 +1403,10 @@ public: if (target.base_oloc.key == o) target.base_oloc.key.clear(); - if (parent_trace && parent_trace->valid()) + if (parent_trace && parent_trace->valid()) { trace.init("op", nullptr, parent_trace); + trace.event("start"); + } } bool operator<(const Op& other) const { @@ -1404,6 +1425,7 @@ public: delete out_handler.back(); out_handler.pop_back(); } + trace.event("finish"); } }; @@ -1838,7 +1860,7 @@ public: map poolstat_ops; map statfs_ops; map pool_ops; - atomic_t num_homeless_ops; + std::atomic num_homeless_ops{0}; OSDSession *homeless_session; @@ -1974,12 +1996,12 @@ private: double osd_timeout) : Dispatcher(cct_), messenger(m), monc(mc), finisher(fin), trace_endpoint("0.0.0.0", 0, "Objecter"), - osdmap(new OSDMap), initialized(0), last_tid(0), client_inc(-1), - max_linger_id(0), num_in_flight(0), global_op_flags(0), + osdmap(new OSDMap), + max_linger_id(0), keep_balanced_budget(false), honor_osdmap_full(true), osdmap_full_try(false), + blacklist_events_enabled(false), last_seen_osdmap_version(0), last_seen_pgmap_version(0), logger(NULL), tick_event(0), m_request_state_hook(NULL), - num_homeless_ops(0), homeless_session(new OSDSession(cct, -1)), mon_timeout(ceph::make_timespan(mon_timeout)), osd_timeout(ceph::make_timespan(osd_timeout)), @@ -2070,6 +2092,17 @@ private: void handle_osd_map(class MOSDMap *m); void wait_for_osd_map(); + /** + * Get list of entities blacklisted since this was last called, + * and reset the list. + * + * Uses a std::set because typical use case is to compare some + * other list of clients to see which overlap with the blacklisted + * addrs. + * + */ + void consume_blacklist_events(std::set *events); + int pool_snap_by_name(int64_t poolid, const char *snap_name, snapid_t *snap) const; @@ -2078,6 +2111,10 @@ private: int pool_snap_list(int64_t poolid, vector *snaps); private: + void emit_blacklist_events(const OSDMap::Incremental &inc); + void emit_blacklist_events(const OSDMap &old_osd_map, + const OSDMap &new_osd_map); + // low-level void _op_submit(Op *op, shunique_lock& lc, ceph_tid_t *ptid); void _op_submit_with_budget(Op *op, shunique_lock& lc, @@ -2090,7 +2127,7 @@ public: void op_submit(Op *op, ceph_tid_t *ptid = NULL, int *ctx_budget = NULL); bool is_active() { shared_lock l(rwlock); - return !((!inflight_ops.read()) && linger_ops.empty() && + return !((!inflight_ops) && linger_ops.empty() && poolstat_ops.empty() && statfs_ops.empty()); } @@ -2111,8 +2148,8 @@ public: void dump_pool_stat_ops(Formatter *fmt) const; void dump_statfs_ops(Formatter *fmt) const; - int get_client_incarnation() const { return client_inc.read(); } - void set_client_incarnation(int inc) { client_inc.set(inc); } + int get_client_incarnation() const { return client_inc; } + void set_client_incarnation(int inc) { client_inc = inc; } bool have_map(epoch_t epoch); /// wait for epoch; true if we already have it @@ -2123,15 +2160,14 @@ public: void _get_latest_version(epoch_t oldest, epoch_t neweset, Context *fin); /** Get the current set of global op flags */ - int get_global_op_flags() { return global_op_flags.read(); } + int get_global_op_flags() const { return global_op_flags; } /** Add a flag to the global op flags, not really atomic operation */ void add_global_op_flags(int flag) { - global_op_flags.set(global_op_flags.read() | flag); + global_op_flags.fetch_or(flag); } - /** Clear the passed flags from the global op flag set, not really - atomic operation */ + /** Clear the passed flags from the global op flag set */ void clear_global_op_flag(int flags) { - global_op_flags.set(global_op_flags.read() & ~flags); + global_op_flags.fetch_and(~flags); } /// cancel an in-progress request with the given return code @@ -2186,7 +2222,7 @@ public: Context *oncommit, version_t *objver = NULL, osd_reqid_t reqid = osd_reqid_t(), ZTracer::Trace *parent_trace = nullptr) { - Op *o = new Op(oid, oloc, op.ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, op.ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver, nullptr, parent_trace); o->priority = op.priority; o->mtime = mtime; @@ -2215,7 +2251,7 @@ public: int *data_offset = NULL, uint64_t features = 0, ZTracer::Trace *parent_trace = nullptr) { - Op *o = new Op(oid, oloc, op.ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, op.ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, onack, objver, data_offset, parent_trace); o->priority = op.priority; o->snapid = snapid; @@ -2249,7 +2285,7 @@ public: int *ctx_budget) { Op *o = new Op(object_t(), oloc, op.ops, - flags | global_op_flags.read() | CEPH_OSD_FLAG_READ | + flags | global_op_flags | CEPH_OSD_FLAG_READ | CEPH_OSD_FLAG_IGNORE_OVERLAY, onack, NULL); o->target.precalc_pgid = true; @@ -2337,7 +2373,7 @@ public: int i = init_ops(ops, 1, extra_ops); ops[i].op.op = CEPH_OSD_OP_STAT; C_Stat *fin = new C_Stat(psize, pmtime, onfinish); - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, fin, objver); o->snapid = snap; o->outbl = &fin->bl; @@ -2369,7 +2405,7 @@ public: ops[i].op.extent.truncate_size = 0; ops[i].op.extent.truncate_seq = 0; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, onfinish, objver, nullptr, parent_trace); o->snapid = snap; o->outbl = pbl; @@ -2401,7 +2437,7 @@ public: ops[i].op.extent.truncate_seq = 0; ops[i].indata = cmp_bl; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, onfinish, objver); o->snapid = snap; return o; @@ -2433,7 +2469,7 @@ public: ops[i].op.extent.truncate_size = trunc_size; ops[i].op.extent.truncate_seq = trunc_seq; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, onfinish, objver); o->snapid = snap; o->outbl = pbl; @@ -2452,7 +2488,7 @@ public: ops[i].op.extent.length = len; ops[i].op.extent.truncate_size = 0; ops[i].op.extent.truncate_seq = 0; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, onfinish, objver); o->snapid = snap; o->outbl = pbl; @@ -2471,7 +2507,7 @@ public: ops[i].op.xattr.value_len = 0; if (name) ops[i].indata.append(name); - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, onfinish, objver); o->snapid = snap; o->outbl = pbl; @@ -2488,7 +2524,7 @@ public: int i = init_ops(ops, 1, extra_ops); ops[i].op.op = CEPH_OSD_OP_GETXATTRS; C_GetAttrs *fin = new C_GetAttrs(attrset, onfinish); - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_READ, fin, objver); o->snapid = snap; o->outbl = &fin->bl; @@ -2501,7 +2537,7 @@ public: snapid_t snap, bufferlist *pbl, int flags, Context *onfinish, version_t *objver = NULL, ObjectOperation *extra_ops = NULL) { - return read(oid, oloc, 0, 0, snap, pbl, flags | global_op_flags.read() | + return read(oid, oloc, 0, 0, snap, pbl, flags | global_op_flags | CEPH_OSD_FLAG_READ, onfinish, objver, extra_ops); } @@ -2512,7 +2548,7 @@ public: const SnapContext& snapc, int flags, Context *oncommit, version_t *objver = NULL) { - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2536,7 +2572,7 @@ public: ops[i].op.extent.truncate_seq = 0; ops[i].indata = bl; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver, nullptr, parent_trace); o->mtime = mtime; @@ -2570,7 +2606,7 @@ public: ops[i].op.extent.truncate_size = 0; ops[i].op.extent.truncate_seq = 0; ops[i].indata = bl; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2605,7 +2641,7 @@ public: ops[i].op.extent.truncate_seq = trunc_seq; ops[i].indata = bl; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2626,7 +2662,7 @@ public: ops[i].op.extent.length = bl.length(); ops[i].indata = bl; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2660,7 +2696,7 @@ public: ops[i].op.writesame.data_length = bl.length(); ops[i].indata = bl; ops[i].op.flags = op_flags; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2693,7 +2729,7 @@ public: ops[i].op.extent.offset = trunc_size; ops[i].op.extent.truncate_size = trunc_size; ops[i].op.extent.truncate_seq = trunc_seq; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2710,7 +2746,7 @@ public: ops[i].op.op = CEPH_OSD_OP_ZERO; ops[i].op.extent.offset = off; ops[i].op.extent.length = len; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2743,7 +2779,7 @@ public: int i = init_ops(ops, 1, extra_ops); ops[i].op.op = CEPH_OSD_OP_CREATE; ops[i].op.flags = create_flags; - Op *o = new Op(oid, oloc, ops, global_flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, global_flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2759,7 +2795,7 @@ public: vector ops; int i = init_ops(ops, 1, extra_ops); ops[i].op.op = CEPH_OSD_OP_DELETE; - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2790,7 +2826,7 @@ public: if (name) ops[i].indata.append(name); ops[i].indata.append(bl); - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; @@ -2810,7 +2846,7 @@ public: ops[i].op.xattr.value_len = 0; if (name) ops[i].indata.append(name); - Op *o = new Op(oid, oloc, ops, flags | global_op_flags.read() | + Op *o = new Op(oid, oloc, ops, flags | global_op_flags | CEPH_OSD_FLAG_WRITE, oncommit, objver); o->mtime = mtime; o->snapc = snapc; diff --git a/ceph/src/osdc/WritebackHandler.h b/ceph/src/osdc/WritebackHandler.h index c28353223..bf90fdd0a 100644 --- a/ceph/src/osdc/WritebackHandler.h +++ b/ceph/src/osdc/WritebackHandler.h @@ -15,7 +15,8 @@ class WritebackHandler { virtual void read(const object_t& oid, uint64_t object_no, const object_locator_t& oloc, uint64_t off, uint64_t len, snapid_t snapid, bufferlist *pbl, uint64_t trunc_size, - __u32 trunc_seq, int op_flags, Context *onfinish) = 0; + __u32 trunc_seq, int op_flags, + const ZTracer::Trace &parent_trace, Context *onfinish) = 0; /** * check if a given extent read result may change due to a write * @@ -34,7 +35,9 @@ class WritebackHandler { const SnapContext& snapc, const bufferlist &bl, ceph::real_time mtime, uint64_t trunc_size, __u32 trunc_seq, - ceph_tid_t journal_tid, Context *oncommit) = 0; + ceph_tid_t journal_tid, + const ZTracer::Trace &parent_trace, + Context *oncommit) = 0; virtual void overwrite_extent(const object_t& oid, uint64_t off, uint64_t len, ceph_tid_t original_journal_tid, diff --git a/ceph/src/perf_histogram.h b/ceph/src/perf_histogram.h new file mode 100644 index 000000000..06ebaf805 --- /dev/null +++ b/ceph/src/perf_histogram.h @@ -0,0 +1,227 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2017 OVH + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_COMMON_PERF_HISTOGRAM_H +#define CEPH_COMMON_PERF_HISTOGRAM_H + +#include "common/Formatter.h" +#include "include/int_types.h" + +#include +#include +#include +#include + +class PerfHistogramCommon { +public: + enum scale_type_d : uint8_t { + SCALE_LINEAR = 1, + SCALE_LOG2 = 2, + }; + + struct axis_config_d { + const char *m_name = nullptr; + scale_type_d m_scale_type = SCALE_LINEAR; + int64_t m_min = 0; + int64_t m_quant_size = 0; + int32_t m_buckets = 0; + axis_config_d() = default; + axis_config_d(const char* name, + scale_type_d scale_type, + int64_t min, + int64_t quant_size, + int32_t buckets) + : m_name(name), + m_scale_type(scale_type), + m_min(min), + m_quant_size(quant_size), + m_buckets(buckets) + {} + }; + +protected: + /// Dump configuration of one axis to a formatter + static void dump_formatted_axis(ceph::Formatter *f, const axis_config_d &ac); + + /// Quantize given value and convert to bucket number on given axis + static int64_t get_bucket_for_axis(int64_t value, const axis_config_d &ac); + + /// Calculate inclusive ranges of axis values for each bucket on that axis + static std::vector> get_axis_bucket_ranges( + const axis_config_d &ac); +}; + +/// PerfHistogram does trace a histogram of input values. It's an extended +/// version of a standard histogram which does trace characteristics of a single +/// one value only. In this implementation, values can be traced in multiple +/// dimensions - i.e. we can create a histogram of input request size (first +/// dimension) and processing latency (second dimension). Creating standard +/// histogram out of such multidimensional one is trivial and requires summing +/// values across dimensions we're not interested in. +template +class PerfHistogram : public PerfHistogramCommon { +public: + /// Initialize new histogram object + PerfHistogram(std::initializer_list axes_config) { + assert(axes_config.size() == DIM && + "Invalid number of axis configuration objects"); + + int i = 0; + for (const auto &ac : axes_config) { + assert(ac.m_buckets > 0 && "Must have at least one bucket on axis"); + assert(ac.m_quant_size > 0 && + "Quantization unit must be non-zero positive integer value"); + + m_axes_config[i++] = ac; + } + + m_rawData.reset(new std::atomic[get_raw_size()]); + } + + /// Copy from other histogram object + PerfHistogram(const PerfHistogram &other) + : m_axes_config(other.m_axes_config) { + int64_t size = get_raw_size(); + m_rawData.reset(new std::atomic[size]); + for (int64_t i = 0; i < size; i++) { + m_rawData[i] = other.m_rawData[i]; + } + } + + /// Set all histogram values to 0 + void reset() { + auto size = get_raw_size(); + for (auto i = size; --i >= 0;) { + m_rawData[i] = 0; + } + } + + /// Increase counter for given axis values by one + template + void inc(T... axis) { + auto index = get_raw_index_for_value(axis...); + m_rawData[index] += 1; + } + + /// Increase counter for given axis buckets by one + template + void inc_bucket(T... bucket) { + auto index = get_raw_index_for_bucket(bucket...); + m_rawData[index] += 1; + } + + /// Read value from given bucket + template + uint64_t read_bucket(T... bucket) const { + auto index = get_raw_index_for_bucket(bucket...); + return m_rawData[index]; + } + + /// Dump data to a Formatter object + void dump_formatted(ceph::Formatter *f) const { + // Dump axes configuration + f->open_array_section("axes"); + for (auto &ac : m_axes_config) { + dump_formatted_axis(f, ac); + } + f->close_section(); + + // Dump histogram values + dump_formatted_values(f); + } + +protected: + /// Raw data stored as linear space, internal indexes are calculated on + /// demand. + std::unique_ptr[]> m_rawData; + + /// Configuration of axes + std::array m_axes_config; + + /// Dump histogram counters to a formatter + void dump_formatted_values(ceph::Formatter *f) const { + visit_values([f](int) { f->open_array_section("values"); }, + [f](int64_t value) { f->dump_unsigned("value", value); }, + [f](int) { f->close_section(); }); + } + + /// Get number of all histogram counters + int64_t get_raw_size() { + int64_t ret = 1; + for (const auto &ac : m_axes_config) { + ret *= ac.m_buckets; + } + return ret; + } + + /// Calculate m_rawData index from axis values + template + int64_t get_raw_index_for_value(T... axes) const { + static_assert(sizeof...(T) == DIM, "Incorrect number of arguments"); + return get_raw_index_internal<0>(get_bucket_for_axis, 0, axes...); + } + + /// Calculate m_rawData index from axis bucket numbers + template + int64_t get_raw_index_for_bucket(T... buckets) const { + static_assert(sizeof...(T) == DIM, "Incorrect number of arguments"); + return get_raw_index_internal<0>( + [](int64_t bucket, const axis_config_d &ac) { + assert(bucket >= 0 && "Bucket index can not be negative"); + assert(bucket < ac.m_buckets && "Bucket index too large"); + return bucket; + }, + 0, buckets...); + } + + template + int64_t get_raw_index_internal(F bucket_evaluator, int64_t startIndex, + int64_t value, T... tail) const { + static_assert(level + 1 + sizeof...(T) == DIM, + "Internal consistency check"); + auto &ac = m_axes_config[level]; + auto bucket = bucket_evaluator(value, ac); + return get_raw_index_internal( + bucket_evaluator, ac.m_buckets * startIndex + bucket, tail...); + } + + template + int64_t get_raw_index_internal(F, int64_t startIndex) const { + static_assert(level == DIM, "Internal consistency check"); + return startIndex; + } + + /// Visit all histogram counters, call onDimensionEnter / onDimensionLeave + /// when starting / finishing traversal + /// on given axis, call onValue when dumping raw histogram counter value. + template + void visit_values(FDE onDimensionEnter, FV onValue, FDL onDimensionLeave, + int level = 0, int startIndex = 0) const { + if (level == DIM) { + onValue(m_rawData[startIndex]); + return; + } + + onDimensionEnter(level); + auto &ac = m_axes_config[level]; + startIndex *= ac.m_buckets; + for (int32_t i = 0; i < ac.m_buckets; ++i, ++startIndex) { + visit_values(onDimensionEnter, onValue, onDimensionLeave, level + 1, + startIndex); + } + onDimensionLeave(level); + } +}; + +#endif diff --git a/ceph/src/pybind/ceph_argparse.py b/ceph/src/pybind/ceph_argparse.py index 9328b6c47..cc96d7708 100644 --- a/ceph/src/pybind/ceph_argparse.py +++ b/ceph/src/pybind/ceph_argparse.py @@ -395,6 +395,10 @@ class CephName(CephArgtype): self.nametype = "mgr" self.val = s return + elif s == "mon": + self.nametype = "mon" + self.val = s + return if s.find('.') == -1: raise ArgumentFormat('CephName: no . in {0}'.format(s)) else: @@ -920,12 +924,12 @@ def validate(args, signature, flags=0, partial=False): # no arg, but not required? Continue consuming mysig # in case there are later required args - if not myarg and not desc.req: + if myarg in (None, []) and not desc.req: break # out of arguments for a required param? # Either return (if partial validation) or raise - if not myarg and desc.req: + if myarg in (None, []) and desc.req: if desc.N and desc.numseen < 1: # wanted N, didn't even get 1 if partial: @@ -1262,7 +1266,7 @@ def send_command(cluster, target=('mon', ''), cmd=None, inbuf=b'', timeout=0, if verbose: print('{0} to {1}'.format(cmd, target[0]), file=sys.stderr) - if target[1] == '': + if len(target) < 2 or target[1] == '': ret, outbuf, outs = run_in_thread( cluster.mon_command, cmd, inbuf, timeout) else: diff --git a/ceph/src/pybind/ceph_daemon.py b/ceph/src/pybind/ceph_daemon.py index 48bd4e0d7..0ab591195 100755 --- a/ceph/src/pybind/ceph_daemon.py +++ b/ceph/src/pybind/ceph_daemon.py @@ -87,36 +87,37 @@ def admin_socket(asok_path, cmd, format=''): return ret -def _gettermsize(): - try: - rows, cols = struct.unpack('hhhh', ioctl(0, TIOCGWINSZ, 8*'\x00'))[0:2] - except IOError: - return 25, 80 - - return rows,cols - - class Termsize(object): - + DEFAULT_SIZE = (25, 80) def __init__(self): - self.rows, self.cols = _gettermsize() + self.rows, self.cols = self._gettermsize() self.changed = False + def _gettermsize(self): + try: + fd = sys.stdin.fileno() + sz = struct.pack('hhhh', 0, 0, 0, 0) + rows, cols = struct.unpack('hhhh', ioctl(fd, TIOCGWINSZ, sz))[:2] + return rows, cols + except IOError: + return self.DEFAULT_SIZE + def update(self): - rows, cols = _gettermsize() - self.changed = self.changed or ( - (self.rows != rows) or (self.cols != cols) - ) + rows, cols = self._gettermsize() + if not self.changed: + self.changed = (self.rows, self.cols) != (rows, cols) self.rows, self.cols = rows, cols def reset_changed(self): self.changed = False def __str__(self): - return '%s(%dx%d, changed %s)' % (self.__class__, self.rows, self.cols, self.changed) + return '%s(%dx%d, changed %s)' % (self.__class__, + self.rows, self.cols, self.changed) def __repr__(self): - return 'Termsize(%d,%d,%s)' % (self.__class__, self.rows, self.cols, self.changed) + return 'Termsize(%d,%d,%s)' % (self.__class__, + self.rows, self.cols, self.changed) class DaemonWatcher(object): diff --git a/ceph/src/pybind/ceph_rest_api.py b/ceph/src/pybind/ceph_rest_api.py index 9bae3ef62..6ca217798 100755 --- a/ceph/src/pybind/ceph_rest_api.py +++ b/ceph/src/pybind/ceph_rest_api.py @@ -29,6 +29,12 @@ DEFAULT_LOG_LEVEL = 'warning' DEFAULT_LOGDIR = '/var/log/ceph' # default client name will be 'client.' +# network failure could keep the underlying json_command() waiting forever, +# set a timeout, so it bails out on timeout. +DEFAULT_TIMEOUT = 20 +# and retry in that case. +DEFAULT_TRIES = 5 + # 'app' must be global for decorators, etc. APPNAME = '__main__' app = flask.Flask(APPNAME) @@ -481,9 +487,18 @@ def handler(catchall_path=None, fmt=None, target=None): cmdtarget = ('mon', '') app.logger.debug('sending command prefix %s argdict %s', prefix, argdict) - ret, outbuf, outs = json_command(app.ceph_cluster, prefix=prefix, - target=cmdtarget, - inbuf=flask.request.data, argdict=argdict) + + for _ in range(DEFAULT_TRIES): + ret, outbuf, outs = json_command(app.ceph_cluster, prefix=prefix, + target=cmdtarget, + inbuf=flask.request.data, + argdict=argdict, + timeout=DEFAULT_TIMEOUT) + if ret != -errno.EINTR: + break + else: + return make_response(fmt, '', + 'Timedout: {0} ({1})'.format(outs, ret), 504) if ret: return make_response(fmt, '', 'Error: {0} ({1})'.format(outs, ret), 400) diff --git a/ceph/src/pybind/mgr/dashboard/HACKING.rst b/ceph/src/pybind/mgr/dashboard/HACKING.rst new file mode 100644 index 000000000..b1cae5f0d --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/HACKING.rst @@ -0,0 +1,95 @@ + +HACKING +======= + +See the top-level docs in the ceph repository for general information about how to submit code. This +file is about the specifics of how this module fits together. + +This module uses deliberately simple/explicit structure so that it is accessbile +to people who are not specialists in webapps. Very little javascript knowledge +is needed. The absence of a javascript toolchain (node, bower, grunt, etc) is +considered a feature rather than a bug. All of the CSS and Javascript in +the git repository is used as-is without any compilation/minification. + +On the server (i.e. python-side) +-------------------------------- + +In the serve() method, there's a cherrypy request handler object with methods that correspond to URLs. +See the cherrypy documentatino for how that stuff works. + +There is a mixture of endpoints that return JSON (for live updates of pages) and endpoints that return +HTML (for initial loads of pages). The HTML files are rendered from jinja2 templates (the .html files +in the source tree). + +The initial render of the HTML template includes some json-ized inline data, so that the page can +be rendered immediately without having to make another request to the server to load the data +after loading the markup. + +The pattern is that for some resource 'foo' we would generally have three methods, along the lines of: + +:: + + def _foo(self): + return {...the data of interest...} + + @cherrypy.expose + def foo(self): + data = self._foo() + *render a foo.html template with data inline* + + @cherrypy.expose + @cherrypy.tools.json_out() + def foo_data(self): + return self._foo() + +In the browser (Javascript and markup) +-------------------------------------- + +The javascript code uses the rivets.js (http://rivetsjs.com/) library to render the data from +the server into HTML templates, and to enable subsequent updates without reloading the whole +page. + +The use of rivets.js looks something like this: + +:: + + + + {server.hostname} + + +The "rv-each" attributes do iteration over lists, and the curly braces substitute +values into place. See the rivets docs for more. + +If you see double-curly-brace items in the markup, those are the ones that +were populated server side, including the initial data, like this: + +:: + + var content_data = {{ content_data }}; + +If you really wanted to, you could skip rivets on any given page, and just +render the whole page server-side with ``{{}}`` entries, but that of course +leaves you with a page that won't update without the user actively refreshing. + +The common markup such as headers and footers lives in ``base.html``, and +all the other pages' templates start with ``{% extends "base.html" %}``. This +is jinja2 syntax that is handled server-side. + +Styles/CSS +---------- + +This module includes the AdminLTE dashboard layout. This is perhaps overkill, +but saves us from writing any significant amount of CSS. If you need to fudge +something, don't be shy about putting "style=" attributes inline within reason. + +URLs +---- + +The URLs follow a convention that CherryPy knows how to route for us: the +name of the handler function, followed by positional arguments between +slashes. For example, a handler like ``def filesystem(self, fscid)`` is +automatically called on requests like ``/filesystem/123``` + + + diff --git a/ceph/src/pybind/mgr/dashboard/README.rst b/ceph/src/pybind/mgr/dashboard/README.rst new file mode 100644 index 000000000..1b0276632 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/README.rst @@ -0,0 +1,72 @@ + +========================= +ceph-mgr dashboard module +========================= + +Dependencies +============ + +On Ubuntu Xenial: + +:: + + apt-get install python-cherrypy3 + +On Fedora: + +:: + + dnf install -y python-cherrypy + + +If you had already enabled the module, restart ceph-mgr after installing dependencies to reload the module. + +Enabling +======== + +Add this to your ceph.conf on nodes where you run ceph-mgr: + +:: + + [mgr] + mgr modules = dashboard + +If you use any other ceph-mgr modules, make sure they're in the list too. + +Restart the ceph-mgr daemon after modifying the setting to load the module. + +Accessing +========= + +Point your browser at port 7000 on the server where ceph-mgr is running. + +FAQs +==== + +Q: Aargh there's no authentication! Are you crazy? +A: At present this module only serves read-only status information, and it is disabled by default. Administrators can make a decision + at the point of enabling the module whether they want to limit access to the port, and/or put it behind an authenticating HTTP proxy + such as Apache+digest auth. + A motivated person could totally build in some authentication stuff though: that would probably only be worth the effort at the point + that non-readonly features were added. + +Q: Aargh there's no SSL! Are you crazy? +A: See the authentication question. You can always configure your own SSL gateway on top of this if you need it. + +Q: Why CherryPy? +A: ceph-mgr is a pure CPython environment, which means that anything gevent based doesn't work (gevent relies on C-level hacks). CherryPy + includes a web server based on standard python threads, making it a convenient choice. There are other web frameworks of course. + +Q: Does this use the `restful` module? +A: No. This module loads everything it needs directly via the interfaces available to ceph-mgr modules, and sends it straight to your browser. + +Q: My browser says "connection refused" +A: Check that you have a running ceph-mgr daemon. Look in the ceph-mgr log (/var/log/ceph/ceph-mgr...) for errors loading modules. Check + that you have enabled the module (see "Enabling" above) + +Q: My log contains an error like "ImportError: No module named cherrypy" +A: See "Dependencies" above. Make sure you installed a 3.x version of cherrypy, many distros have multiple cherrypy packages. + +Q: I want to add something to the UI, how do I do it? +A: See HACKING.rst + diff --git a/ceph/src/pybind/mgr/rest/__init__.py b/ceph/src/pybind/mgr/dashboard/__init__.py similarity index 96% rename from ceph/src/pybind/mgr/rest/__init__.py rename to ceph/src/pybind/mgr/dashboard/__init__.py index e87777b46..79f5b86fd 100644 --- a/ceph/src/pybind/mgr/rest/__init__.py +++ b/ceph/src/pybind/mgr/dashboard/__init__.py @@ -1,3 +1,2 @@ from module import * # NOQA - diff --git a/ceph/src/pybind/mgr/dashboard/base.html b/ceph/src/pybind/mgr/dashboard/base.html new file mode 100644 index 000000000..41d059347 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/base.html @@ -0,0 +1,292 @@ + + + + + + + Ceph + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
+ + + +
+ + {% block content %}{% endblock %} + +
+ + + +
+ + + + Copyright © 2016 by Ceph Contributors. Free software (LGPL 2.1) +
+ + + + + +
+ +
+ + + + + + + + + + diff --git a/ceph/src/pybind/mgr/dashboard/cephfs_clients.py b/ceph/src/pybind/mgr/dashboard/cephfs_clients.py new file mode 100644 index 000000000..40d79713f --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/cephfs_clients.py @@ -0,0 +1,25 @@ + +import json + +from mgr_module import CommandResult +from remote_view_cache import RemoteViewCache + + +class CephFSClients(RemoteViewCache): + def __init__(self, module_inst, fscid): + super(CephFSClients, self).__init__(module_inst) + + self.fscid = fscid + + def _get(self): + mds_spec = "{0}:0".format(self.fscid) + result = CommandResult("") + self._module.send_command(result, "mds", mds_spec, + json.dumps({ + "prefix": "session ls", + }), + "") + r, outb, outs = result.wait() + # TODO handle nonzero returns, e.g. when rank isn't active + assert r == 0 + return json.loads(outb) diff --git a/ceph/src/pybind/mgr/dashboard/clients.html b/ceph/src/pybind/mgr/dashboard/clients.html new file mode 100644 index 000000000..8d775cc5a --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/clients.html @@ -0,0 +1,66 @@ +{% extends "base.html" %} + +{% block content %} + + + + +
+

+ Clients +

+
+ +
+
+
+

Clients

+
+
+ + + + + + + + + + + + + + + + + + + + + +
IDTypeStateVersionHostRoot
{client.id}{client.type}{client.state}{client.version}{client.hostname}{client.root}
+
+
+ + +
+ + +{% endblock %} diff --git a/ceph/src/pybind/mgr/dashboard/filesystem.html b/ceph/src/pybind/mgr/dashboard/filesystem.html new file mode 100644 index 000000000..a8bd193c9 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/filesystem.html @@ -0,0 +1,290 @@ +{% extends "base.html" %} + +{% block content %} + + + + +
+

+ Filesystem {filesystem.name} +

+
+ +
+

+   Clients: {filesystem.client_count} + Detail... +

+ +
+
+
+
+

Ranks

+
+
+ + + + + + + + + + + + + + + + + + + + + +
RankStateDaemonActivityDentriesInodes
{rank.rank}{rank.state}{rank.mds}{rank.activity}{rank.dns | dimless}{rank.inos | dimless}
+
+
+
+
+
+
+

Pools

+
+
+ + + + + + + + + + + + + + + + + + + +
PoolTypeUsedAvail
{pool.pool}{pool.type}{pool.used | dimless}{pool.avail | dimless} +
+
+
+
+
+
+
+ +
+
+
+

Standby daemons

+
+
+ + + + + + + + + + + +
Daemon
{standby.name}
+
+
+ +
+
+ +
+ + +{% endblock %} diff --git a/ceph/src/pybind/mgr/dashboard/health.html b/ceph/src/pybind/mgr/dashboard/health.html new file mode 100644 index 000000000..e41a1e2da --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/health.html @@ -0,0 +1,234 @@ + +{% extends "base.html" %} + +{% block content %} + + + + + +
+

+ Health +

+ +
+ + +
+ + Overall status: {health.overall_status} + +
    +
  • + {summary.severity}: {summary.summary} +
  • +
+ +
+
+
+ + +
+ Monitors + {mon_status | mon_summary} +
+ +
+
+ +
+
+ + +
+ OSDs + {osd_map | osd_summary} +
+ +
+
+
+ +
+
+ Pools +
+
+ + + + + + + + + + + + + + + + +
NamePG statusUsageActivity
+ {pool.pool_name} + + {pool.pg_status | pg_status} + + {pool.stats.bytes_used.latest | dimless} / + {pool.stats.max_avail.latest | dimless } + + {pool.stats.rd_bytes.rate | dimless } rd, { + pool.stats.wr_bytes.rate | dimless } wr +
+
+ +
+ +
+
+ Cluster log +
+
+ +
+
+ + + { line.stamp } {line.priority}  + + + { line.message } +
+
+
+
+
+
+ + + { line.stamp } {line.priority}  + + + { line.message } +
+
+
+
+ +
+
+ +
+ +
+ + + + +
+ +{% endblock %} diff --git a/ceph/src/pybind/mgr/dashboard/module.py b/ceph/src/pybind/mgr/dashboard/module.py new file mode 100644 index 000000000..362faddad --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/module.py @@ -0,0 +1,760 @@ + +""" +Demonstrate writing a Ceph web interface inside a mgr module. +""" + +# We must share a global reference to this instance, because it is the +# gatekeeper to all accesses to data from the C++ side (e.g. the REST API +# request handlers need to see it) +from collections import defaultdict +import collections + +_global_instance = {'plugin': None} +def global_instance(): + assert _global_instance['plugin'] is not None + return _global_instance['plugin'] + + +import os +import logging +import logging.config +import json +import sys +import time +import threading + +import cherrypy +import jinja2 + +from mgr_module import MgrModule, CommandResult + +from types import OsdMap, NotFound, Config, FsMap, MonMap, \ + PgSummary, Health, MonStatus + +import rados +from rbd_ls import RbdLs +from cephfs_clients import CephFSClients + + +log = logging.getLogger("dashboard") + + +# How many cluster log lines shall we hold onto in our +# python module for the convenience of the GUI? +LOG_BUFFER_SIZE = 30 + +# cherrypy likes to sys.exit on error. don't let it take us down too! +def os_exit_noop(): + pass + +os._exit = os_exit_noop + + +def recurse_refs(root, path): + if isinstance(root, dict): + for k, v in root.items(): + recurse_refs(v, path + "->%s" % k) + elif isinstance(root, list): + for n, i in enumerate(root): + recurse_refs(i, path + "[%d]" % n) + + log.info("%s %d (%s)" % (path, sys.getrefcount(root), root.__class__)) + + +class Module(MgrModule): + def __init__(self, *args, **kwargs): + super(Module, self).__init__(*args, **kwargs) + _global_instance['plugin'] = self + self.log.info("Constructing module {0}: instance {1}".format( + __name__, _global_instance)) + + self.log_primed = False + self.log_buffer = collections.deque(maxlen=LOG_BUFFER_SIZE) + self.audit_buffer = collections.deque(maxlen=LOG_BUFFER_SIZE) + + # Keep a librados instance for those that need it. + self._rados = None + + # Stateful instances of RbdLs, hold cached results. Key to dict + # is pool name. + self.rbd_ls = {} + + # Stateful instances of CephFSClients, hold cached results. Key to + # dict is FSCID + self.cephfs_clients = {} + + # A short history of pool df stats + self.pool_stats = defaultdict(lambda: defaultdict( + lambda: collections.deque(maxlen=10))) + + @property + def rados(self): + """ + A librados instance to be shared by any classes within + this mgr module that want one. + """ + if self._rados: + return self._rados + + from mgr_module import ceph_state + ctx_capsule = ceph_state.get_context() + self._rados = rados.Rados(context=ctx_capsule) + self._rados.connect() + + return self._rados + + def get_localized_config(self, key): + r = self.get_config(self.get_mgr_id() + '/' + key) + if r is None: + r = self.get_config(key) + return r + + def update_pool_stats(self): + df = global_instance().get("df") + pool_stats = dict([(p['id'], p['stats']) for p in df['pools']]) + now = time.time() + for pool_id, stats in pool_stats.items(): + for stat_name, stat_val in stats.items(): + self.pool_stats[pool_id][stat_name].appendleft((now, stat_val)) + + def notify(self, notify_type, notify_val): + if notify_type == "clog": + # Only store log messages once we've done our initial load, + # so that we don't end up duplicating. + if self.log_primed: + if notify_val['channel'] == "audit": + self.audit_buffer.appendleft(notify_val) + else: + self.log_buffer.appendleft(notify_val) + elif notify_type == "pg_summary": + self.update_pool_stats() + else: + pass + + def get_sync_object(self, object_type, path=None): + if object_type == OsdMap: + data = self.get("osd_map") + + assert data is not None + + data['tree'] = self.get("osd_map_tree") + data['crush'] = self.get("osd_map_crush") + data['crush_map_text'] = self.get("osd_map_crush_map_text") + data['osd_metadata'] = self.get("osd_metadata") + obj = OsdMap(data) + elif object_type == Config: + data = self.get("config") + obj = Config( data) + elif object_type == MonMap: + data = self.get("mon_map") + obj = MonMap(data) + elif object_type == FsMap: + data = self.get("fs_map") + obj = FsMap(data) + elif object_type == PgSummary: + data = self.get("pg_summary") + self.log.debug("JSON: {0}".format(data)) + obj = PgSummary(data) + elif object_type == Health: + data = self.get("health") + obj = Health(json.loads(data['json'])) + elif object_type == MonStatus: + data = self.get("mon_status") + obj = MonStatus(json.loads(data['json'])) + else: + raise NotImplementedError(object_type) + + # TODO: move 'path' handling up into C++ land so that we only + # Pythonize the part we're interested in + if path: + try: + for part in path: + if isinstance(obj, dict): + obj = obj[part] + else: + obj = getattr(obj, part) + except (AttributeError, KeyError): + raise NotFound(object_type, path) + + return obj + + def shutdown(self): + log.info("Stopping server...") + cherrypy.engine.exit() + log.info("Stopped server") + + log.info("Stopping librados...") + if self._rados: + self._rados.shutdown() + log.info("Stopped librados.") + + def get_latest(self, daemon_type, daemon_name, stat): + data = self.get_counter(daemon_type, daemon_name, stat)[stat] + if data: + return data[-1][1] + else: + return 0 + + def get_rate(self, daemon_type, daemon_name, stat): + data = self.get_counter(daemon_type, daemon_name, stat)[stat] + + if data and len(data) > 1: + return (data[-1][1] - data[-2][1]) / float(data[-1][0] - data[-2][0]) + else: + return 0 + + def format_dimless(self, n, width, colored=True): + """ + Format a number without units, so as to fit into `width` characters, substituting + an appropriate unit suffix. + """ + units = [' ', 'k', 'M', 'G', 'T', 'P'] + unit = 0 + while len("%s" % (int(n) // (1000**unit))) > width - 1: + unit += 1 + + if unit > 0: + truncated_float = ("%f" % (n / (1000.0 ** unit)))[0:width - 1] + if truncated_float[-1] == '.': + truncated_float = " " + truncated_float[0:-1] + else: + truncated_float = "%{wid}d".format(wid=width-1) % n + formatted = "%s%s" % (truncated_float, units[unit]) + + if colored: + # TODO: html equivalent + # if n == 0: + # color = self.BLACK, False + # else: + # color = self.YELLOW, False + # return self.bold(self.colorize(formatted[0:-1], color[0], color[1])) \ + # + self.bold(self.colorize(formatted[-1], self.BLACK, False)) + return formatted + else: + return formatted + + def fs_status(self, fs_id): + mds_versions = defaultdict(list) + + fsmap = self.get("fs_map") + filesystem = None + for fs in fsmap['filesystems']: + if fs['id'] == fs_id: + filesystem = fs + break + + rank_table = [] + + mdsmap = filesystem['mdsmap'] + + client_count = 0 + + for rank in mdsmap["in"]: + up = "mds_{0}".format(rank) in mdsmap["up"] + if up: + gid = mdsmap['up']["mds_{0}".format(rank)] + info = mdsmap['info']['gid_{0}'.format(gid)] + dns = self.get_latest("mds", info['name'], "mds.inodes") + inos = self.get_latest("mds", info['name'], "mds_mem.ino") + + if rank == 0: + client_count = self.get_latest("mds", info['name'], + "mds_sessions.session_count") + elif client_count == 0: + # In case rank 0 was down, look at another rank's + # sessionmap to get an indication of clients. + client_count = self.get_latest("mds", info['name'], + "mds_sessions.session_count") + + laggy = "laggy_since" in info + + state = info['state'].split(":")[1] + if laggy: + state += "(laggy)" + + # if state == "active" and not laggy: + # c_state = self.colorize(state, self.GREEN) + # else: + # c_state = self.colorize(state, self.YELLOW) + + # Populate based on context of state, e.g. client + # ops for an active daemon, replay progress, reconnect + # progress + activity = "" + + if state == "active": + activity = "Reqs: " + self.format_dimless( + self.get_rate("mds", info['name'], "mds_server.handle_client_request"), + 5 + ) + "/s" + + metadata = self.get_metadata('mds', info['name']) + mds_versions[metadata['ceph_version']].append(info['name']) + rank_table.append( + { + "rank": rank, + "state": state, + "mds": info['name'], + "activity": activity, + "dns": dns, + "inos": inos + } + ) + + else: + rank_table.append( + { + "rank": rank, + "state": "failed", + "mds": "", + "activity": "", + "dns": 0, + "inos": 0 + } + ) + + # Find the standby replays + for gid_str, daemon_info in mdsmap['info'].iteritems(): + if daemon_info['state'] != "up:standby-replay": + continue + + inos = self.get_latest("mds", daemon_info['name'], "mds_mem.ino") + dns = self.get_latest("mds", daemon_info['name'], "mds.inodes") + + activity = "Evts: " + self.format_dimless( + self.get_rate("mds", daemon_info['name'], "mds_log.replay"), + 5 + ) + "/s" + + rank_table.append( + { + "rank": "{0}-s".format(daemon_info['rank']), + "state": "standby-replay", + "mds": daemon_info['name'], + "activity": activity, + "dns": dns, + "inos": inos + } + ) + + df = self.get("df") + pool_stats = dict([(p['id'], p['stats']) for p in df['pools']]) + osdmap = self.get("osd_map") + pools = dict([(p['pool'], p) for p in osdmap['pools']]) + metadata_pool_id = mdsmap['metadata_pool'] + data_pool_ids = mdsmap['data_pools'] + + pools_table = [] + for pool_id in [metadata_pool_id] + data_pool_ids: + pool_type = "metadata" if pool_id == metadata_pool_id else "data" + stats = pool_stats[pool_id] + pools_table.append({ + "pool": pools[pool_id]['pool_name'], + "type": pool_type, + "used": stats['bytes_used'], + "avail": stats['max_avail'] + }) + + standby_table = [] + for standby in fsmap['standbys']: + metadata = self.get_metadata('mds', standby['name']) + mds_versions[metadata['ceph_version']].append(standby['name']) + + standby_table.append({ + 'name': standby['name'] + }) + + return { + "filesystem": { + "id": fs_id, + "name": mdsmap['fs_name'], + "client_count": client_count, + "clients_url": "/clients/{0}/".format(fs_id), + "ranks": rank_table, + "pools": pools_table + }, + "standbys": standby_table, + "versions": mds_versions + } + + def serve(self): + current_dir = os.path.dirname(os.path.abspath(__file__)) + + jinja_loader = jinja2.FileSystemLoader(current_dir) + env = jinja2.Environment(loader=jinja_loader) + + result = CommandResult("") + self.send_command(result, "mon", "", json.dumps({ + "prefix":"log last", + "format": "json" + }), "") + r, outb, outs = result.wait() + if r != 0: + # Oh well. We won't let this stop us though. + self.log.error("Error fetching log history (r={0}, \"{1}\")".format( + r, outs)) + else: + try: + lines = json.loads(outb) + except ValueError: + self.log.error("Error decoding log history") + else: + for l in lines: + if l['channel'] == 'audit': + self.audit_buffer.appendleft(l) + else: + self.log_buffer.appendleft(l) + + self.log_primed = True + + class Root(object): + def _toplevel_data(self): + """ + Data consumed by the base.html template + """ + fsmap = global_instance().get_sync_object(FsMap) + filesystems = [ + { + "id": f['id'], + "name": f['mdsmap']['fs_name'], + "url": "/filesystem/{0}/".format(f['id']) + } + for f in fsmap.data['filesystems'] + ] + + return { + 'health': global_instance().get_sync_object(Health).data, + 'filesystems': filesystems + } + + @cherrypy.expose + def filesystem(self, fs_id): + template = env.get_template("filesystem.html") + + toplevel_data = self._toplevel_data() + + content_data = { + "fs_status": global_instance().fs_status(int(fs_id)) + } + + return template.render( + ceph_version=global_instance().version, + toplevel_data=json.dumps(toplevel_data, indent=2), + content_data=json.dumps(content_data, indent=2) + ) + + @cherrypy.expose + @cherrypy.tools.json_out() + def filesystem_data(self, fs_id): + return global_instance().fs_status(int(fs_id)) + + def _osd(self, osd_id): + #global_instance().fs_status(int(fs_id)) + osd_id = int(osd_id) + + osd_map = global_instance().get("osd_map") + + osd = None + for o in osd_map['osds']: + if o['osd'] == osd_id: + osd = o + break + + assert osd is not None # TODO 400 + + osd_spec = "{0}".format(osd_id) + + osd_metadata = global_instance().get_metadata( + "osd", osd_spec) + + result = CommandResult("") + global_instance().send_command(result, "osd", osd_spec, + json.dumps({ + "prefix": "perf histogram dump", + }), + "") + r, outb, outs = result.wait() + assert r == 0 + histogram = json.loads(outb) + + return { + "osd": osd, + "osd_metadata": osd_metadata, + "osd_histogram": histogram + } + + @cherrypy.expose + def osd_perf(self, osd_id): + template = env.get_template("osd_perf.html") + toplevel_data = self._toplevel_data() + + return template.render( + ceph_version=global_instance().version, + toplevel_data=json.dumps(toplevel_data, indent=2), + content_data=json.dumps(self._osd(osd_id), indent=2) + ) + + @cherrypy.expose + @cherrypy.tools.json_out() + def osd_perf_data(self, osd_id): + return self._osd(osd_id) + + def _clients(self, fs_id): + cephfs_clients = global_instance().cephfs_clients.get(fs_id, None) + if cephfs_clients is None: + cephfs_clients = CephFSClients(global_instance(), fs_id) + global_instance().cephfs_clients[fs_id] = cephfs_clients + + status, clients = cephfs_clients.get() + #TODO do something sensible with status + + # Decorate the metadata with some fields that will be + # indepdendent of whether it's a kernel or userspace + # client, so that the javascript doesn't have to grok that. + for client in clients: + if "ceph_version" in client['client_metadata']: + client['type'] = "userspace" + client['version'] = client['client_metadata']['ceph_version'] + client['hostname'] = client['client_metadata']['hostname'] + elif "kernel_version" in client['client_metadata']: + client['type'] = "kernel" + client['version'] = client['kernel_version'] + client['hostname'] = client['client_metadata']['hostname'] + else: + client['type'] = "unknown" + client['version'] = "" + client['hostname'] = "" + + return clients + + @cherrypy.expose + def clients(self, fs_id): + template = env.get_template("clients.html") + + toplevel_data = self._toplevel_data() + + clients = self._clients(int(fs_id)) + global_instance().log.debug(json.dumps(clients, indent=2)) + content_data = { + "clients": clients, + "fscid": fs_id + } + + return template.render( + ceph_version=global_instance().version, + toplevel_data=json.dumps(toplevel_data, indent=2), + content_data=json.dumps(content_data, indent=2) + ) + + @cherrypy.expose + @cherrypy.tools.json_out() + def clients_data(self, fs_id): + return self._clients(int(fs_id)) + + def _rbd(self, pool_name): + rbd_ls = global_instance().rbd_ls.get(pool_name, None) + if rbd_ls is None: + rbd_ls = RbdLs(global_instance(), pool_name) + global_instance().rbd_ls[pool_name] = rbd_ls + + status, value = rbd_ls.get() + + interval = 5 + + wait = interval - rbd_ls.latency + def wait_and_load(): + time.sleep(wait) + rbd_ls.get() + + threading.Thread(target=wait_and_load).start() + + assert status != RbdLs.VALUE_NONE # FIXME bubble status up to UI + return value + + @cherrypy.expose + def rbd(self, pool_name): + template = env.get_template("rbd.html") + + toplevel_data = self._toplevel_data() + + images = self._rbd(pool_name) + content_data = { + "images": images, + "pool_name": pool_name + } + + return template.render( + ceph_version=global_instance().version, + toplevel_data=json.dumps(toplevel_data, indent=2), + content_data=json.dumps(content_data, indent=2) + ) + + @cherrypy.expose + @cherrypy.tools.json_out() + def rbd_data(self, pool_name): + return self._rbd(pool_name) + + @cherrypy.expose + def health(self): + template = env.get_template("health.html") + return template.render( + ceph_version=global_instance().version, + toplevel_data=json.dumps(self._toplevel_data(), indent=2), + content_data=json.dumps(self._health(), indent=2) + ) + + @cherrypy.expose + def servers(self): + template = env.get_template("servers.html") + return template.render( + ceph_version=global_instance().version, + toplevel_data=json.dumps(self._toplevel_data(), indent=2), + content_data=json.dumps(self._servers(), indent=2) + ) + + def _servers(self): + servers = global_instance().list_servers() + return { + 'servers': global_instance().list_servers() + } + + @cherrypy.expose + @cherrypy.tools.json_out() + def servers_data(self): + return self._servers() + + def _health(self): + # Fuse osdmap with pg_summary to get description of pools + # including their PG states + osd_map = global_instance().get_sync_object(OsdMap).data + pg_summary = global_instance().get_sync_object(PgSummary).data + pools = [] + + if len(global_instance().pool_stats) == 0: + global_instance().update_pool_stats() + + for pool in osd_map['pools']: + pool['pg_status'] = pg_summary['by_pool'][pool['pool'].__str__()] + stats = global_instance().pool_stats[pool['pool']] + s = {} + + def get_rate(series): + if len(series) >= 2: + return (float(series[0][1]) - float(series[1][1])) / (float(series[0][0]) - float(series[1][0])) + else: + return 0 + + for stat_name, stat_series in stats.items(): + s[stat_name] = { + 'latest': stat_series[0][1], + 'rate': get_rate(stat_series), + 'series': [i for i in stat_series] + } + pool['stats'] = s + pools.append(pool) + + # Not needed, skip the effort of transmitting this + # to UI + del osd_map['pg_temp'] + + return { + "health": global_instance().get_sync_object(Health).data, + "mon_status": global_instance().get_sync_object( + MonStatus).data, + "osd_map": osd_map, + "clog": list(global_instance().log_buffer), + "audit_log": list(global_instance().audit_buffer), + "pools": pools + } + + @cherrypy.expose + @cherrypy.tools.json_out() + def health_data(self): + return self._health() + + @cherrypy.expose + def index(self): + return self.health() + + @cherrypy.expose + @cherrypy.tools.json_out() + def toplevel_data(self): + return self._toplevel_data() + + def _get_mds_names(self, filesystem_id=None): + names = [] + + fsmap = global_instance().get("fs_map") + for fs in fsmap['filesystems']: + if filesystem_id is not None and fs['id'] != filesystem_id: + continue + names.extend([info['name'] for _, info in fs['mdsmap']['info'].items()]) + + if filesystem_id is None: + names.extend(info['name'] for info in fsmap['standbys']) + + return names + + @cherrypy.expose + @cherrypy.tools.json_out() + def mds_counters(self, fs_id): + """ + Result format: map of daemon name to map of counter to list of datapoints + """ + + # Opinionated list of interesting performance counters for the GUI -- + # if you need something else just add it. See how simple life is + # when you don't have to write general purpose APIs? + counters = [ + "mds_server.handle_client_request", + "mds_log.ev", + "mds_cache.num_strays", + "mds.exported", + "mds.exported_inodes", + "mds.imported", + "mds.imported_inodes", + "mds.inodes", + "mds.caps", + "mds.subtrees" + ] + + result = {} + mds_names = self._get_mds_names(int(fs_id)) + + for mds_name in mds_names: + result[mds_name] = {} + for counter in counters: + data = global_instance().get_counter("mds", mds_name, counter) + if data is not None: + result[mds_name][counter] = data[counter] + else: + result[mds_name][counter] = [] + + return dict(result) + + server_addr = self.get_localized_config('server_addr') + server_port = self.get_localized_config('server_port') or '7000' + if server_addr is None: + raise RuntimeError('no server_addr configured; try "ceph config-key put mgr/dashboard/server_addr "') + log.info("server_addr: %s server_port: %s" % (server_addr, server_port)) + cherrypy.config.update({ + 'server.socket_host': server_addr, + 'server.socket_port': int(server_port), + 'engine.autoreload.on': False + }) + + static_dir = os.path.join(current_dir, 'static') + conf = { + "/static": { + "tools.staticdir.on": True, + 'tools.staticdir.dir': static_dir + } + } + log.info("Serving static from {0}".format(static_dir)) + cherrypy.tree.mount(Root(), "/", conf) + + log.info("Starting engine...") + cherrypy.engine.start() + log.info("Waiting for engine...") + cherrypy.engine.block() + log.info("Engine done.") diff --git a/ceph/src/pybind/mgr/dashboard/osd_perf.html b/ceph/src/pybind/mgr/dashboard/osd_perf.html new file mode 100644 index 000000000..8c92414cf --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/osd_perf.html @@ -0,0 +1,188 @@ +{% extends "base.html" %} + +{% block content %} + + + + +
+

+ osd.{osd.osd} +

+
+ +
+ + + + + +
+

Writes

+ +
+
  +

Reads

+ +
+
+ +
+
+

Attributes (OSD map)

+
+
+ + + + + + + + + + + + + +
KeyValue
{item.key}{item.value}
+
+
+ +
+
+

Metadata

+
+
+ + + + + + + + + + + + + +
KeyValue
{meta_item.key}{meta_item.value}
+
+
+ + +
+ + +{% endblock %} diff --git a/ceph/src/pybind/mgr/dashboard/rbd.html b/ceph/src/pybind/mgr/dashboard/rbd.html new file mode 100644 index 000000000..3e0e69945 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/rbd.html @@ -0,0 +1,64 @@ +{% extends "base.html" %} + +{% block content %} + + + + +
+

+ RBD +

+
+ +
+
+
+

Images

+
+
+ + + + + + + + + + + + + + + + + + + +
NameSizeObjectsObject sizeParent
{image.name}{image.size | dimless}{image.num_objs | dimless}{image.obj_size | dimless}{image.parent}
+
+
+ + +
+ + +{% endblock %} \ No newline at end of file diff --git a/ceph/src/pybind/mgr/dashboard/rbd_ls.py b/ceph/src/pybind/mgr/dashboard/rbd_ls.py new file mode 100644 index 000000000..510a77778 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/rbd_ls.py @@ -0,0 +1,38 @@ + +import rados +import rbd +from remote_view_cache import RemoteViewCache + + +class RbdLs(RemoteViewCache): + def __init__(self, module_inst, pool): + super(RbdLs, self).__init__(module_inst) + + self.pool = pool + + self.ioctx = None + self.rbd = None + + def _init(self): + from mgr_module import ceph_state + ctx_capsule = ceph_state.get_context() + + self.log.info("Constructing Rados") + cluster = rados.Rados(context=ctx_capsule) + cluster.connect() + self.log.info("Constructing IOCtx") + self.ioctx = cluster.open_ioctx("rbd") + + self.log.info("Constructing RBD") + self.rbd = rbd.RBD() + + def _get(self): + self.log.debug("rbd.list") + names = self.rbd.list(self.ioctx) + result = [] + for name in names: + i = rbd.Image(self.ioctx, name) + stat = i.stat() + stat['name'] = name + result.append(stat) + return result diff --git a/ceph/src/pybind/mgr/dashboard/remote_view_cache.py b/ceph/src/pybind/mgr/dashboard/remote_view_cache.py new file mode 100644 index 000000000..294975d76 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/remote_view_cache.py @@ -0,0 +1,135 @@ + + +from threading import Thread, Event, Lock +import datetime +import time + + +class GetterThread(Thread): + def __init__(self, view): + super(GetterThread, self).__init__() + self._view = view + self.event = Event() + + def run(self): + try: + t0 = time.time() + val = self._view._get() + t1 = time.time() + except: + self._view.log.exception("Error while calling _get:") + # TODO: separate channel for passing back error + self._view.value = None + self._view.value_when = None + self._view.getter_thread = None + else: + with self._view.lock: + self._view.latency = t1 - t0 + self._view.value = val + self._view.value_when = datetime.datetime.now() + self._view.getter_thread = None + + self.event.set() + + +class RemoteViewCache(object): + """ + A cached view of something we have to fetch remotely, e.g. the output + of a 'tell' command to a daemon, or something we read from RADOS like + and rbd image's status. + + There are two reasons this wrapper exists: + * To reduce load on remote entities when we frequently fetch something + (i.e. 10 page loads in one second should not translate into 10 separate + remote fetches) + * To handle the blocking nature of some remote operations + (i.e. if RADOS isn't responding, we need a predictable way to either + return no data, or return stale data, when something from RADOS is + requested) + + Note that relying on timeouts in underlying libraries isn't wise here: + if something is really slow, we would like to return a 'stale' state + to a GUI quickly, but we should let our underlying request to the cluster + run to completion so that we get some data even if it's slow, and so that + a polling caller doesn't end up firing off a large number of requests to + the cluster because each one timed out. + + Subclasses may override _init and must override _get + """ + + def __init__(self, module_inst): + self.initialized = False + + self.log = module_inst.log + + self.getter_thread = None + + # Consider data within 1s old to be sufficiently fresh + self.stale_period = 1.0 + + # Return stale data if + self.timeout = 5 + + self.event = Event() + self.value_when = None + self.value = None + self.latency = 0 + self.lock = Lock() + + self._module = module_inst + + def init(self): + self._init() + self.initialized = True + + VALUE_OK = 0 + VALUE_STALE = 1 + VALUE_NONE = 2 + + def get(self): + """ + If data less than `stale_period` old is available, return it + immediately. + If an attempt to fetch data does not complete within `timeout`, then + return the most recent data available, with a status to indicate that + it is stale. + + Initialization does not count towards the timeout, so the first call + on one of these objects during the process lifetime may be slower + than subsequent calls. + + :return: 2-tuple of value status code, value + """ + with self.lock: + if not self.initialized: + self.init() + + now = datetime.datetime.now() + if self.value_when and now - self.value_when < datetime.timedelta( + seconds=self.stale_period): + return self.VALUE_OK, self.value + + if self.getter_thread is None: + self.getter_thread = GetterThread(self) + self.getter_thread.start() + + ev = self.getter_thread.event + + success = ev.wait(timeout=self.timeout) + + with self.lock: + if success: + # We fetched the data within the timeout + return self.VALUE_OK, self.value + elif self.value_when is not None: + # We have some data, but it doesn't meet freshness requirements + return self.VALUE_STALE, self.value + else: + # We have no data, not even stale data + return self.VALUE_NONE, None + + def _init(self): + pass + + def _get(self): + raise NotImplementedError() diff --git a/ceph/src/pybind/mgr/dashboard/servers.html b/ceph/src/pybind/mgr/dashboard/servers.html new file mode 100644 index 000000000..301bca24b --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/servers.html @@ -0,0 +1,84 @@ +{% extends "base.html" %} + +{% block content %} + + + + + +
+

+ Servers +

+
+ + +
+
+
+ + + + + + + + + + + +
+ Hostname + + Services + + Version +
+ {server.hostname} + + {server.services | service_list} + + {server.ceph_version | short_version} +
+
+
+
+ +{% endblock %} diff --git a/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/.jshintrc b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/.jshintrc new file mode 100644 index 000000000..f91c8ee5c --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/.jshintrc @@ -0,0 +1,17 @@ +{ + "asi" : true, + "browser" : true, + "eqeqeq" : false, + "eqnull" : true, + "es3" : true, + "expr" : true, + "jquery" : true, + "latedef" : "nofunc", + "laxbreak" : true, + "nonbsp" : true, + "strict" : true, + "undef" : true, + "unused" : true, + // External variabls and plugins + "predef": [ "AdminLTEOptions", "FastClick", "moment", "Morris", "Chart" ] +} diff --git a/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/Gruntfile.js b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/Gruntfile.js new file mode 100644 index 000000000..05c94287c --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/Gruntfile.js @@ -0,0 +1,172 @@ +// AdminLTE Gruntfile +module.exports = function (grunt) { + + 'use strict'; + + grunt.initConfig({ + watch: { + // If any .less file changes in directory "build/less/" run the "less"-task. + files: ["build/less/*.less", "build/less/skins/*.less", "dist/js/app.js"], + tasks: ["less", "uglify"] + }, + // "less"-task configuration + // This task will compile all less files upon saving to create both AdminLTE.css and AdminLTE.min.css + less: { + // Development not compressed + development: { + options: { + // Whether to compress or not + compress: false + }, + files: { + // compilation.css : source.less + "dist/css/AdminLTE.css": "build/less/AdminLTE.less", + //Non minified skin files + "dist/css/skins/skin-blue.css": "build/less/skins/skin-blue.less", + "dist/css/skins/skin-black.css": "build/less/skins/skin-black.less", + "dist/css/skins/skin-yellow.css": "build/less/skins/skin-yellow.less", + "dist/css/skins/skin-green.css": "build/less/skins/skin-green.less", + "dist/css/skins/skin-red.css": "build/less/skins/skin-red.less", + "dist/css/skins/skin-purple.css": "build/less/skins/skin-purple.less", + "dist/css/skins/skin-blue-light.css": "build/less/skins/skin-blue-light.less", + "dist/css/skins/skin-black-light.css": "build/less/skins/skin-black-light.less", + "dist/css/skins/skin-yellow-light.css": "build/less/skins/skin-yellow-light.less", + "dist/css/skins/skin-green-light.css": "build/less/skins/skin-green-light.less", + "dist/css/skins/skin-red-light.css": "build/less/skins/skin-red-light.less", + "dist/css/skins/skin-purple-light.css": "build/less/skins/skin-purple-light.less", + "dist/css/skins/_all-skins.css": "build/less/skins/_all-skins.less" + } + }, + // Production compresses version + production: { + options: { + // Whether to compress or not + compress: true + }, + files: { + // compilation.css : source.less + "dist/css/AdminLTE.min.css": "build/less/AdminLTE.less", + // Skins minified + "dist/css/skins/skin-blue.min.css": "build/less/skins/skin-blue.less", + "dist/css/skins/skin-black.min.css": "build/less/skins/skin-black.less", + "dist/css/skins/skin-yellow.min.css": "build/less/skins/skin-yellow.less", + "dist/css/skins/skin-green.min.css": "build/less/skins/skin-green.less", + "dist/css/skins/skin-red.min.css": "build/less/skins/skin-red.less", + "dist/css/skins/skin-purple.min.css": "build/less/skins/skin-purple.less", + "dist/css/skins/skin-blue-light.min.css": "build/less/skins/skin-blue-light.less", + "dist/css/skins/skin-black-light.min.css": "build/less/skins/skin-black-light.less", + "dist/css/skins/skin-yellow-light.min.css": "build/less/skins/skin-yellow-light.less", + "dist/css/skins/skin-green-light.min.css": "build/less/skins/skin-green-light.less", + "dist/css/skins/skin-red-light.min.css": "build/less/skins/skin-red-light.less", + "dist/css/skins/skin-purple-light.min.css": "build/less/skins/skin-purple-light.less", + "dist/css/skins/_all-skins.min.css": "build/less/skins/_all-skins.less" + } + } + }, + // Uglify task info. Compress the js files. + uglify: { + options: { + mangle: true, + preserveComments: 'some' + }, + my_target: { + files: { + 'dist/js/app.min.js': ['dist/js/app.js'] + } + } + }, + // Build the documentation files + includes: { + build: { + src: ['*.html'], // Source files + dest: 'documentation/', // Destination directory + flatten: true, + cwd: 'documentation/build', + options: { + silent: true, + includePath: 'documentation/build/include' + } + } + }, + + // Optimize images + image: { + dynamic: { + files: [{ + expand: true, + cwd: 'build/img/', + src: ['**/*.{png,jpg,gif,svg,jpeg}'], + dest: 'dist/img/' + }] + } + }, + + // Validate JS code + jshint: { + options: { + jshintrc: '.jshintrc' + }, + core: { + src: 'dist/js/app.js' + }, + demo: { + src: 'dist/js/demo.js' + }, + pages: { + src: 'dist/js/pages/*.js' + } + }, + + // Validate CSS files + csslint: { + options: { + csslintrc: 'build/less/.csslintrc' + }, + dist: [ + 'dist/css/AdminLTE.css', + ] + }, + + // Validate Bootstrap HTML + bootlint: { + options: { + relaxerror: ['W005'] + }, + files: ['pages/**/*.html', '*.html'] + }, + + // Delete images in build directory + // After compressing the images in the build/img dir, there is no need + // for them + clean: { + build: ["build/img/*"] + } + }); + + // Load all grunt tasks + + // LESS Compiler + grunt.loadNpmTasks('grunt-contrib-less'); + // Watch File Changes + grunt.loadNpmTasks('grunt-contrib-watch'); + // Compress JS Files + grunt.loadNpmTasks('grunt-contrib-uglify'); + // Include Files Within HTML + grunt.loadNpmTasks('grunt-includes'); + // Optimize images + grunt.loadNpmTasks('grunt-image'); + // Validate JS code + grunt.loadNpmTasks('grunt-contrib-jshint'); + // Delete not needed files + grunt.loadNpmTasks('grunt-contrib-clean'); + // Lint CSS + grunt.loadNpmTasks('grunt-contrib-csslint'); + // Lint Bootstrap + grunt.loadNpmTasks('grunt-bootlint'); + + // Linting task + grunt.registerTask('lint', ['jshint', 'csslint', 'bootlint']); + + // The default task (running "grunt" in console) is "watch" + grunt.registerTask('default', ['watch']); +}; diff --git a/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/LICENSE b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/LICENSE new file mode 100644 index 000000000..4c31b5630 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016 Abdullah Almsaeed + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/README.md b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/README.md new file mode 100644 index 000000000..20c588142 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/README.md @@ -0,0 +1,123 @@ +Introduction +============ + +![Bower version](https://img.shields.io/bower/v/adminlte.svg) +[![npm version](https://img.shields.io/npm/v/admin-lte.svg)](https://www.npmjs.com/package/admin-lte) +[![Packagist](https://img.shields.io/packagist/v/almasaeed2010/adminlte.svg)](https://packagist.org/packages/almasaeed2010/adminlte) + +**AdminLTE** -- is a fully responsive admin template. Based on **[Bootstrap 3](https://github.com/twbs/bootstrap)** framework. Highly customizable and easy to use. Fits many screen resolutions from small mobile devices to large desktops. Check out the live preview now and see for yourself. + +**Download & Preview on [Almsaeed Studio](https://almsaeedstudio.com)** + +Looking for Premium Templates? +------------------------------ +**Almsaeed studio just opened a new premium templates page. Hand picked to insure the best quality and the most affordable prices. Visit https://almsaeedstudio.com/premium for more information.** + + +!["AdminLTE Presentation"] (https://almsaeedstudio.com/AdminLTE2.png "AdminLTE Presentation") + +**AdminLTE** has been carefully coded with clear comments in all of its JS, LESS and HTML files. LESS has been used to increase code customizability. + +Installation +------------ +There are multiple ways to install AdminLTE. + +####Download: + +Download from Github or [visit Almsaeed Studio](https://almsaeedstudio.com) and download the latest release. + +####Using The Command Line: + +**Github** + +- Fork the repository ([here is the guide](https://help.github.com/articles/fork-a-repo/)). +- Clone to your machine +``` +git clone https://github.com/YOUR_USERNAME/AdminLTE.git +``` + +**Bower** + +``` +bower install admin-lte +``` + +**npm** + +``` +npm install --save admin-lte +``` + +**Composer** + +``` +composer require "almasaeed2010/adminlte=~2.0" +``` + +Documentation +------------- +Visit the [online documentation](https://almsaeedstudio.com/themes/AdminLTE/documentation/index.html) for the most +updated guide. Information will be added on a weekly basis. + +Browser Support +--------------- +- IE 9+ +- Firefox (latest) +- Chrome (latest) +- Safari (latest) +- Opera (latest) + +Contribution +------------ +Contribution are always **welcome and recommended**! Here is how: + +- Fork the repository ([here is the guide](https://help.github.com/articles/fork-a-repo/)). +- Clone to your machine ```git clone https://github.com/YOUR_USERNAME/AdminLTE.git``` +- Make your changes +- Create a pull request + +#### Contribution Requirements: + +- When you contribute, you agree to give a non-exclusive license to Almsaeed Studio to use that contribution in any context as we (Almsaeed Studio) see appropriate. +- If you use content provided by another party, it must be appropriately licensed using an [open source](http://opensource.org/licenses) license. +- Contributions are only accepted through Github pull requests. +- Finally, contributed code must work in all supported browsers (see above for browser support). + +License +------- +AdminLTE is an open source project by [Almsaeed Studio](https://almsaeedstudio.com) that is licensed under [MIT](http://opensource.org/licenses/MIT). Almsaeed Studio +reserves the right to change the license of future releases. + +Todo List +--------- +- ~~Light sidebar colors~~ (Done v2.1.0) +- ~~Right sidebar~~ (Done v2.1.0) +- ~~Minified main-sidebar~~ (Done v2.1.0) +- Right to left support +- ~~Custom pace style~~ (Done v2.3.1) + +Legacy Releases +---------------- +AdminLTE 1.x can be easily upgraded to 2.x using [this guide](https://almsaeedstudio.com/themes/AdminLTE/documentation/index.html#upgrade), but if you intend to keep using AdminLTE 1.x, you can download the latest release from the [releases](https://github.com/almasaeed2010/AdminLTE/releases) section above. + +Change log +---------- +**For the most recent change log, visit the [releases page](https://github.com/almasaeed2010/AdminLTE/releases) or the [changelog file](https://github.com/almasaeed2010/AdminLTE/blob/master/changelog.md).** We will add a detailed release notes to each new release. + +Image Credits +------------- +[Pixeden](http://www.pixeden.com/psd-web-elements/flat-responsive-showcase-psd) + +[Graphicsfuel](http://www.graphicsfuel.com/2013/02/13-high-resolution-blur-backgrounds/) + +[Pickaface](http://pickaface.net/) + +[Unsplash](https://unsplash.com/) + +[Uifaces](http://uifaces.com/) + +Donations +--------- +Donations are **greatly appreciated!** + +[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif "AdminLTE Presentation")](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=629XCUSXBHCBC "Donate") diff --git a/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css new file mode 100755 index 000000000..42c79d6e4 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css @@ -0,0 +1,6760 @@ +/*! + * Bootstrap v3.3.6 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 46px; + line-height: 46px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + padding-right: 15px; + padding-left: 15px; + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + filter: alpha(opacity=0); + opacity: 0; + + line-break: auto; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + + line-break: auto; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + background-color: rgba(0, 0, 0, 0); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + margin-top: -10px; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css.map b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css.map new file mode 100755 index 000000000..09f8cda78 --- /dev/null +++ b/ceph/src/pybind/mgr/dashboard/static/AdminLTE-2.3.7/bootstrap/css/bootstrap.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACG5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDDD;ACQD;EACE,UAAA;CDND;ACmBD;;;;;;;;;;;;;EAaE,eAAA;CDjBD;ACyBD;;;;EAIE,sBAAA;EACA,yBAAA;CDvBD;AC+BD;EACE,cAAA;EACA,UAAA;CD7BD;ACqCD;;EAEE,cAAA;CDnCD;AC6CD;EACE,8BAAA;CD3CD;ACmDD;;EAEE,WAAA;CDjDD;AC2DD;EACE,0BAAA;CDzDD;ACgED;;EAEE,kBAAA;CD9DD;ACqED;EACE,mBAAA;CDnED;AC2ED;EACE,eAAA;EACA,iBAAA;CDzED;ACgFD;EACE,iBAAA;EACA,YAAA;CD9ED;ACqFD;EACE,eAAA;CDnFD;AC0FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CDxFD;AC2FD;EACE,YAAA;CDzFD;AC4FD;EACE,gBAAA;CD1FD;ACoGD;EACE,UAAA;CDlGD;ACyGD;EACE,iBAAA;CDvGD;ACiHD;EACE,iBAAA;CD/GD;ACsHD;EACE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,UAAA;CDpHD;AC2HD;EACE,eAAA;CDzHD;ACgID;;;;EAIE,kCAAA;EACA,eAAA;CD9HD;ACgJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CD9ID;ACqJD;EACE,kBAAA;CDnJD;AC6JD;;EAEE,qBAAA;CD3JD;ACsKD;;;;EAIE,2BAAA;EACA,gBAAA;CDpKD;AC2KD;;EAEE,gBAAA;CDzKD;ACgLD;;EAEE,UAAA;EACA,WAAA;CD9KD;ACsLD;EACE,oBAAA;CDpLD;AC+LD;;EAEE,+BAAA;KAAA,4BAAA;UAAA,uBAAA;EACA,WAAA;CD7LD;ACsMD;;EAEE,aAAA;CDpMD;AC4MD;EACE,8BAAA;EACA,gCAAA;KAAA,6BAAA;UAAA,wBAAA;CD1MD;ACmND;;EAEE,yBAAA;CDjND;ACwND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDtND;AC8ND;EACE,UAAA;EACA,WAAA;CD5ND;ACmOD;EACE,eAAA;CDjOD;ACyOD;EACE,kBAAA;CDvOD;ACiPD;EACE,0BAAA;EACA,kBAAA;CD/OD;ACkPD;;EAEE,WAAA;CDhPD;AACD,qFAAqF;AElFrF;EA7FI;;;IAGI,mCAAA;IACA,uBAAA;IACA,oCAAA;YAAA,4BAAA;IACA,6BAAA;GFkLL;EE/KC;;IAEI,2BAAA;GFiLL;EE9KC;IACI,6BAAA;GFgLL;EE7KC;IACI,8BAAA;GF+KL;EE1KC;;IAEI,YAAA;GF4KL;EEzKC;;IAEI,uBAAA;IACA,yBAAA;GF2KL;EExKC;IACI,4BAAA;GF0KL;EEvKC;;IAEI,yBAAA;GFyKL;EEtKC;IACI,2BAAA;GFwKL;EErKC;;;IAGI,WAAA;IACA,UAAA;GFuKL;EEpKC;;IAEI,wBAAA;GFsKL;EEhKC;IACI,cAAA;GFkKL;EEhKC;;IAGQ,kCAAA;GFiKT;EE9JC;IACI,uBAAA;GFgKL;EE7JC;IACI,qCAAA;GF+JL;EEhKC;;IAKQ,kCAAA;GF+JT;EE5JC;;IAGQ,kCAAA;GF6JT;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,oBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,iBAAA;CH8O9C;AG7OmC;EAAW,iBAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;EAAW,iBAAA;CH4tB9C;AG3tBmC;EAAW,iBAAA;CH8tB9C;AG7tBmC;EAAW,iBAAA;CHguB9C;AG/tBmC;EAAW,iBAAA;CHkuB9C;AGjuBmC;EAAW,iBAAA;CHouB9C;AGnuBmC;EAAW,iBAAA;CHsuB9C;AGruBmC;EAAW,iBAAA;CHwuB9C;AGvuBmC;EAAW,iBAAA;CH0uB9C;AGzuBmC;EAAW,iBAAA;CH4uB9C;AG3uBmC;EAAW,iBAAA;CH8uB9C;AG7uBmC;EAAW,iBAAA;CHgvB9C;AIthCD;ECgEE,+BAAA;EACG,4BAAA;EACK,uBAAA;CLy9BT;AIxhCD;;EC6DE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL+9BT;AIthCD;EACE,gBAAA;EACA,8CAAA;CJwhCD;AIrhCD;EACE,4DAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;CJuhCD;AInhCD;;;;EAIE,qBAAA;EACA,mBAAA;EACA,qBAAA;CJqhCD;AI/gCD;EACE,eAAA;EACA,sBAAA;CJihCD;AI/gCC;;EAEE,eAAA;EACA,2BAAA;CJihCH;AI9gCC;EErDA,qBAAA;EAEA,2CAAA;EACA,qBAAA;CNqkCD;AIxgCD;EACE,UAAA;CJ0gCD;AIpgCD;EACE,uBAAA;CJsgCD;AIlgCD;;;;;EGvEE,eAAA;EACA,gBAAA;EACA,aAAA;CPglCD;AItgCD;EACE,mBAAA;CJwgCD;AIlgCD;EACE,aAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EC6FA,yCAAA;EACK,oCAAA;EACG,iCAAA;EEvLR,sBAAA;EACA,gBAAA;EACA,aAAA;CPgmCD;AIlgCD;EACE,mBAAA;CJogCD;AI9/BD;EACE,iBAAA;EACA,oBAAA;EACA,UAAA;EACA,8BAAA;CJggCD;AIx/BD;EACE,mBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,iBAAA;EACA,uBAAA;EACA,UAAA;CJ0/BD;AIl/BC;;EAEE,iBAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;EACA,kBAAA;EACA,WAAA;CJo/BH;AIz+BD;EACE,gBAAA;CJ2+BD;AQloCD;;;;;;;;;;;;EAEE,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;CR8oCD;AQnpCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,oBAAA;EACA,eAAA;EACA,eAAA;CRoqCH;AQhqCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRqqCD;AQzqCD;;;;;;;;;;;;EAQI,eAAA;CR+qCH;AQ5qCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRirCD;AQrrCD;;;;;;;;;;;;EAQI,eAAA;CR2rCH;AQvrCD;;EAAU,gBAAA;CR2rCT;AQ1rCD;;EAAU,gBAAA;CR8rCT;AQ7rCD;;EAAU,gBAAA;CRisCT;AQhsCD;;EAAU,gBAAA;CRosCT;AQnsCD;;EAAU,gBAAA;CRusCT;AQtsCD;;EAAU,gBAAA;CR0sCT;AQpsCD;EACE,iBAAA;CRssCD;AQnsCD;EACE,oBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;CRqsCD;AQhsCD;EAwOA;IA1OI,gBAAA;GRssCD;CACF;AQ9rCD;;EAEE,eAAA;CRgsCD;AQ7rCD;;EAEE,0BAAA;EACA,cAAA;CR+rCD;AQ3rCD;EAAuB,iBAAA;CR8rCtB;AQ7rCD;EAAuB,kBAAA;CRgsCtB;AQ/rCD;EAAuB,mBAAA;CRksCtB;AQjsCD;EAAuB,oBAAA;CRosCtB;AQnsCD;EAAuB,oBAAA;CRssCtB;AQnsCD;EAAuB,0BAAA;CRssCtB;AQrsCD;EAAuB,0BAAA;CRwsCtB;AQvsCD;EAAuB,2BAAA;CR0sCtB;AQvsCD;EACE,eAAA;CRysCD;AQvsCD;ECrGE,eAAA;CT+yCD;AS9yCC;;EAEE,eAAA;CTgzCH;AQ3sCD;ECxGE,eAAA;CTszCD;ASrzCC;;EAEE,eAAA;CTuzCH;AQ/sCD;EC3GE,eAAA;CT6zCD;AS5zCC;;EAEE,eAAA;CT8zCH;AQntCD;EC9GE,eAAA;CTo0CD;ASn0CC;;EAEE,eAAA;CTq0CH;AQvtCD;ECjHE,eAAA;CT20CD;AS10CC;;EAEE,eAAA;CT40CH;AQvtCD;EAGE,YAAA;EE3HA,0BAAA;CVm1CD;AUl1CC;;EAEE,0BAAA;CVo1CH;AQztCD;EE9HE,0BAAA;CV01CD;AUz1CC;;EAEE,0BAAA;CV21CH;AQ7tCD;EEjIE,0BAAA;CVi2CD;AUh2CC;;EAEE,0BAAA;CVk2CH;AQjuCD;EEpIE,0BAAA;CVw2CD;AUv2CC;;EAEE,0BAAA;CVy2CH;AQruCD;EEvIE,0BAAA;CV+2CD;AU92CC;;EAEE,0BAAA;CVg3CH;AQpuCD;EACE,oBAAA;EACA,oBAAA;EACA,iCAAA;CRsuCD;AQ9tCD;;EAEE,cAAA;EACA,oBAAA;CRguCD;AQnuCD;;;;EAMI,iBAAA;CRmuCH;AQ5tCD;EACE,gBAAA;EACA,iBAAA;CR8tCD;AQ1tCD;EALE,gBAAA;EACA,iBAAA;EAMA,kBAAA;CR6tCD;AQ/tCD;EAKI,sBAAA;EACA,kBAAA;EACA,mBAAA;CR6tCH;AQxtCD;EACE,cAAA;EACA,oBAAA;CR0tCD;AQxtCD;;EAEE,wBAAA;CR0tCD;AQxtCD;EACE,kBAAA;CR0tCD;AQxtCD;EACE,eAAA;CR0tCD;AQjsCD;EA6EA;IAvFM,YAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IGtNJ,iBAAA;IACA,wBAAA;IACA,oBAAA;GXs6CC;EQ9nCH;IAhFM,mBAAA;GRitCH;CACF;AQxsCD;;EAGE,aAAA;EACA,kCAAA;CRysCD;AQvsCD;EACE,eAAA;EA9IqB,0BAAA;CRw1CtB;AQrsCD;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,+BAAA;CRusCD;AQlsCG;;;EACE,iBAAA;CRssCL;AQhtCD;;;EAmBI,eAAA;EACA,eAAA;EACA,wBAAA;EACA,eAAA;CRksCH;AQhsCG;;;EACE,uBAAA;CRosCL;AQ5rCD;;EAEE,oBAAA;EACA,gBAAA;EACA,gCAAA;EACA,eAAA;EACA,kBAAA;CR8rCD;AQxrCG;;;;;;EAAW,YAAA;CRgsCd;AQ/rCG;;;;;;EACE,uBAAA;CRssCL;AQhsCD;EACE,oBAAA;EACA,mBAAA;EACA,wBAAA;CRksCD;AYx+CD;;;;EAIE,+DAAA;CZ0+CD;AYt+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CZw+CD;AYp+CD;EACE,iBAAA;EACA,eAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;EACA,uDAAA;UAAA,+CAAA;CZs+CD;AY5+CD;EASI,WAAA;EACA,gBAAA;EACA,kBAAA;EACA,yBAAA;UAAA,iBAAA;CZs+CH;AYj+CD;EACE,eAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,sBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;CZm+CD;AY9+CD;EAeI,WAAA;EACA,mBAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,iBAAA;CZk+CH;AY79CD;EACE,kBAAA;EACA,mBAAA;CZ+9CD;AazhDD;ECHE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;Cd+hDD;AazhDC;EAqEF;IAvEI,aAAA;Gb+hDD;CACF;Aa3hDC;EAkEF;IApEI,aAAA;GbiiDD;CACF;Aa7hDD;EA+DA;IAjEI,cAAA;GbmiDD;CACF;Aa1hDD;ECvBE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;CdojDD;AavhDD;ECvBE,mBAAA;EACA,oBAAA;CdijDD;AejjDG;EACE,mBAAA;EAEA,gBAAA;EAEA,mBAAA;EACA,oBAAA;CfijDL;AejiDG;EACE,YAAA;CfmiDL;Ae5hDC;EACE,YAAA;Cf8hDH;Ae/hDC;EACE,oBAAA;CfiiDH;AeliDC;EACE,oBAAA;CfoiDH;AeriDC;EACE,WAAA;CfuiDH;AexiDC;EACE,oBAAA;Cf0iDH;Ae3iDC;EACE,oBAAA;Cf6iDH;Ae9iDC;EACE,WAAA;CfgjDH;AejjDC;EACE,oBAAA;CfmjDH;AepjDC;EACE,oBAAA;CfsjDH;AevjDC;EACE,WAAA;CfyjDH;Ae1jDC;EACE,oBAAA;Cf4jDH;Ae7jDC;EACE,mBAAA;Cf+jDH;AejjDC;EACE,YAAA;CfmjDH;AepjDC;EACE,oBAAA;CfsjDH;AevjDC;EACE,oBAAA;CfyjDH;Ae1jDC;EACE,WAAA;Cf4jDH;Ae7jDC;EACE,oBAAA;Cf+jDH;AehkDC;EACE,oBAAA;CfkkDH;AenkDC;EACE,WAAA;CfqkDH;AetkDC;EACE,oBAAA;CfwkDH;AezkDC;EACE,oBAAA;Cf2kDH;Ae5kDC;EACE,WAAA;Cf8kDH;Ae/kDC;EACE,oBAAA;CfilDH;AellDC;EACE,mBAAA;CfolDH;AehlDC;EACE,YAAA;CfklDH;AelmDC;EACE,WAAA;CfomDH;AermDC;EACE,mBAAA;CfumDH;AexmDC;EACE,mBAAA;Cf0mDH;Ae3mDC;EACE,UAAA;Cf6mDH;Ae9mDC;EACE,mBAAA;CfgnDH;AejnDC;EACE,mBAAA;CfmnDH;AepnDC;EACE,UAAA;CfsnDH;AevnDC;EACE,mBAAA;CfynDH;Ae1nDC;EACE,mBAAA;Cf4nDH;Ae7nDC;EACE,UAAA;Cf+nDH;AehoDC;EACE,mBAAA;CfkoDH;AenoDC;EACE,kBAAA;CfqoDH;AejoDC;EACE,WAAA;CfmoDH;AernDC;EACE,kBAAA;CfunDH;AexnDC;EACE,0BAAA;Cf0nDH;Ae3nDC;EACE,0BAAA;Cf6nDH;Ae9nDC;EACE,iBAAA;CfgoDH;AejoDC;EACE,0BAAA;CfmoDH;AepoDC;EACE,0BAAA;CfsoDH;AevoDC;EACE,iBAAA;CfyoDH;Ae1oDC;EACE,0BAAA;Cf4oDH;Ae7oDC;EACE,0BAAA;Cf+oDH;AehpDC;EACE,iBAAA;CfkpDH;AenpDC;EACE,0BAAA;CfqpDH;AetpDC;EACE,yBAAA;CfwpDH;AezpDC;EACE,gBAAA;Cf2pDH;Aa3pDD;EElCI;IACE,YAAA;GfgsDH;EezrDD;IACE,YAAA;Gf2rDD;Ee5rDD;IACE,oBAAA;Gf8rDD;Ee/rDD;IACE,oBAAA;GfisDD;EelsDD;IACE,WAAA;GfosDD;EersDD;IACE,oBAAA;GfusDD;EexsDD;IACE,oBAAA;Gf0sDD;Ee3sDD;IACE,WAAA;Gf6sDD;Ee9sDD;IACE,oBAAA;GfgtDD;EejtDD;IACE,oBAAA;GfmtDD;EeptDD;IACE,WAAA;GfstDD;EevtDD;IACE,oBAAA;GfytDD;Ee1tDD;IACE,mBAAA;Gf4tDD;Ee9sDD;IACE,YAAA;GfgtDD;EejtDD;IACE,oBAAA;GfmtDD;EeptDD;IACE,oBAAA;GfstDD;EevtDD;IACE,WAAA;GfytDD;Ee1tDD;IACE,oBAAA;Gf4tDD;Ee7tDD;IACE,oBAAA;Gf+tDD;EehuDD;IACE,WAAA;GfkuDD;EenuDD;IACE,oBAAA;GfquDD;EetuDD;IACE,oBAAA;GfwuDD;EezuDD;IACE,WAAA;Gf2uDD;Ee5uDD;IACE,oBAAA;Gf8uDD;Ee/uDD;IACE,mBAAA;GfivDD;Ee7uDD;IACE,YAAA;Gf+uDD;Ee/vDD;IACE,WAAA;GfiwDD;EelwDD;IACE,mBAAA;GfowDD;EerwDD;IACE,mBAAA;GfuwDD;EexwDD;IACE,UAAA;Gf0wDD;Ee3wDD;IACE,mBAAA;Gf6wDD;Ee9wDD;IACE,mBAAA;GfgxDD;EejxDD;IACE,UAAA;GfmxDD;EepxDD;IACE,mBAAA;GfsxDD;EevxDD;IACE,mBAAA;GfyxDD;Ee1xDD;IACE,UAAA;Gf4xDD;Ee7xDD;IACE,mBAAA;Gf+xDD;EehyDD;IACE,kBAAA;GfkyDD;Ee9xDD;IACE,WAAA;GfgyDD;EelxDD;IACE,kBAAA;GfoxDD;EerxDD;IACE,0BAAA;GfuxDD;EexxDD;IACE,0BAAA;Gf0xDD;Ee3xDD;IACE,iBAAA;Gf6xDD;Ee9xDD;IACE,0BAAA;GfgyDD;EejyDD;IACE,0BAAA;GfmyDD;EepyDD;IACE,iBAAA;GfsyDD;EevyDD;IACE,0BAAA;GfyyDD;Ee1yDD;IACE,0BAAA;Gf4yDD;Ee7yDD;IACE,iBAAA;Gf+yDD;EehzDD;IACE,0BAAA;GfkzDD;EenzDD;IACE,yBAAA;GfqzDD;EetzDD;IACE,gBAAA;GfwzDD;CACF;AahzDD;EE3CI;IACE,YAAA;Gf81DH;Eev1DD;IACE,YAAA;Gfy1DD;Ee11DD;IACE,oBAAA;Gf41DD;Ee71DD;IACE,oBAAA;Gf+1DD;Eeh2DD;IACE,WAAA;Gfk2DD;Een2DD;IACE,oBAAA;Gfq2DD;Eet2DD;IACE,oBAAA;Gfw2DD;Eez2DD;IACE,WAAA;Gf22DD;Ee52DD;IACE,oBAAA;Gf82DD;Ee/2DD;IACE,oBAAA;Gfi3DD;Eel3DD;IACE,WAAA;Gfo3DD;Eer3DD;IACE,oBAAA;Gfu3DD;Eex3DD;IACE,mBAAA;Gf03DD;Ee52DD;IACE,YAAA;Gf82DD;Ee/2DD;IACE,oBAAA;Gfi3DD;Eel3DD;IACE,oBAAA;Gfo3DD;Eer3DD;IACE,WAAA;Gfu3DD;Eex3DD;IACE,oBAAA;Gf03DD;Ee33DD;IACE,oBAAA;Gf63DD;Ee93DD;IACE,WAAA;Gfg4DD;Eej4DD;IACE,oBAAA;Gfm4DD;Eep4DD;IACE,oBAAA;Gfs4DD;Eev4DD;IACE,WAAA;Gfy4DD;Ee14DD;IACE,oBAAA;Gf44DD;Ee74DD;IACE,mBAAA;Gf+4DD;Ee34DD;IACE,YAAA;Gf64DD;Ee75DD;IACE,WAAA;Gf+5DD;Eeh6DD;IACE,mBAAA;Gfk6DD;Een6DD;IACE,mBAAA;Gfq6DD;Eet6DD;IACE,UAAA;Gfw6DD;Eez6DD;IACE,mBAAA;Gf26DD;Ee56DD;IACE,mBAAA;Gf86DD;Ee/6DD;IACE,UAAA;Gfi7DD;Eel7DD;IACE,mBAAA;Gfo7DD;Eer7DD;IACE,mBAAA;Gfu7DD;Eex7DD;IACE,UAAA;Gf07DD;Ee37DD;IACE,mBAAA;Gf67DD;Ee97DD;IACE,kBAAA;Gfg8DD;Ee57DD;IACE,WAAA;Gf87DD;Eeh7DD;IACE,kBAAA;Gfk7DD;Een7DD;IACE,0BAAA;Gfq7DD;Eet7DD;IACE,0BAAA;Gfw7DD;Eez7DD;IACE,iBAAA;Gf27DD;Ee57DD;IACE,0BAAA;Gf87DD;Ee/7DD;IACE,0BAAA;Gfi8DD;Eel8DD;IACE,iBAAA;Gfo8DD;Eer8DD;IACE,0BAAA;Gfu8DD;Eex8DD;IACE,0BAAA;Gf08DD;Ee38DD;IACE,iBAAA;Gf68DD;Ee98DD;IACE,0BAAA;Gfg9DD;Eej9DD;IACE,yBAAA;Gfm9DD;Eep9DD;IACE,gBAAA;Gfs9DD;CACF;Aa38DD;EE9CI;IACE,YAAA;Gf4/DH;Eer/DD;IACE,YAAA;Gfu/DD;Eex/DD;IACE,oBAAA;Gf0/DD;Ee3/DD;IACE,oBAAA;Gf6/DD;Ee9/DD;IACE,WAAA;GfggED;EejgED;IACE,oBAAA;GfmgED;EepgED;IACE,oBAAA;GfsgED;EevgED;IACE,WAAA;GfygED;Ee1gED;IACE,oBAAA;Gf4gED;Ee7gED;IACE,oBAAA;Gf+gED;EehhED;IACE,WAAA;GfkhED;EenhED;IACE,oBAAA;GfqhED;EethED;IACE,mBAAA;GfwhED;Ee1gED;IACE,YAAA;Gf4gED;Ee7gED;IACE,oBAAA;Gf+gED;EehhED;IACE,oBAAA;GfkhED;EenhED;IACE,WAAA;GfqhED;EethED;IACE,oBAAA;GfwhED;EezhED;IACE,oBAAA;Gf2hED;Ee5hED;IACE,WAAA;Gf8hED;Ee/hED;IACE,oBAAA;GfiiED;EeliED;IACE,oBAAA;GfoiED;EeriED;IACE,WAAA;GfuiED;EexiED;IACE,oBAAA;Gf0iED;Ee3iED;IACE,mBAAA;Gf6iED;EeziED;IACE,YAAA;Gf2iED;Ee3jED;IACE,WAAA;Gf6jED;Ee9jED;IACE,mBAAA;GfgkED;EejkED;IACE,mBAAA;GfmkED;EepkED;IACE,UAAA;GfskED;EevkED;IACE,mBAAA;GfykED;Ee1kED;IACE,mBAAA;Gf4kED;Ee7kED;IACE,UAAA;Gf+kED;EehlED;IACE,mBAAA;GfklED;EenlED;IACE,mBAAA;GfqlED;EetlED;IACE,UAAA;GfwlED;EezlED;IACE,mBAAA;Gf2lED;Ee5lED;IACE,kBAAA;Gf8lED;Ee1lED;IACE,WAAA;Gf4lED;Ee9kED;IACE,kBAAA;GfglED;EejlED;IACE,0BAAA;GfmlED;EeplED;IACE,0BAAA;GfslED;EevlED;IACE,iBAAA;GfylED;Ee1lED;IACE,0BAAA;Gf4lED;Ee7lED;IACE,0BAAA;Gf+lED;EehmED;IACE,iBAAA;GfkmED;EenmED;IACE,0BAAA;GfqmED;EetmED;IACE,0BAAA;GfwmED;EezmED;IACE,iBAAA;Gf2mED;Ee5mED;IACE,0BAAA;Gf8mED;Ee/mED;IACE,yBAAA;GfinED;EelnED;IACE,gBAAA;GfonED;CACF;AgBxrED;EACE,8BAAA;ChB0rED;AgBxrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChB0rED;AgBxrED;EACE,iBAAA;ChB0rED;AgBprED;EACE,YAAA;EACA,gBAAA;EACA,oBAAA;ChBsrED;AgBzrED;;;;;;EAWQ,aAAA;EACA,wBAAA;EACA,oBAAA;EACA,2BAAA;ChBsrEP;AgBpsED;EAoBI,uBAAA;EACA,8BAAA;ChBmrEH;AgBxsED;;;;;;EA8BQ,cAAA;ChBkrEP;AgBhtED;EAoCI,2BAAA;ChB+qEH;AgBntED;EAyCI,uBAAA;ChB6qEH;AgBtqED;;;;;;EAOQ,aAAA;ChBuqEP;AgB5pED;EACE,uBAAA;ChB8pED;AgB/pED;;;;;;EAQQ,uBAAA;ChB+pEP;AgBvqED;;EAeM,yBAAA;ChB4pEL;AgBlpED;EAEI,0BAAA;ChBmpEH;AgB1oED;EAEI,0BAAA;ChB2oEH;AgBloED;EACE,iBAAA;EACA,YAAA;EACA,sBAAA;ChBooED;AgB/nEG;;EACE,iBAAA;EACA,YAAA;EACA,oBAAA;ChBkoEL;AiB9wEC;;;;;;;;;;;;EAOI,0BAAA;CjBqxEL;AiB/wEC;;;;;EAMI,0BAAA;CjBgxEL;AiBnyEC;;;;;;;;;;;;EAOI,0BAAA;CjB0yEL;AiBpyEC;;;;;EAMI,0BAAA;CjBqyEL;AiBxzEC;;;;;;;;;;;;EAOI,0BAAA;CjB+zEL;AiBzzEC;;;;;EAMI,0BAAA;CjB0zEL;AiB70EC;;;;;;;;;;;;EAOI,0BAAA;CjBo1EL;AiB90EC;;;;;EAMI,0BAAA;CjB+0EL;AiBl2EC;;;;;;;;;;;;EAOI,0BAAA;CjBy2EL;AiBn2EC;;;;;EAMI,0BAAA;CjBo2EL;AgBltED;EACE,iBAAA;EACA,kBAAA;ChBotED;AgBvpED;EACA;IA3DI,YAAA;IACA,oBAAA;IACA,mBAAA;IACA,6CAAA;IACA,uBAAA;GhBqtED;EgB9pEH;IAnDM,iBAAA;GhBotEH;EgBjqEH;;;;;;IA1CY,oBAAA;GhBmtET;EgBzqEH;IAlCM,UAAA;GhB8sEH;EgB5qEH;;;;;;IAzBY,eAAA;GhB6sET;EgBprEH;;;;;;IArBY,gBAAA;GhBitET;EgB5rEH;;;;IARY,iBAAA;GhB0sET;CACF;AkBp6ED;EACE,WAAA;EACA,UAAA;EACA,UAAA;EAIA,aAAA;ClBm6ED;AkBh6ED;EACE,eAAA;EACA,YAAA;EACA,WAAA;EACA,oBAAA;EACA,gBAAA;EACA,qBAAA;EACA,eAAA;EACA,UAAA;EACA,iCAAA;ClBk6ED;AkB/5ED;EACE,sBAAA;EACA,gBAAA;EACA,mBAAA;EACA,kBAAA;ClBi6ED;AkBt5ED;Eb4BE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL63ET;AkBt5ED;;EAEE,gBAAA;EACA,mBAAA;EACA,oBAAA;ClBw5ED;AkBr5ED;EACE,eAAA;ClBu5ED;AkBn5ED;EACE,eAAA;EACA,YAAA;ClBq5ED;AkBj5ED;;EAEE,aAAA;ClBm5ED;AkB/4ED;;;EZvEE,qBAAA;EAEA,2CAAA;EACA,qBAAA;CN09ED;AkB/4ED;EACE,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;ClBi5ED;AkBv3ED;EACE,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EbxDA,yDAAA;EACQ,iDAAA;EAyHR,uFAAA;EACK,0EAAA;EACG,uEAAA;CL0zET;AmBl8EC;EACE,sBAAA;EACA,WAAA;EdUF,uFAAA;EACQ,+EAAA;CL27ET;AK15EC;EACE,YAAA;EACA,WAAA;CL45EH;AK15EC;EAA0B,YAAA;CL65E3B;AK55EC;EAAgC,YAAA;CL+5EjC;AkBn4EC;EACE,UAAA;EACA,8BAAA;ClBq4EH;AkB73EC;;;EAGE,0BAAA;EACA,WAAA;ClB+3EH;AkB53EC;;EAEE,oBAAA;ClB83EH;AkB13EC;EACE,aAAA;ClB43EH;AkBh3ED;EACE,yBAAA;ClBk3ED;AkB10ED;EAtBI;;;;IACE,kBAAA;GlBs2EH;EkBn2EC;;;;;;;;IAEE,kBAAA;GlB22EH;EkBx2EC;;;;;;;;IAEE,kBAAA;GlBg3EH;CACF;AkBt2ED;EACE,oBAAA;ClBw2ED;AkBh2ED;;EAEE,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,oBAAA;ClBk2ED;AkBv2ED;;EAQI,iBAAA;EACA,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,gBAAA;ClBm2EH;AkBh2ED;;;;EAIE,mBAAA;EACA,mBAAA;EACA,mBAAA;ClBk2ED;AkB/1ED;;EAEE,iBAAA;ClBi2ED;AkB71ED;;EAEE,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;ClB+1ED;AkB71ED;;EAEE,cAAA;EACA,kBAAA;ClB+1ED;AkBt1EC;;;;;;EAGE,oBAAA;ClB21EH;AkBr1EC;;;;EAEE,oBAAA;ClBy1EH;AkBn1EC;;;;EAGI,oBAAA;ClBs1EL;AkB30ED;EAEE,iBAAA;EACA,oBAAA;EAEA,iBAAA;EACA,iBAAA;ClB20ED;AkBz0EC;;EAEE,gBAAA;EACA,iBAAA;ClB20EH;AkB9zED;ECnQE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBokFD;AmBlkFC;EACE,aAAA;EACA,kBAAA;CnBokFH;AmBjkFC;;EAEE,aAAA;CnBmkFH;AkB10ED;EAEI,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;ClB20EH;AkBj1ED;EASI,aAAA;EACA,kBAAA;ClB20EH;AkBr1ED;;EAcI,aAAA;ClB20EH;AkBz1ED;EAiBI,aAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;ClB20EH;AkBv0ED;EC/RE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBymFD;AmBvmFC;EACE,aAAA;EACA,kBAAA;CnBymFH;AmBtmFC;;EAEE,aAAA;CnBwmFH;AkBn1ED;EAEI,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ClBo1EH;AkB11ED;EASI,aAAA;EACA,kBAAA;ClBo1EH;AkB91ED;;EAcI,aAAA;ClBo1EH;AkBl2ED;EAiBI,aAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;ClBo1EH;AkB30ED;EAEE,mBAAA;ClB40ED;AkB90ED;EAMI,sBAAA;ClB20EH;AkBv0ED;EACE,mBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;ClBy0ED;AkBv0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBy0ED;AkBv0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBy0ED;AkBr0ED;;;;;;;;;;EC1ZI,eAAA;CnB2uFH;AkBj1ED;ECtZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CL4rFT;AmB1uFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CLisFT;AkB31ED;EC5YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnB0uFH;AkBh2ED;ECtYI,eAAA;CnByuFH;AkBh2ED;;;;;;;;;;EC7ZI,eAAA;CnBywFH;AkB52ED;ECzZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CL0tFT;AmBxwFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL+tFT;AkBt3ED;EC/YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBwwFH;AkB33ED;ECzYI,eAAA;CnBuwFH;AkB33ED;;;;;;;;;;EChaI,eAAA;CnBuyFH;AkBv4ED;EC5ZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLwvFT;AmBtyFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL6vFT;AkBj5ED;EClZI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBsyFH;AkBt5ED;EC5YI,eAAA;CnBqyFH;AkBl5EC;EACE,UAAA;ClBo5EH;AkBl5EC;EACE,OAAA;ClBo5EH;AkB14ED;EACE,eAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;ClB44ED;AkBzzED;EAwEA;IAtIM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB23EH;EkBvvEH;IA/HM,sBAAA;IACA,YAAA;IACA,uBAAA;GlBy3EH;EkB5vEH;IAxHM,sBAAA;GlBu3EH;EkB/vEH;IApHM,sBAAA;IACA,uBAAA;GlBs3EH;EkBnwEH;;;IA9GQ,YAAA;GlBs3EL;EkBxwEH;IAxGM,YAAA;GlBm3EH;EkB3wEH;IApGM,iBAAA;IACA,uBAAA;GlBk3EH;EkB/wEH;;IA5FM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB+2EH;EkBtxEH;;IAtFQ,gBAAA;GlBg3EL;EkB1xEH;;IAjFM,mBAAA;IACA,eAAA;GlB+2EH;EkB/xEH;IA3EM,OAAA;GlB62EH;CACF;AkBn2ED;;;;EASI,cAAA;EACA,iBAAA;EACA,iBAAA;ClBg2EH;AkB32ED;;EAiBI,iBAAA;ClB81EH;AkB/2ED;EJthBE,mBAAA;EACA,oBAAA;Cdw4FD;AkB50EC;EAyBF;IAnCM,kBAAA;IACA,iBAAA;IACA,iBAAA;GlB01EH;CACF;AkB13ED;EAwCI,YAAA;ClBq1EH;AkBv0EC;EAUF;IAdQ,kBAAA;IACA,gBAAA;GlB+0EL;CACF;AkBr0EC;EAEF;IANQ,iBAAA;IACA,gBAAA;GlB60EL;CACF;AoBt6FD;EACE,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,uBAAA;EACA,+BAAA;MAAA,2BAAA;EACA,gBAAA;EACA,uBAAA;EACA,8BAAA;EACA,oBAAA;EC0CA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,mBAAA;EhB+JA,0BAAA;EACG,uBAAA;EACC,sBAAA;EACI,kBAAA;CLiuFT;AoBz6FG;;;;;;EdrBF,qBAAA;EAEA,2CAAA;EACA,qBAAA;CNq8FD;AoB76FC;;;EAGE,YAAA;EACA,sBAAA;CpB+6FH;AoB56FC;;EAEE,WAAA;EACA,uBAAA;Ef2BF,yDAAA;EACQ,iDAAA;CLo5FT;AoB56FC;;;EAGE,oBAAA;EE7CF,cAAA;EAGA,0BAAA;EjB8DA,yBAAA;EACQ,iBAAA;CL65FT;AoB56FG;;EAEE,qBAAA;CpB86FL;AoBr6FD;EC3DE,YAAA;EACA,uBAAA;EACA,mBAAA;CrBm+FD;AqBj+FC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBm+FP;AqBj+FC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBm+FP;AqBj+FC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBm+FP;AqBj+FG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBy+FT;AqBt+FC;;;EAGE,uBAAA;CrBw+FH;AqBn+FG;;;;;;;;;EAGE,uBAAA;EACI,mBAAA;CrB2+FT;AoB19FD;ECZI,YAAA;EACA,uBAAA;CrBy+FH;AoB39FD;EC9DE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB4hGD;AqB1hGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB4hGP;AqB1hGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB4hGP;AqB1hGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB4hGP;AqB1hGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBkiGT;AqB/hGC;;;EAGE,uBAAA;CrBiiGH;AqB5hGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBoiGT;AoBhhGD;ECfI,eAAA;EACA,uBAAA;CrBkiGH;AoBhhGD;EClEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBqlGD;AqBnlGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBqlGP;AqBnlGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBqlGP;AqBnlGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBqlGP;AqBnlGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB2lGT;AqBxlGC;;;EAGE,uBAAA;CrB0lGH;AqBrlGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrB6lGT;AoBrkGD;ECnBI,eAAA;EACA,uBAAA;CrB2lGH;AoBrkGD;ECtEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB8oGD;AqB5oGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB8oGP;AqB5oGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB8oGP;AqB5oGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB8oGP;AqB5oGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBopGT;AqBjpGC;;;EAGE,uBAAA;CrBmpGH;AqB9oGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBspGT;AoB1nGD;ECvBI,eAAA;EACA,uBAAA;CrBopGH;AoB1nGD;EC1EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBusGD;AqBrsGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBusGP;AqBrsGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBusGP;AqBrsGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBusGP;AqBrsGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrB6sGT;AqB1sGC;;;EAGE,uBAAA;CrB4sGH;AqBvsGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrB+sGT;AoB/qGD;EC3BI,eAAA;EACA,uBAAA;CrB6sGH;AoB/qGD;EC9EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBgwGD;AqB9vGC;;EAEE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBgwGP;AqB9vGC;EACE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBgwGP;AqB9vGC;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBgwGP;AqB9vGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACI,sBAAA;CrBswGT;AqBnwGC;;;EAGE,uBAAA;CrBqwGH;AqBhwGG;;;;;;;;;EAGE,0BAAA;EACI,sBAAA;CrBwwGT;AoBpuGD;EC/BI,eAAA;EACA,uBAAA;CrBswGH;AoB/tGD;EACE,eAAA;EACA,oBAAA;EACA,iBAAA;CpBiuGD;AoB/tGC;;;;;EAKE,8BAAA;EfnCF,yBAAA;EACQ,iBAAA;CLqwGT;AoBhuGC;;;;EAIE,0BAAA;CpBkuGH;AoBhuGC;;EAEE,eAAA;EACA,2BAAA;EACA,8BAAA;CpBkuGH;AoB9tGG;;;;EAEE,eAAA;EACA,sBAAA;CpBkuGL;AoBztGD;;ECxEE,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CrBqyGD;AoB5tGD;;EC5EE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrB4yGD;AoB/tGD;;EChFE,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrBmzGD;AoB9tGD;EACE,eAAA;EACA,YAAA;CpBguGD;AoB5tGD;EACE,gBAAA;CpB8tGD;AoBvtGC;;;EACE,YAAA;CpB2tGH;AuBr3GD;EACE,WAAA;ElBoLA,yCAAA;EACK,oCAAA;EACG,iCAAA;CLosGT;AuBx3GC;EACE,WAAA;CvB03GH;AuBt3GD;EACE,cAAA;CvBw3GD;AuBt3GC;EAAY,eAAA;CvBy3Gb;AuBx3GC;EAAY,mBAAA;CvB23Gb;AuB13GC;EAAY,yBAAA;CvB63Gb;AuB13GD;EACE,mBAAA;EACA,UAAA;EACA,iBAAA;ElBuKA,gDAAA;EACQ,2CAAA;KAAA,wCAAA;EAOR,mCAAA;EACQ,8BAAA;KAAA,2BAAA;EAGR,yCAAA;EACQ,oCAAA;KAAA,iCAAA;CL8sGT;AwBx5GD;EACE,sBAAA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,yBAAA;EACA,oCAAA;EACA,mCAAA;CxB05GD;AwBt5GD;;EAEE,mBAAA;CxBw5GD;AwBp5GD;EACE,WAAA;CxBs5GD;AwBl5GD;EACE,mBAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,sCAAA;EACA,mBAAA;EnBsBA,oDAAA;EACQ,4CAAA;EmBrBR,qCAAA;UAAA,6BAAA;CxBq5GD;AwBh5GC;EACE,SAAA;EACA,WAAA;CxBk5GH;AwB36GD;ECzBE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBu8GD;AwBj7GD;EAmCI,eAAA;EACA,kBAAA;EACA,YAAA;EACA,oBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBi5GH;AwB34GC;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CxB64GH;AwBv4GC;;;EAGE,YAAA;EACA,sBAAA;EACA,WAAA;EACA,0BAAA;CxBy4GH;AwBh4GC;;;EAGE,eAAA;CxBk4GH;AwB93GC;;EAEE,sBAAA;EACA,8BAAA;EACA,uBAAA;EE3GF,oEAAA;EF6GE,oBAAA;CxBg4GH;AwB33GD;EAGI,eAAA;CxB23GH;AwB93GD;EAQI,WAAA;CxBy3GH;AwBj3GD;EACE,WAAA;EACA,SAAA;CxBm3GD;AwB32GD;EACE,QAAA;EACA,YAAA;CxB62GD;AwBz2GD;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxB22GD;AwBv2GD;EACE,gBAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;CxBy2GD;AwBr2GD;EACE,SAAA;EACA,WAAA;CxBu2GD;AwB/1GD;;EAII,cAAA;EACA,0BAAA;EACA,4BAAA;EACA,YAAA;CxB+1GH;AwBt2GD;;EAWI,UAAA;EACA,aAAA;EACA,mBAAA;CxB+1GH;AwB10GD;EAXE;IApEA,WAAA;IACA,SAAA;GxB65GC;EwB11GD;IA1DA,QAAA;IACA,YAAA;GxBu5GC;CACF;A2BviHD;;EAEE,mBAAA;EACA,sBAAA;EACA,uBAAA;C3ByiHD;A2B7iHD;;EAMI,mBAAA;EACA,YAAA;C3B2iHH;A2BziHG;;;;;;;;EAIE,WAAA;C3B+iHL;A2BziHD;;;;EAKI,kBAAA;C3B0iHH;A2BriHD;EACE,kBAAA;C3BuiHD;A2BxiHD;;;EAOI,YAAA;C3BsiHH;A2B7iHD;;;EAYI,iBAAA;C3BsiHH;A2BliHD;EACE,iBAAA;C3BoiHD;A2BhiHD;EACE,eAAA;C3BkiHD;A2BjiHC;EClDA,8BAAA;EACG,2BAAA;C5BslHJ;A2BhiHD;;EC/CE,6BAAA;EACG,0BAAA;C5BmlHJ;A2B/hHD;EACE,YAAA;C3BiiHD;A2B/hHD;EACE,iBAAA;C3BiiHD;A2B/hHD;;ECnEE,8BAAA;EACG,2BAAA;C5BsmHJ;A2B9hHD;ECjEE,6BAAA;EACG,0BAAA;C5BkmHJ;A2B7hHD;;EAEE,WAAA;C3B+hHD;A2B9gHD;EACE,kBAAA;EACA,mBAAA;C3BghHD;A2B9gHD;EACE,mBAAA;EACA,oBAAA;C3BghHD;A2B3gHD;EtB/CE,yDAAA;EACQ,iDAAA;CL6jHT;A2B3gHC;EtBnDA,yBAAA;EACQ,iBAAA;CLikHT;A2BxgHD;EACE,eAAA;C3B0gHD;A2BvgHD;EACE,wBAAA;EACA,uBAAA;C3BygHD;A2BtgHD;EACE,wBAAA;C3BwgHD;A2BjgHD;;;EAII,eAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;C3BkgHH;A2BzgHD;EAcM,YAAA;C3B8/GL;A2B5gHD;;;;EAsBI,iBAAA;EACA,eAAA;C3B4/GH;A2Bv/GC;EACE,iBAAA;C3By/GH;A2Bv/GC;EC3KA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5B+pHF;A2Bz/GC;EC/KA,2BAAA;EACC,0BAAA;EAOD,gCAAA;EACC,+BAAA;C5BqqHF;A2B1/GD;EACE,iBAAA;C3B4/GD;A2B1/GD;;EC/KE,8BAAA;EACC,6BAAA;C5B6qHF;A2Bz/GD;EC7LE,2BAAA;EACC,0BAAA;C5ByrHF;A2Br/GD;EACE,eAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;C3Bu/GD;A2B3/GD;;EAOI,YAAA;EACA,oBAAA;EACA,UAAA;C3Bw/GH;A2BjgHD;EAYI,YAAA;C3Bw/GH;A2BpgHD;EAgBI,WAAA;C3Bu/GH;A2Bt+GD;;;;EAKM,mBAAA;EACA,uBAAA;EACA,qBAAA;C3Bu+GL;A6BjtHD;EACE,mBAAA;EACA,eAAA;EACA,0BAAA;C7BmtHD;A6BhtHC;EACE,YAAA;EACA,gBAAA;EACA,iBAAA;C7BktHH;A6B3tHD;EAeI,mBAAA;EACA,WAAA;EAKA,YAAA;EAEA,YAAA;EACA,iBAAA;C7B0sHH;A6BxsHG;EACE,WAAA;C7B0sHL;A6BhsHD;;;EV0BE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnB2qHD;AmBzqHC;;;EACE,aAAA;EACA,kBAAA;CnB6qHH;AmB1qHC;;;;;;EAEE,aAAA;CnBgrHH;A6BltHD;;;EVqBE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBksHD;AmBhsHC;;;EACE,aAAA;EACA,kBAAA;CnBosHH;AmBjsHC;;;;;;EAEE,aAAA;CnBusHH;A6BhuHD;;;EAGE,oBAAA;C7BkuHD;A6BhuHC;;;EACE,iBAAA;C7BouHH;A6BhuHD;;EAEE,UAAA;EACA,oBAAA;EACA,uBAAA;C7BkuHD;A6B7tHD;EACE,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;C7B+tHD;A6B5tHC;EACE,kBAAA;EACA,gBAAA;EACA,mBAAA;C7B8tHH;A6B5tHC;EACE,mBAAA;EACA,gBAAA;EACA,mBAAA;C7B8tHH;A6BlvHD;;EA0BI,cAAA;C7B4tHH;A6BvtHD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;C5Bo0HJ;A6BxtHD;EACE,gBAAA;C7B0tHD;A6BxtHD;;;;;;;EDxGE,6BAAA;EACG,0BAAA;C5By0HJ;A6BztHD;EACE,eAAA;C7B2tHD;A6BttHD;EACE,mBAAA;EAGA,aAAA;EACA,oBAAA;C7BstHD;A6B3tHD;EAUI,mBAAA;C7BotHH;A6B9tHD;EAYM,kBAAA;C7BqtHL;A6BltHG;;;EAGE,WAAA;C7BotHL;A6B/sHC;;EAGI,mBAAA;C7BgtHL;A6B7sHC;;EAGI,WAAA;EACA,kBAAA;C7B8sHL;A8B72HD;EACE,iBAAA;EACA,gBAAA;EACA,iBAAA;C9B+2HD;A8Bl3HD;EAOI,mBAAA;EACA,eAAA;C9B82HH;A8Bt3HD;EAWM,mBAAA;EACA,eAAA;EACA,mBAAA;C9B82HL;A8B72HK;;EAEE,sBAAA;EACA,0BAAA;C9B+2HP;A8B12HG;EACE,eAAA;C9B42HL;A8B12HK;;EAEE,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,oBAAA;C9B42HP;A8Br2HG;;;EAGE,0BAAA;EACA,sBAAA;C9Bu2HL;A8Bh5HD;ELHE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBs5HD;A8Bt5HD;EA0DI,gBAAA;C9B+1HH;A8Bt1HD;EACE,8BAAA;C9Bw1HD;A8Bz1HD;EAGI,YAAA;EAEA,oBAAA;C9Bw1HH;A8B71HD;EASM,kBAAA;EACA,wBAAA;EACA,8BAAA;EACA,2BAAA;C9Bu1HL;A8Bt1HK;EACE,mCAAA;C9Bw1HP;A8Bl1HK;;;EAGE,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,iCAAA;EACA,gBAAA;C9Bo1HP;A8B/0HC;EAqDA,YAAA;EA8BA,iBAAA;C9BgwHD;A8Bn1HC;EAwDE,YAAA;C9B8xHH;A8Bt1HC;EA0DI,mBAAA;EACA,mBAAA;C9B+xHL;A8B11HC;EAgEE,UAAA;EACA,WAAA;C9B6xHH;A8BjxHD;EA0DA;IAjEM,oBAAA;IACA,UAAA;G9B4xHH;E8B5tHH;IA9DQ,iBAAA;G9B6xHL;CACF;A8Bv2HC;EAuFE,gBAAA;EACA,mBAAA;C9BmxHH;A8B32HC;;;EA8FE,uBAAA;C9BkxHH;A8BpwHD;EA2BA;IApCM,8BAAA;IACA,2BAAA;G9BixHH;E8B9uHH;;;IA9BM,0BAAA;G9BixHH;CACF;A8Bl3HD;EAEI,YAAA;C9Bm3HH;A8Br3HD;EAMM,mBAAA;C9Bk3HL;A8Bx3HD;EASM,iBAAA;C9Bk3HL;A8B72HK;;;EAGE,YAAA;EACA,0BAAA;C9B+2HP;A8Bv2HD;EAEI,YAAA;C9Bw2HH;A8B12HD;EAIM,gBAAA;EACA,eAAA;C9By2HL;A8B71HD;EACE,YAAA;C9B+1HD;A8Bh2HD;EAII,YAAA;C9B+1HH;A8Bn2HD;EAMM,mBAAA;EACA,mBAAA;C9Bg2HL;A8Bv2HD;EAYI,UAAA;EACA,WAAA;C9B81HH;A8Bl1HD;EA0DA;IAjEM,oBAAA;IACA,UAAA;G9B61HH;E8B7xHH;IA9DQ,iBAAA;G9B81HL;CACF;A8Bt1HD;EACE,iBAAA;C9Bw1HD;A8Bz1HD;EAKI,gBAAA;EACA,mBAAA;C9Bu1HH;A8B71HD;;;EAYI,uBAAA;C9Bs1HH;A8Bx0HD;EA2BA;IApCM,8BAAA;IACA,2BAAA;G9Bq1HH;E8BlzHH;;;IA9BM,0BAAA;G9Bq1HH;CACF;A8B50HD;EAEI,cAAA;C9B60HH;A8B/0HD;EAKI,eAAA;C9B60HH;A8Bp0HD;EAEE,iBAAA;EF3OA,2BAAA;EACC,0BAAA;C5BijIF;A+B3iID;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,8BAAA;C/B6iID;A+BriID;EA8nBA;IAhoBI,mBAAA;G/B2iID;CACF;A+B5hID;EAgnBA;IAlnBI,YAAA;G/BkiID;CACF;A+BphID;EACE,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,2DAAA;UAAA,mDAAA;EAEA,kCAAA;C/BqhID;A+BnhIC;EACE,iBAAA;C/BqhIH;A+Bz/HD;EA6jBA;IArlBI,YAAA;IACA,cAAA;IACA,yBAAA;YAAA,iBAAA;G/BqhID;E+BnhIC;IACE,0BAAA;IACA,wBAAA;IACA,kBAAA;IACA,6BAAA;G/BqhIH;E+BlhIC;IACE,oBAAA;G/BohIH;E+B/gIC;;;IAGE,gBAAA;IACA,iBAAA;G/BihIH;CACF;A+B7gID;;EAGI,kBAAA;C/B8gIH;A+BzgIC;EAmjBF;;IArjBM,kBAAA;G/BghIH;CACF;A+BvgID;;;;EAII,oBAAA;EACA,mBAAA;C/BygIH;A+BngIC;EAgiBF;;;;IAniBM,gBAAA;IACA,eAAA;G/B6gIH;CACF;A+BjgID;EACE,cAAA;EACA,sBAAA;C/BmgID;A+B9/HD;EA8gBA;IAhhBI,iBAAA;G/BogID;CACF;A+BhgID;;EAEE,gBAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;C/BkgID;A+B5/HD;EAggBA;;IAlgBI,iBAAA;G/BmgID;CACF;A+BjgID;EACE,OAAA;EACA,sBAAA;C/BmgID;A+BjgID;EACE,UAAA;EACA,iBAAA;EACA,sBAAA;C/BmgID;A+B7/HD;EACE,YAAA;EACA,mBAAA;EACA,gBAAA;EACA,kBAAA;EACA,aAAA;C/B+/HD;A+B7/HC;;EAEE,sBAAA;C/B+/HH;A+BxgID;EAaI,eAAA;C/B8/HH;A+Br/HD;EALI;;IAEE,mBAAA;G/B6/HH;CACF;A+Bn/HD;EACE,mBAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;EC9LA,gBAAA;EACA,mBAAA;ED+LA,8BAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;C/Bs/HD;A+Bl/HC;EACE,WAAA;C/Bo/HH;A+BlgID;EAmBI,eAAA;EACA,YAAA;EACA,YAAA;EACA,mBAAA;C/Bk/HH;A+BxgID;EAyBI,gBAAA;C/Bk/HH;A+B5+HD;EAqbA;IAvbI,cAAA;G/Bk/HD;CACF;A+Bz+HD;EACE,oBAAA;C/B2+HD;A+B5+HD;EAII,kBAAA;EACA,qBAAA;EACA,kBAAA;C/B2+HH;A+B/8HC;EA2YF;IAjaM,iBAAA;IACA,YAAA;IACA,YAAA;IACA,cAAA;IACA,8BAAA;IACA,UAAA;IACA,yBAAA;YAAA,iBAAA;G/By+HH;E+B9kHH;;IAxZQ,2BAAA;G/B0+HL;E+BllHH;IArZQ,kBAAA;G/B0+HL;E+Bz+HK;;IAEE,uBAAA;G/B2+HP;CACF;A+Bz9HD;EA+XA;IA1YI,YAAA;IACA,UAAA;G/Bw+HD;E+B/lHH;IAtYM,YAAA;G/Bw+HH;E+BlmHH;IApYQ,kBAAA;IACA,qBAAA;G/By+HL;CACF;A+B99HD;EACE,mBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,qCAAA;E1B9NA,6FAAA;EACQ,qFAAA;E2B/DR,gBAAA;EACA,mBAAA;ChC+vID;AkBzuHD;EAwEA;IAtIM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB2yHH;EkBvqHH;IA/HM,sBAAA;IACA,YAAA;IACA,uBAAA;GlByyHH;EkB5qHH;IAxHM,sBAAA;GlBuyHH;EkB/qHH;IApHM,sBAAA;IACA,uBAAA;GlBsyHH;EkBnrHH;;;IA9GQ,YAAA;GlBsyHL;EkBxrHH;IAxGM,YAAA;GlBmyHH;EkB3rHH;IApGM,iBAAA;IACA,uBAAA;GlBkyHH;EkB/rHH;;IA5FM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB+xHH;EkBtsHH;;IAtFQ,gBAAA;GlBgyHL;EkB1sHH;;IAjFM,mBAAA;IACA,eAAA;GlB+xHH;EkB/sHH;IA3EM,OAAA;GlB6xHH;CACF;A+BvgIC;EAmWF;IAzWM,mBAAA;G/BihIH;E+B/gIG;IACE,iBAAA;G/BihIL;CACF;A+BhgID;EAoVA;IA5VI,YAAA;IACA,UAAA;IACA,eAAA;IACA,gBAAA;IACA,eAAA;IACA,kBAAA;I1BzPF,yBAAA;IACQ,iBAAA;GLswIP;CACF;A+BtgID;EACE,cAAA;EHpUA,2BAAA;EACC,0BAAA;C5B60IF;A+BtgID;EACE,iBAAA;EHzUA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5B40IF;A+BlgID;EChVE,gBAAA;EACA,mBAAA;ChCq1ID;A+BngIC;ECnVA,iBAAA;EACA,oBAAA;ChCy1ID;A+BpgIC;ECtVA,iBAAA;EACA,oBAAA;ChC61ID;A+B9/HD;EChWE,iBAAA;EACA,oBAAA;ChCi2ID;A+B1/HD;EAsSA;IA1SI,YAAA;IACA,kBAAA;IACA,mBAAA;G/BkgID;CACF;A+Br+HD;EAhBE;IExWA,uBAAA;GjCi2IC;E+Bx/HD;IE5WA,wBAAA;IF8WE,oBAAA;G/B0/HD;E+B5/HD;IAKI,gBAAA;G/B0/HH;CACF;A+Bj/HD;EACE,0BAAA;EACA,sBAAA;C/Bm/HD;A+Br/HD;EAKI,YAAA;C/Bm/HH;A+Bl/HG;;EAEE,eAAA;EACA,8BAAA;C/Bo/HL;A+B7/HD;EAcI,YAAA;C/Bk/HH;A+BhgID;EAmBM,YAAA;C/Bg/HL;A+B9+HK;;EAEE,YAAA;EACA,8BAAA;C/Bg/HP;A+B5+HK;;;EAGE,YAAA;EACA,0BAAA;C/B8+HP;A+B1+HK;;;EAGE,YAAA;EACA,8BAAA;C/B4+HP;A+BphID;EA8CI,mBAAA;C/By+HH;A+Bx+HG;;EAEE,uBAAA;C/B0+HL;A+B3hID;EAoDM,uBAAA;C/B0+HL;A+B9hID;;EA0DI,sBAAA;C/Bw+HH;A+Bj+HK;;;EAGE,0BAAA;EACA,YAAA;C/Bm+HP;A+Bl8HC;EAoKF;IA7LU,YAAA;G/B+9HP;E+B99HO;;IAEE,YAAA;IACA,8BAAA;G/Bg+HT;E+B59HO;;;IAGE,YAAA;IACA,0BAAA;G/B89HT;E+B19HO;;;IAGE,YAAA;IACA,8BAAA;G/B49HT;CACF;A+B9jID;EA8GI,YAAA;C/Bm9HH;A+Bl9HG;EACE,YAAA;C/Bo9HL;A+BpkID;EAqHI,YAAA;C/Bk9HH;A+Bj9HG;;EAEE,YAAA;C/Bm9HL;A+B/8HK;;;;EAEE,YAAA;C/Bm9HP;A+B38HD;EACE,uBAAA;EACA,sBAAA;C/B68HD;A+B/8HD;EAKI,eAAA;C/B68HH;A+B58HG;;EAEE,YAAA;EACA,8BAAA;C/B88HL;A+Bv9HD;EAcI,eAAA;C/B48HH;A+B19HD;EAmBM,eAAA;C/B08HL;A+Bx8HK;;EAEE,YAAA;EACA,8BAAA;C/B08HP;A+Bt8HK;;;EAGE,YAAA;EACA,0BAAA;C/Bw8HP;A+Bp8HK;;;EAGE,YAAA;EACA,8BAAA;C/Bs8HP;A+B9+HD;EA+CI,mBAAA;C/Bk8HH;A+Bj8HG;;EAEE,uBAAA;C/Bm8HL;A+Br/HD;EAqDM,uBAAA;C/Bm8HL;A+Bx/HD;;EA2DI,sBAAA;C/Bi8HH;A+B37HK;;;EAGE,0BAAA;EACA,YAAA;C/B67HP;A+Bt5HC;EAwBF;IAvDU,sBAAA;G/By7HP;E+Bl4HH;IApDU,0BAAA;G/By7HP;E+Br4HH;IAjDU,eAAA;G/By7HP;E+Bx7HO;;IAEE,YAAA;IACA,8BAAA;G/B07HT;E+Bt7HO;;;IAGE,YAAA;IACA,0BAAA;G/Bw7HT;E+Bp7HO;;;IAGE,YAAA;IACA,8BAAA;G/Bs7HT;CACF;A+B9hID;EA+GI,eAAA;C/Bk7HH;A+Bj7HG;EACE,YAAA;C/Bm7HL;A+BpiID;EAsHI,eAAA;C/Bi7HH;A+Bh7HG;;EAEE,YAAA;C/Bk7HL;A+B96HK;;;;EAEE,YAAA;C/Bk7HP;AkC5jJD;EACE,kBAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ClC8jJD;AkCnkJD;EAQI,sBAAA;ClC8jJH;AkCtkJD;EAWM,kBAAA;EACA,eAAA;EACA,YAAA;ClC8jJL;AkC3kJD;EAkBI,eAAA;ClC4jJH;AmChlJD;EACE,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,mBAAA;CnCklJD;AmCtlJD;EAOI,gBAAA;CnCklJH;AmCzlJD;;EAUM,mBAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,sBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,kBAAA;CnCmlJL;AmCjlJG;;EAGI,eAAA;EPXN,+BAAA;EACG,4BAAA;C5B8lJJ;AmChlJG;;EPvBF,gCAAA;EACG,6BAAA;C5B2mJJ;AmC3kJG;;;;EAEE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CnC+kJL;AmCzkJG;;;;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;EACA,gBAAA;CnC8kJL;AmCroJD;;;;;;EAkEM,eAAA;EACA,uBAAA;EACA,mBAAA;EACA,oBAAA;CnC2kJL;AmClkJD;;EC3EM,mBAAA;EACA,gBAAA;EACA,uBAAA;CpCipJL;AoC/oJG;;ERKF,+BAAA;EACG,4BAAA;C5B8oJJ;AoC9oJG;;ERTF,gCAAA;EACG,6BAAA;C5B2pJJ;AmC7kJD;;EChFM,kBAAA;EACA,gBAAA;EACA,iBAAA;CpCiqJL;AoC/pJG;;ERKF,+BAAA;EACG,4BAAA;C5B8pJJ;AoC9pJG;;ERTF,gCAAA;EACG,6BAAA;C5B2qJJ;AqC9qJD;EACE,gBAAA;EACA,eAAA;EACA,iBAAA;EACA,mBAAA;CrCgrJD;AqCprJD;EAOI,gBAAA;CrCgrJH;AqCvrJD;;EAUM,sBAAA;EACA,kBAAA;EACA,uBAAA;EACA,uBAAA;EACA,oBAAA;CrCirJL;AqC/rJD;;EAmBM,sBAAA;EACA,0BAAA;CrCgrJL;AqCpsJD;;EA2BM,aAAA;CrC6qJL;AqCxsJD;;EAkCM,YAAA;CrC0qJL;AqC5sJD;;;;EA2CM,eAAA;EACA,uBAAA;EACA,oBAAA;CrCuqJL;AsCrtJD;EACE,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,mBAAA;EACA,oBAAA;EACA,yBAAA;EACA,qBAAA;CtCutJD;AsCntJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CtCqtJL;AsChtJC;EACE,cAAA;CtCktJH;AsC9sJC;EACE,mBAAA;EACA,UAAA;CtCgtJH;AsCzsJD;ECtCE,0BAAA;CvCkvJD;AuC/uJG;;EAEE,0BAAA;CvCivJL;AsC5sJD;EC1CE,0BAAA;CvCyvJD;AuCtvJG;;EAEE,0BAAA;CvCwvJL;AsC/sJD;EC9CE,0BAAA;CvCgwJD;AuC7vJG;;EAEE,0BAAA;CvC+vJL;AsCltJD;EClDE,0BAAA;CvCuwJD;AuCpwJG;;EAEE,0BAAA;CvCswJL;AsCrtJD;ECtDE,0BAAA;CvC8wJD;AuC3wJG;;EAEE,0BAAA;CvC6wJL;AsCxtJD;EC1DE,0BAAA;CvCqxJD;AuClxJG;;EAEE,0BAAA;CvCoxJL;AwCtxJD;EACE,sBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,eAAA;EACA,uBAAA;EACA,oBAAA;EACA,mBAAA;EACA,0BAAA;EACA,oBAAA;CxCwxJD;AwCrxJC;EACE,cAAA;CxCuxJH;AwCnxJC;EACE,mBAAA;EACA,UAAA;CxCqxJH;AwClxJC;;EAEE,OAAA;EACA,iBAAA;CxCoxJH;AwC/wJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CxCixJL;AwC5wJC;;EAEE,eAAA;EACA,uBAAA;CxC8wJH;AwC3wJC;EACE,aAAA;CxC6wJH;AwC1wJC;EACE,kBAAA;CxC4wJH;AwCzwJC;EACE,iBAAA;CxC2wJH;AyCr0JD;EACE,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,eAAA;EACA,0BAAA;CzCu0JD;AyC50JD;;EASI,eAAA;CzCu0JH;AyCh1JD;EAaI,oBAAA;EACA,gBAAA;EACA,iBAAA;CzCs0JH;AyCr1JD;EAmBI,0BAAA;CzCq0JH;AyCl0JC;;EAEE,mBAAA;EACA,mBAAA;EACA,oBAAA;CzCo0JH;AyC91JD;EA8BI,gBAAA;CzCm0JH;AyCjzJD;EACA;IAfI,kBAAA;IACA,qBAAA;GzCm0JD;EyCj0JC;;IAEE,mBAAA;IACA,oBAAA;GzCm0JH;EyC1zJH;;IAJM,gBAAA;GzCk0JH;CACF;A0C/2JD;EACE,eAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;ErCiLA,4CAAA;EACK,uCAAA;EACG,oCAAA;CLisJT;A0C33JD;;EAaI,kBAAA;EACA,mBAAA;C1Ck3JH;A0C92JC;;;EAGE,sBAAA;C1Cg3JH;A0Cr4JD;EA0BI,aAAA;EACA,eAAA;C1C82JH;A2Cv4JD;EACE,cAAA;EACA,oBAAA;EACA,8BAAA;EACA,mBAAA;C3Cy4JD;A2C74JD;EAQI,cAAA;EAEA,eAAA;C3Cu4JH;A2Cj5JD;EAeI,kBAAA;C3Cq4JH;A2Cp5JD;;EAqBI,iBAAA;C3Cm4JH;A2Cx5JD;EAyBI,gBAAA;C3Ck4JH;A2C13JD;;EAEE,oBAAA;C3C43JD;A2C93JD;;EAMI,mBAAA;EACA,UAAA;EACA,aAAA;EACA,eAAA;C3C43JH;A2Cp3JD;ECvDE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C86JD;A2Cz3JD;EClDI,0BAAA;C5C86JH;A2C53JD;EC/CI,eAAA;C5C86JH;A2C33JD;EC3DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Cy7JD;A2Ch4JD;ECtDI,0BAAA;C5Cy7JH;A2Cn4JD;ECnDI,eAAA;C5Cy7JH;A2Cl4JD;EC/DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Co8JD;A2Cv4JD;EC1DI,0BAAA;C5Co8JH;A2C14JD;ECvDI,eAAA;C5Co8JH;A2Cz4JD;ECnEE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C+8JD;A2C94JD;EC9DI,0BAAA;C5C+8JH;A2Cj5JD;EC3DI,eAAA;C5C+8JH;A6Cj9JD;EACE;IAAQ,4BAAA;G7Co9JP;E6Cn9JD;IAAQ,yBAAA;G7Cs9JP;CACF;A6Cn9JD;EACE;IAAQ,4BAAA;G7Cs9JP;E6Cr9JD;IAAQ,yBAAA;G7Cw9JP;CACF;A6C39JD;EACE;IAAQ,4BAAA;G7Cs9JP;E6Cr9JD;IAAQ,yBAAA;G7Cw9JP;CACF;A6Cj9JD;EACE,iBAAA;EACA,aAAA;EACA,oBAAA;EACA,0BAAA;EACA,mBAAA;ExCsCA,uDAAA;EACQ,+CAAA;CL86JT;A6Ch9JD;EACE,YAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,mBAAA;EACA,0BAAA;ExCyBA,uDAAA;EACQ,+CAAA;EAyHR,oCAAA;EACK,+BAAA;EACG,4BAAA;CLk0JT;A6C78JD;;ECCI,8MAAA;EACA,yMAAA;EACA,sMAAA;EDAF,mCAAA;UAAA,2BAAA;C7Ci9JD;A6C18JD;;ExC5CE,2DAAA;EACK,sDAAA;EACG,mDAAA;CL0/JT;A6Cv8JD;EErEE,0BAAA;C/C+gKD;A+C5gKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C+9JH;A6C38JD;EEzEE,0BAAA;C/CuhKD;A+CphKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9Cu+JH;A6C/8JD;EE7EE,0BAAA;C/C+hKD;A+C5hKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C++JH;A6Cn9JD;EEjFE,0BAAA;C/CuiKD;A+CpiKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9Cu/JH;AgD/iKD;EAEE,iBAAA;ChDgjKD;AgD9iKC;EACE,cAAA;ChDgjKH;AgD5iKD;;EAEE,QAAA;EACA,iBAAA;ChD8iKD;AgD3iKD;EACE,eAAA;ChD6iKD;AgD1iKD;EACE,eAAA;ChD4iKD;AgDziKC;EACE,gBAAA;ChD2iKH;AgDviKD;;EAEE,mBAAA;ChDyiKD;AgDtiKD;;EAEE,oBAAA;ChDwiKD;AgDriKD;;;EAGE,oBAAA;EACA,oBAAA;ChDuiKD;AgDpiKD;EACE,uBAAA;ChDsiKD;AgDniKD;EACE,uBAAA;ChDqiKD;AgDjiKD;EACE,cAAA;EACA,mBAAA;ChDmiKD;AgD7hKD;EACE,gBAAA;EACA,iBAAA;ChD+hKD;AiDtlKD;EAEE,oBAAA;EACA,gBAAA;CjDulKD;AiD/kKD;EACE,mBAAA;EACA,eAAA;EACA,mBAAA;EAEA,oBAAA;EACA,uBAAA;EACA,uBAAA;CjDglKD;AiD7kKC;ErB3BA,6BAAA;EACC,4BAAA;C5B2mKF;AiD9kKC;EACE,iBAAA;ErBvBF,gCAAA;EACC,+BAAA;C5BwmKF;AiDvkKD;;EAEE,YAAA;CjDykKD;AiD3kKD;;EAKI,YAAA;CjD0kKH;AiDtkKC;;;;EAEE,sBAAA;EACA,YAAA;EACA,0BAAA;CjD0kKH;AiDtkKD;EACE,YAAA;EACA,iBAAA;CjDwkKD;AiDnkKC;;;EAGE,0BAAA;EACA,eAAA;EACA,oBAAA;CjDqkKH;AiD1kKC;;;EASI,eAAA;CjDskKL;AiD/kKC;;;EAYI,eAAA;CjDwkKL;AiDnkKC;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;CjDqkKH;AiD3kKC;;;;;;;;;EAYI,eAAA;CjD0kKL;AiDtlKC;;;EAeI,eAAA;CjD4kKL;AkD9qKC;EACE,eAAA;EACA,0BAAA;ClDgrKH;AkD9qKG;;EAEE,eAAA;ClDgrKL;AkDlrKG;;EAKI,eAAA;ClDirKP;AkD9qKK;;;;EAEE,eAAA;EACA,0BAAA;ClDkrKP;AkDhrKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDqrKP;AkD3sKC;EACE,eAAA;EACA,0BAAA;ClD6sKH;AkD3sKG;;EAEE,eAAA;ClD6sKL;AkD/sKG;;EAKI,eAAA;ClD8sKP;AkD3sKK;;;;EAEE,eAAA;EACA,0BAAA;ClD+sKP;AkD7sKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDktKP;AkDxuKC;EACE,eAAA;EACA,0BAAA;ClD0uKH;AkDxuKG;;EAEE,eAAA;ClD0uKL;AkD5uKG;;EAKI,eAAA;ClD2uKP;AkDxuKK;;;;EAEE,eAAA;EACA,0BAAA;ClD4uKP;AkD1uKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD+uKP;AkDrwKC;EACE,eAAA;EACA,0BAAA;ClDuwKH;AkDrwKG;;EAEE,eAAA;ClDuwKL;AkDzwKG;;EAKI,eAAA;ClDwwKP;AkDrwKK;;;;EAEE,eAAA;EACA,0BAAA;ClDywKP;AkDvwKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD4wKP;AiD3qKD;EACE,cAAA;EACA,mBAAA;CjD6qKD;AiD3qKD;EACE,iBAAA;EACA,iBAAA;CjD6qKD;AmDvyKD;EACE,oBAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;E9C0DA,kDAAA;EACQ,0CAAA;CLgvKT;AmDtyKD;EACE,cAAA;CnDwyKD;AmDnyKD;EACE,mBAAA;EACA,qCAAA;EvBpBA,6BAAA;EACC,4BAAA;C5B0zKF;AmDzyKD;EAMI,eAAA;CnDsyKH;AmDjyKD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;CnDmyKD;AmDvyKD;;;;;EAWI,eAAA;CnDmyKH;AmD9xKD;EACE,mBAAA;EACA,0BAAA;EACA,2BAAA;EvBxCA,gCAAA;EACC,+BAAA;C5By0KF;AmDxxKD;;EAGI,iBAAA;CnDyxKH;AmD5xKD;;EAMM,oBAAA;EACA,iBAAA;CnD0xKL;AmDtxKG;;EAEI,cAAA;EvBvEN,6BAAA;EACC,4BAAA;C5Bg2KF;AmDpxKG;;EAEI,iBAAA;EvBvEN,gCAAA;EACC,+BAAA;C5B81KF;AmD7yKD;EvB1DE,2BAAA;EACC,0BAAA;C5B02KF;AmDhxKD;EAEI,oBAAA;CnDixKH;AmD9wKD;EACE,oBAAA;CnDgxKD;AmDxwKD;;;EAII,iBAAA;CnDywKH;AmD7wKD;;;EAOM,mBAAA;EACA,oBAAA;CnD2wKL;AmDnxKD;;EvBzGE,6BAAA;EACC,4BAAA;C5Bg4KF;AmDxxKD;;;;EAmBQ,4BAAA;EACA,6BAAA;CnD2wKP;AmD/xKD;;;;;;;;EAwBU,4BAAA;CnDixKT;AmDzyKD;;;;;;;;EA4BU,6BAAA;CnDuxKT;AmDnzKD;;EvBjGE,gCAAA;EACC,+BAAA;C5Bw5KF;AmDxzKD;;;;EAyCQ,+BAAA;EACA,gCAAA;CnDqxKP;AmD/zKD;;;;;;;;EA8CU,+BAAA;CnD2xKT;AmDz0KD;;;;;;;;EAkDU,gCAAA;CnDiyKT;AmDn1KD;;;;EA2DI,2BAAA;CnD8xKH;AmDz1KD;;EA+DI,cAAA;CnD8xKH;AmD71KD;;EAmEI,UAAA;CnD8xKH;AmDj2KD;;;;;;;;;;;;EA0EU,eAAA;CnDqyKT;AmD/2KD;;;;;;;;;;;;EA8EU,gBAAA;CnD+yKT;AmD73KD;;;;;;;;EAuFU,iBAAA;CnDgzKT;AmDv4KD;;;;;;;;EAgGU,iBAAA;CnDizKT;AmDj5KD;EAsGI,UAAA;EACA,iBAAA;CnD8yKH;AmDpyKD;EACE,oBAAA;CnDsyKD;AmDvyKD;EAKI,iBAAA;EACA,mBAAA;CnDqyKH;AmD3yKD;EASM,gBAAA;CnDqyKL;AmD9yKD;EAcI,iBAAA;CnDmyKH;AmDjzKD;;EAkBM,2BAAA;CnDmyKL;AmDrzKD;EAuBI,cAAA;CnDiyKH;AmDxzKD;EAyBM,8BAAA;CnDkyKL;AmD3xKD;EC1PE,mBAAA;CpDwhLD;AoDthLC;EACE,eAAA;EACA,0BAAA;EACA,mBAAA;CpDwhLH;AoD3hLC;EAMI,uBAAA;CpDwhLL;AoD9hLC;EASI,eAAA;EACA,0BAAA;CpDwhLL;AoDrhLC;EAEI,0BAAA;CpDshLL;AmD1yKD;EC7PE,sBAAA;CpD0iLD;AoDxiLC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CpD0iLH;AoD7iLC;EAMI,0BAAA;CpD0iLL;AoDhjLC;EASI,eAAA;EACA,uBAAA;CpD0iLL;AoDviLC;EAEI,6BAAA;CpDwiLL;AmDzzKD;EChQE,sBAAA;CpD4jLD;AoD1jLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD4jLH;AoD/jLC;EAMI,0BAAA;CpD4jLL;AoDlkLC;EASI,eAAA;EACA,0BAAA;CpD4jLL;AoDzjLC;EAEI,6BAAA;CpD0jLL;AmDx0KD;ECnQE,sBAAA;CpD8kLD;AoD5kLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD8kLH;AoDjlLC;EAMI,0BAAA;CpD8kLL;AoDplLC;EASI,eAAA;EACA,0BAAA;CpD8kLL;AoD3kLC;EAEI,6BAAA;CpD4kLL;AmDv1KD;ECtQE,sBAAA;CpDgmLD;AoD9lLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDgmLH;AoDnmLC;EAMI,0BAAA;CpDgmLL;AoDtmLC;EASI,eAAA;EACA,0BAAA;CpDgmLL;AoD7lLC;EAEI,6BAAA;CpD8lLL;AmDt2KD;ECzQE,sBAAA;CpDknLD;AoDhnLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDknLH;AoDrnLC;EAMI,0BAAA;CpDknLL;AoDxnLC;EASI,eAAA;EACA,0BAAA;CpDknLL;AoD/mLC;EAEI,6BAAA;CpDgnLL;AqDhoLD;EACE,mBAAA;EACA,eAAA;EACA,UAAA;EACA,WAAA;EACA,iBAAA;CrDkoLD;AqDvoLD;;;;;EAYI,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,aAAA;EACA,YAAA;EACA,UAAA;CrDkoLH;AqD7nLD;EACE,uBAAA;CrD+nLD;AqD3nLD;EACE,oBAAA;CrD6nLD;AsDxpLD;EACE,iBAAA;EACA,cAAA;EACA,oBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EjDwDA,wDAAA;EACQ,gDAAA;CLmmLT;AsDlqLD;EASI,mBAAA;EACA,kCAAA;CtD4pLH;AsDvpLD;EACE,cAAA;EACA,mBAAA;CtDypLD;AsDvpLD;EACE,aAAA;EACA,mBAAA;CtDypLD;AuD/qLD;EACE,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,0BAAA;EjCRA,aAAA;EAGA,0BAAA;CtBwrLD;AuDhrLC;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;EjCfF,aAAA;EAGA,0BAAA;CtBgsLD;AuD5qLC;EACE,WAAA;EACA,gBAAA;EACA,wBAAA;EACA,UAAA;EACA,yBAAA;CvD8qLH;AwDnsLD;EACE,iBAAA;CxDqsLD;AwDjsLD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,kCAAA;EAIA,WAAA;CxDgsLD;AwD7rLC;EnD+GA,sCAAA;EACI,kCAAA;EACC,iCAAA;EACG,8BAAA;EAkER,oDAAA;EAEK,0CAAA;EACG,oCAAA;CLghLT;AwDnsLC;EnD2GA,mCAAA;EACI,+BAAA;EACC,8BAAA;EACG,2BAAA;CL2lLT;AwDvsLD;EACE,mBAAA;EACA,iBAAA;CxDysLD;AwDrsLD;EACE,mBAAA;EACA,YAAA;EACA,aAAA;CxDusLD;AwDnsLD;EACE,mBAAA;EACA,uBAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EnDaA,iDAAA;EACQ,yCAAA;EmDZR,qCAAA;UAAA,6BAAA;EAEA,WAAA;CxDqsLD;AwDjsLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,uBAAA;CxDmsLD;AwDjsLC;ElCrEA,WAAA;EAGA,yBAAA;CtBuwLD;AwDpsLC;ElCtEA,aAAA;EAGA,0BAAA;CtB2wLD;AwDnsLD;EACE,cAAA;EACA,iCAAA;CxDqsLD;AwDjsLD;EACE,iBAAA;CxDmsLD;AwD/rLD;EACE,UAAA;EACA,wBAAA;CxDisLD;AwD5rLD;EACE,mBAAA;EACA,cAAA;CxD8rLD;AwD1rLD;EACE,cAAA;EACA,kBAAA;EACA,8BAAA;CxD4rLD;AwD/rLD;EAQI,iBAAA;EACA,iBAAA;CxD0rLH;AwDnsLD;EAaI,kBAAA;CxDyrLH;AwDtsLD;EAiBI,eAAA;CxDwrLH;AwDnrLD;EACE,mBAAA;EACA,aAAA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;CxDqrLD;AwDnqLD;EAZE;IACE,aAAA;IACA,kBAAA;GxDkrLD;EwDhrLD;InDvEA,kDAAA;IACQ,0CAAA;GL0vLP;EwD/qLD;IAAY,aAAA;GxDkrLX;CACF;AwD7qLD;EAFE;IAAY,aAAA;GxDmrLX;CACF;AyDl0LD;EACE,mBAAA;EACA,cAAA;EACA,eAAA;ECRA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EDHA,gBAAA;EnCVA,WAAA;EAGA,yBAAA;CtBy1LD;AyD90LC;EnCdA,aAAA;EAGA,0BAAA;CtB61LD;AyDj1LC;EAAW,iBAAA;EAAmB,eAAA;CzDq1L/B;AyDp1LC;EAAW,iBAAA;EAAmB,eAAA;CzDw1L/B;AyDv1LC;EAAW,gBAAA;EAAmB,eAAA;CzD21L/B;AyD11LC;EAAW,kBAAA;EAAmB,eAAA;CzD81L/B;AyD11LD;EACE,iBAAA;EACA,iBAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,mBAAA;CzD41LD;AyDx1LD;EACE,mBAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;CzD01LD;AyDt1LC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;CzDw1LH;AyDt1LC;EACE,UAAA;EACA,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzDw1LH;AyDt1LC;EACE,UAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzDw1LH;AyDt1LC;EACE,SAAA;EACA,QAAA;EACA,iBAAA;EACA,4BAAA;EACA,yBAAA;CzDw1LH;AyDt1LC;EACE,SAAA;EACA,SAAA;EACA,iBAAA;EACA,4BAAA;EACA,wBAAA;CzDw1LH;AyDt1LC;EACE,OAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,0BAAA;CzDw1LH;AyDt1LC;EACE,OAAA;EACA,WAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzDw1LH;AyDt1LC;EACE,OAAA;EACA,UAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzDw1LH;A2Dr7LD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EDXA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;ECAA,gBAAA;EAEA,uBAAA;EACA,qCAAA;UAAA,6BAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EtD8CA,kDAAA;EACQ,0CAAA;CLq5LT;A2Dh8LC;EAAY,kBAAA;C3Dm8Lb;A2Dl8LC;EAAY,kBAAA;C3Dq8Lb;A2Dp8LC;EAAY,iBAAA;C3Du8Lb;A2Dt8LC;EAAY,mBAAA;C3Dy8Lb;A2Dt8LD;EACE,UAAA;EACA,kBAAA;EACA,gBAAA;EACA,0BAAA;EACA,iCAAA;EACA,2BAAA;C3Dw8LD;A2Dr8LD;EACE,kBAAA;C3Du8LD;A2D/7LC;;EAEE,mBAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;C3Di8LH;A2D97LD;EACE,mBAAA;C3Dg8LD;A2D97LD;EACE,mBAAA;EACA,YAAA;C3Dg8LD;A2D57LC;EACE,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;EACA,sCAAA;EACA,cAAA;C3D87LH;A2D77LG;EACE,aAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,uBAAA;C3D+7LL;A2D57LC;EACE,SAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,4BAAA;EACA,wCAAA;C3D87LH;A2D77LG;EACE,aAAA;EACA,UAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;C3D+7LL;A2D57LC;EACE,UAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;EACA,yCAAA;EACA,WAAA;C3D87LH;A2D77LG;EACE,aAAA;EACA,SAAA;EACA,mBAAA;EACA,oBAAA;EACA,0BAAA;C3D+7LL;A2D37LC;EACE,SAAA;EACA,aAAA;EACA,kBAAA;EACA,sBAAA;EACA,2BAAA;EACA,uCAAA;C3D67LH;A2D57LG;EACE,aAAA;EACA,WAAA;EACA,sBAAA;EACA,wBAAA;EACA,cAAA;C3D87LL;A4DvjMD;EACE,mBAAA;C5DyjMD;A4DtjMD;EACE,mBAAA;EACA,iBAAA;EACA,YAAA;C5DwjMD;A4D3jMD;EAMI,cAAA;EACA,mBAAA;EvD6KF,0CAAA;EACK,qCAAA;EACG,kCAAA;CL44LT;A4DlkMD;;EAcM,eAAA;C5DwjML;A4D9hMC;EA4NF;IvD3DE,uDAAA;IAEK,6CAAA;IACG,uCAAA;IA7JR,oCAAA;IAEQ,4BAAA;IA+GR,4BAAA;IAEQ,oBAAA;GLi7LP;E4D5jMG;;IvDmHJ,2CAAA;IACQ,mCAAA;IuDjHF,QAAA;G5D+jML;E4D7jMG;;IvD8GJ,4CAAA;IACQ,oCAAA;IuD5GF,QAAA;G5DgkML;E4D9jMG;;;IvDyGJ,wCAAA;IACQ,gCAAA;IuDtGF,QAAA;G5DikML;CACF;A4DvmMD;;;EA6CI,eAAA;C5D+jMH;A4D5mMD;EAiDI,QAAA;C5D8jMH;A4D/mMD;;EAsDI,mBAAA;EACA,OAAA;EACA,YAAA;C5D6jMH;A4DrnMD;EA4DI,WAAA;C5D4jMH;A4DxnMD;EA+DI,YAAA;C5D4jMH;A4D3nMD;;EAmEI,QAAA;C5D4jMH;A4D/nMD;EAuEI,YAAA;C5D2jMH;A4DloMD;EA0EI,WAAA;C5D2jMH;A4DnjMD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EtC9FA,aAAA;EAGA,0BAAA;EsC6FA,gBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;EACA,mCAAA;C5DsjMD;A4DjjMC;EdnGE,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9CupMH;A4DrjMC;EACE,WAAA;EACA,SAAA;EdxGA,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9CgqMH;A4DvjMC;;EAEE,WAAA;EACA,YAAA;EACA,sBAAA;EtCvHF,aAAA;EAGA,0BAAA;CtB+qMD;A4DzlMD;;;;EAuCI,mBAAA;EACA,SAAA;EACA,kBAAA;EACA,WAAA;EACA,sBAAA;C5DwjMH;A4DnmMD;;EA+CI,UAAA;EACA,mBAAA;C5DwjMH;A4DxmMD;;EAoDI,WAAA;EACA,oBAAA;C5DwjMH;A4D7mMD;;EAyDI,YAAA;EACA,aAAA;EACA,eAAA;EACA,mBAAA;C5DwjMH;A4DnjMG;EACE,iBAAA;C5DqjML;A4DjjMG;EACE,iBAAA;C5DmjML;A4DziMD;EACE,mBAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;C5D2iMD;A4DpjMD;EAYI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;EAWA,0BAAA;EACA,mCAAA;C5DiiMH;A4DhkMD;EAkCI,UAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;C5DiiMH;A4D1hMD;EACE,mBAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;C5D4hMD;A4D3hMC;EACE,kBAAA;C5D6hMH;A4Dp/LD;EAhCE;;;;IAKI,YAAA;IACA,aAAA;IACA,kBAAA;IACA,gBAAA;G5DshMH;E4D9hMD;;IAYI,mBAAA;G5DshMH;E4DliMD;;IAgBI,oBAAA;G5DshMH;E4DjhMD;IACE,UAAA;IACA,WAAA;IACA,qBAAA;G5DmhMD;E4D/gMD;IACE,aAAA;G5DihMD;CACF;A6DhxMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,aAAA;EACA,eAAA;C7DgzMH;A6D9yMC;;;;;;;;;;;;;;;;EACE,YAAA;C7D+zMH;AiCv0MD;E6BRE,eAAA;EACA,kBAAA;EACA,mBAAA;C9Dk1MD;AiCz0MD;EACE,wBAAA;CjC20MD;AiCz0MD;EACE,uBAAA;CjC20MD;AiCn0MD;EACE,yBAAA;CjCq0MD;AiCn0MD;EACE,0BAAA;CjCq0MD;AiCn0MD;EACE,mBAAA;CjCq0MD;AiCn0MD;E8BzBE,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,8BAAA;EACA,UAAA;C/D+1MD;AiCj0MD;EACE,yBAAA;CjCm0MD;AiC5zMD;EACE,gBAAA;CjC8zMD;AgE/1MD;EACE,oBAAA;ChEi2MD;AgE31MD;;;;ECdE,yBAAA;CjE+2MD;AgE11MD;;;;;;;;;;;;EAYE,yBAAA;ChE41MD;AgEr1MD;EA6IA;IC7LE,0BAAA;GjEy4MC;EiEx4MD;IAAU,0BAAA;GjE24MT;EiE14MD;IAAU,8BAAA;GjE64MT;EiE54MD;;IACU,+BAAA;GjE+4MT;CACF;AgE/1MD;EAwIA;IA1II,0BAAA;GhEq2MD;CACF;AgE/1MD;EAmIA;IArII,2BAAA;GhEq2MD;CACF;AgE/1MD;EA8HA;IAhII,iCAAA;GhEq2MD;CACF;AgE91MD;EAwHA;IC7LE,0BAAA;GjEu6MC;EiEt6MD;IAAU,0BAAA;GjEy6MT;EiEx6MD;IAAU,8BAAA;GjE26MT;EiE16MD;;IACU,+BAAA;GjE66MT;CACF;AgEx2MD;EAmHA;IArHI,0BAAA;GhE82MD;CACF;AgEx2MD;EA8GA;IAhHI,2BAAA;GhE82MD;CACF;AgEx2MD;EAyGA;IA3GI,iCAAA;GhE82MD;CACF;AgEv2MD;EAmGA;IC7LE,0BAAA;GjEq8MC;EiEp8MD;IAAU,0BAAA;GjEu8MT;EiEt8MD;IAAU,8BAAA;GjEy8MT;EiEx8MD;;IACU,+BAAA;GjE28MT;CACF;AgEj3MD;EA8FA;IAhGI,0BAAA;GhEu3MD;CACF;AgEj3MD;EAyFA;IA3FI,2BAAA;GhEu3MD;CACF;AgEj3MD;EAoFA;IAtFI,iCAAA;GhEu3MD;CACF;AgEh3MD;EA8EA;IC7LE,0BAAA;GjEm+MC;EiEl+MD;IAAU,0BAAA;GjEq+MT;EiEp+MD;IAAU,8BAAA;GjEu+MT;EiEt+MD;;IACU,+BAAA;GjEy+MT;CACF;AgE13MD;EAyEA;IA3EI,0BAAA;GhEg4MD;CACF;AgE13MD;EAoEA;IAtEI,2BAAA;GhEg4MD;CACF;AgE13MD;EA+DA;IAjEI,iCAAA;GhEg4MD;CACF;AgEz3MD;EAyDA;ICrLE,yBAAA;GjEy/MC;CACF;AgEz3MD;EAoDA;ICrLE,yBAAA;GjE8/MC;CACF;AgEz3MD;EA+CA;ICrLE,yBAAA;GjEmgNC;CACF;AgEz3MD;EA0CA;ICrLE,yBAAA;GjEwgNC;CACF;AgEt3MD;ECnJE,yBAAA;CjE4gND;AgEn3MD;EA4BA;IC7LE,0BAAA;GjEwhNC;EiEvhND;IAAU,0BAAA;GjE0hNT;EiEzhND;IAAU,8BAAA;GjE4hNT;EiE3hND;;IACU,+BAAA;GjE8hNT;CACF;AgEj4MD;EACE,yBAAA;ChEm4MD;AgE93MD;EAqBA;IAvBI,0BAAA;GhEo4MD;CACF;AgEl4MD;EACE,yBAAA;ChEo4MD;AgE/3MD;EAcA;IAhBI,2BAAA;GhEq4MD;CACF;AgEn4MD;EACE,yBAAA;ChEq4MD;AgEh4MD;EAOA;IATI,iCAAA;GhEs4MD;CACF;AgE/3MD;EACA;ICrLE,yBAAA;GjEujNC;CACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.6 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n \n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on