1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 Red Hat
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "common/errno.h"
16 #include "osdc/Striper.h"
21 #define dout_context g_ceph_context
22 #define dout_subsys ceph_subsys_mds
24 #define dout_prefix *_dout << "pgeffects." << __func__ << ": "
28 int r = ceph_create_with_context(&cmount, g_ceph_context);
33 return ceph_init(cmount);
36 PgFiles::PgFiles(Objecter *o, std::set<pg_t> pgs_)
37 : objecter(o), pgs(pgs_)
39 for (const auto &i : pgs) {
40 pools.insert(i.m_pool);
49 void PgFiles::hit_dir(std::string const &path)
51 dout(10) << "entering " << path << dendl;
53 ceph_dir_result *dr = nullptr;
54 int r = ceph_opendir(cmount, path.c_str(), &dr);
56 derr << "Failed to open path: " << cpp_strerror(r) << dendl;
61 while((r = ceph_readdir_r(cmount, dr, &de)) != 0) {
63 derr << "Error reading path " << path << ": " << cpp_strerror(r)
65 ceph_closedir(cmount, dr); // best effort, ignore r
69 if (std::string(de.d_name) == "." || std::string(de.d_name) == "..") {
73 struct ceph_statx stx;
74 std::string de_path = (path + std::string("/") + de.d_name);
75 r = ceph_statx(cmount, de_path.c_str(), &stx,
76 CEPH_STATX_INO|CEPH_STATX_SIZE, 0);
78 derr << "Failed to stat path " << de_path << ": "
79 << cpp_strerror(r) << dendl;
80 // Don't hold up the whole process for one bad inode
84 if (S_ISREG(stx.stx_mode)) {
85 hit_file(de_path, stx);
86 } else if (S_ISDIR(stx.stx_mode)) {
89 dout(20) << "Skipping non reg/dir file: " << de_path << dendl;
93 r = ceph_closedir(cmount, dr);
95 derr << "Error closing path " << path << ": " << cpp_strerror(r) << dendl;
100 void PgFiles::hit_file(std::string const &path, const struct ceph_statx &stx)
102 assert(S_ISREG(stx.stx_mode));
104 dout(20) << "Hitting file '" << path << "'" << dendl;
106 int l_stripe_unit = 0;
107 int l_stripe_count = 0;
108 int l_object_size = 0;
110 int r = ceph_get_path_layout(cmount, path.c_str(), &l_stripe_unit,
111 &l_stripe_count, &l_object_size,
114 derr << "Error reading layout on " << path << ": " << cpp_strerror(r)
119 struct file_layout_t layout;
120 layout.stripe_unit = l_stripe_unit;
121 layout.stripe_count = l_stripe_count;
122 layout.object_size = l_object_size;
123 layout.pool_id = l_pool_id;
125 // Avoid calculating PG if the layout targeted a completely different pool
126 if (pools.count(layout.pool_id) == 0) {
127 dout(20) << "Fast check missed: pool " << layout.pool_id << " not in "
128 "target set" << dendl;
132 auto num_objects = Striper::get_num_objects(layout, stx.stx_size);
134 for (uint64_t i = 0; i < num_objects; ++i) {
136 snprintf(buf, sizeof(buf), "%llx.%08llx", (long long unsigned)stx.stx_ino,
137 (long long unsigned int)i);
138 dout(20) << " object " << std::string(buf) << dendl;
142 object_locator_t loc;
143 loc.pool = layout.pool_id;
144 loc.key = std::string(buf);
146 unsigned pg_num_mask = 0;
150 objecter->with_osdmap([&r, oid, loc, &target, &pg_num_mask, &pg_num]
151 (const OSDMap &osd_map) {
152 r = osd_map.object_locator_to_pg(oid, loc, target);
154 auto pool = osd_map.get_pg_pool(loc.pool);
155 pg_num_mask = pool->get_pg_num_mask();
156 pg_num = pool->get_pg_num();
160 // Can happen if layout pointed to pool not in osdmap, for example
164 target.m_seed = ceph_stable_mod(target.ps(), pg_num, pg_num_mask);
166 dout(20) << " target " << target << dendl;
168 if (pgs.count(target)) {
169 std::cout << path << std::endl;
176 int PgFiles::scan_path(std::string const &path)
178 int r = ceph_mount(cmount, "/");
180 derr << "Failed to mount: " << cpp_strerror(r) << dendl;
186 r = ceph_unmount(cmount);
188 derr << "Failed to unmount: " << cpp_strerror(r) << dendl;