]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "librbd/api/Image.h" | |
5 | #include "include/rados/librados.hpp" | |
6 | #include "common/dout.h" | |
7 | #include "common/errno.h" | |
8 | #include "cls/rbd/cls_rbd_client.h" | |
9 | #include "librbd/ImageCtx.h" | |
10 | #include "librbd/ImageState.h" | |
11 | ||
12 | #define dout_subsys ceph_subsys_rbd | |
13 | #undef dout_prefix | |
14 | #define dout_prefix *_dout << "librbd::api::Image: " << __func__ << ": " | |
15 | ||
16 | namespace librbd { | |
17 | namespace api { | |
18 | ||
19 | template <typename I> | |
20 | int Image<I>::list_images(librados::IoCtx& io_ctx, ImageNameToIds *images) { | |
21 | CephContext *cct = (CephContext *)io_ctx.cct(); | |
22 | ldout(cct, 20) << "io_ctx=" << &io_ctx << dendl; | |
23 | ||
24 | // new format images are accessed by class methods | |
25 | int r; | |
26 | int max_read = 1024; | |
27 | string last_read = ""; | |
28 | do { | |
29 | map<string, string> images_page; | |
30 | r = cls_client::dir_list(&io_ctx, RBD_DIRECTORY, | |
31 | last_read, max_read, &images_page); | |
32 | if (r < 0 && r != -ENOENT) { | |
33 | lderr(cct) << "error listing image in directory: " | |
34 | << cpp_strerror(r) << dendl; | |
35 | return r; | |
36 | } else if (r == -ENOENT) { | |
37 | break; | |
38 | } | |
39 | for (map<string, string>::const_iterator it = images_page.begin(); | |
40 | it != images_page.end(); ++it) { | |
41 | images->insert(*it); | |
42 | } | |
43 | if (!images_page.empty()) { | |
44 | last_read = images_page.rbegin()->first; | |
45 | } | |
46 | r = images_page.size(); | |
47 | } while (r == max_read); | |
48 | ||
49 | return 0; | |
50 | } | |
51 | ||
52 | template <typename I> | |
53 | int Image<I>::list_children(I *ictx, const ParentSpec &parent_spec, | |
54 | PoolImageIds *pool_image_ids) | |
55 | { | |
56 | CephContext *cct = ictx->cct; | |
7c673cae FG |
57 | |
58 | // no children for non-layered or old format image | |
59 | if (!ictx->test_features(RBD_FEATURE_LAYERING, ictx->snap_lock)) { | |
60 | return 0; | |
61 | } | |
62 | ||
63 | pool_image_ids->clear(); | |
64 | // search all pools for children depending on this snapshot | |
65 | librados::Rados rados(ictx->md_ctx); | |
66 | std::list<std::pair<int64_t, std::string> > pools; | |
b32b8144 | 67 | int r = rados.pool_list2(pools); |
7c673cae FG |
68 | if (r < 0) { |
69 | lderr(cct) << "error listing pools: " << cpp_strerror(r) << dendl; | |
70 | return r; | |
71 | } | |
72 | ||
73 | for (auto it = pools.begin(); it != pools.end(); ++it) { | |
74 | int64_t base_tier; | |
75 | r = rados.pool_get_base_tier(it->first, &base_tier); | |
76 | if (r == -ENOENT) { | |
77 | ldout(cct, 1) << "pool " << it->second << " no longer exists" << dendl; | |
78 | continue; | |
79 | } else if (r < 0) { | |
80 | lderr(cct) << "error retrieving base tier for pool " << it->second | |
81 | << dendl; | |
82 | return r; | |
83 | } | |
84 | if (it->first != base_tier) { | |
85 | // pool is a cache; skip it | |
86 | continue; | |
87 | } | |
88 | ||
89 | IoCtx ioctx; | |
90 | r = rados.ioctx_create2(it->first, ioctx); | |
91 | if (r == -ENOENT) { | |
92 | ldout(cct, 1) << "pool " << it->second << " no longer exists" << dendl; | |
93 | continue; | |
94 | } else if (r < 0) { | |
95 | lderr(cct) << "error accessing child image pool " << it->second | |
96 | << dendl; | |
97 | return r; | |
98 | } | |
99 | ||
100 | set<string> image_ids; | |
101 | r = cls_client::get_children(&ioctx, RBD_CHILDREN, parent_spec, | |
102 | image_ids); | |
103 | if (r < 0 && r != -ENOENT) { | |
104 | lderr(cct) << "error reading list of children from pool " << it->second | |
105 | << dendl; | |
106 | return r; | |
107 | } | |
108 | pool_image_ids->insert({*it, image_ids}); | |
109 | } | |
110 | ||
111 | return 0; | |
112 | } | |
113 | ||
114 | } // namespace api | |
115 | } // namespace librbd | |
116 | ||
117 | template class librbd::api::Image<librbd::ImageCtx>; |