Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mds / InoTable.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
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.
12  * 
13  */
14
15 #include "InoTable.h"
16 #include "MDSRank.h"
17
18 #include "include/types.h"
19
20 #include "common/config.h"
21
22 #define dout_context g_ceph_context
23 #define dout_subsys ceph_subsys_mds
24 #undef dout_prefix
25 #define dout_prefix *_dout << "mds." << rank << "." << table_name << ": "
26
27 void InoTable::reset_state()
28 {
29   // use generic range. FIXME THIS IS CRAP
30   free.clear();
31   //#ifdef __LP64__
32   uint64_t start = (uint64_t)(rank+1) << 40;
33   uint64_t len = (uint64_t)1 << 40;
34   //#else
35   //# warning this looks like a 32-bit system, using small inode numbers.
36   //  uint64_t start = (uint64_t)(mds->get_nodeid()+1) << 25;
37   //  uint64_t end = ((uint64_t)(mds->get_nodeid()+2) << 25) - 1;
38   //#endif
39   free.insert(start, len);
40
41   projected_free = free;
42 }
43
44 inodeno_t InoTable::project_alloc_id(inodeno_t id) 
45 {
46   dout(10) << "project_alloc_id " << id << " to " << projected_free << "/" << free << dendl;
47   assert(is_active());
48   if (!id)
49     id = projected_free.range_start();
50   projected_free.erase(id);
51   ++projected_version;
52   return id;
53 }
54 void InoTable::apply_alloc_id(inodeno_t id)
55 {
56   dout(10) << "apply_alloc_id " << id << " to " << projected_free << "/" << free << dendl;
57   free.erase(id);
58   ++version;
59 }
60
61 void InoTable::project_alloc_ids(interval_set<inodeno_t>& ids, int want) 
62 {
63   assert(is_active());
64   while (want > 0) {
65     inodeno_t start = projected_free.range_start();
66     inodeno_t end = projected_free.end_after(start);
67     inodeno_t num = end - start;
68     if (num > (inodeno_t)want)
69       num = want;
70     projected_free.erase(start, num);
71     ids.insert(start, num);
72     want -= num;
73   }
74   dout(10) << "project_alloc_ids " << ids << " to " << projected_free << "/" << free << dendl;
75   ++projected_version;
76 }
77 void InoTable::apply_alloc_ids(interval_set<inodeno_t>& ids)
78 {
79   dout(10) << "apply_alloc_ids " << ids << " to " << projected_free << "/" << free << dendl;
80   free.subtract(ids);
81   ++version;
82 }
83
84
85 void InoTable::project_release_ids(interval_set<inodeno_t>& ids) 
86 {
87   dout(10) << "project_release_ids " << ids << " to " << projected_free << "/" << free << dendl;
88   projected_free.insert(ids);
89   ++projected_version;
90 }
91 void InoTable::apply_release_ids(interval_set<inodeno_t>& ids) 
92 {
93   dout(10) << "apply_release_ids " << ids << " to " << projected_free << "/" << free << dendl;
94   free.insert(ids);
95   ++version;
96 }
97
98
99 //
100
101 void InoTable::replay_alloc_id(inodeno_t id) 
102 {
103   assert(mds);  // Only usable in online mode
104
105   dout(10) << "replay_alloc_id " << id << dendl;
106   if (free.contains(id)) {
107     free.erase(id);
108     projected_free.erase(id);
109   } else {
110     mds->clog->error() << "journal replay alloc " << id
111       << " not in free " << free;
112   }
113   projected_version = ++version;
114 }
115 void InoTable::replay_alloc_ids(interval_set<inodeno_t>& ids) 
116 {
117   assert(mds);  // Only usable in online mode
118
119   dout(10) << "replay_alloc_ids " << ids << dendl;
120   interval_set<inodeno_t> is;
121   is.intersection_of(free, ids);
122   if (is == ids) {
123     free.subtract(ids);
124     projected_free.subtract(ids);
125   } else {
126     mds->clog->error() << "journal replay alloc " << ids << ", only "
127         << is << " is in free " << free;
128     free.subtract(is);
129     projected_free.subtract(is);
130   }
131   projected_version = ++version;
132 }
133 void InoTable::replay_release_ids(interval_set<inodeno_t>& ids) 
134 {
135   dout(10) << "replay_release_ids " << ids << dendl;
136   free.insert(ids);
137   projected_free.insert(ids);
138   projected_version = ++version;
139 }
140
141
142 void InoTable::replay_reset()
143 {
144   dout(10) << "replay_reset " << free << dendl;
145   skip_inos(inodeno_t(10000000));  // a lot!
146   projected_free = free;
147   projected_version = ++version;
148 }
149
150
151 void InoTable::skip_inos(inodeno_t i)
152 {
153   dout(10) << "skip_inos was " << free << dendl;
154   inodeno_t first = free.range_start();
155   interval_set<inodeno_t> s;
156   s.insert(first, i);
157   s.intersection_of(free);
158   free.subtract(s);
159   projected_free = free;
160   projected_version = ++version;
161   dout(10) << "skip_inos now " << free << dendl;
162 }
163
164 void InoTable::dump(Formatter *f) const
165 {
166   f->open_object_section("inotable");
167
168   f->open_array_section("projected_free");
169   for (interval_set<inodeno_t>::const_iterator i = projected_free.begin(); i != projected_free.end(); ++i) {
170     f->open_object_section("range");
171     f->dump_int("start", (*i).first);
172     f->dump_int("len", (*i).second);
173     f->close_section();
174   }
175   f->close_section();
176
177   f->open_array_section("free");
178   for (interval_set<inodeno_t>::const_iterator i = free.begin(); i != free.end(); ++i) {
179     f->open_object_section("range");
180     f->dump_int("start", (*i).first);
181     f->dump_int("len", (*i).second);
182     f->close_section();
183   }
184   f->close_section();
185
186   f->close_section();
187 }
188
189
190 void InoTable::generate_test_instances(list<InoTable*>& ls)
191 {
192   ls.push_back(new InoTable());
193 }
194
195
196 bool InoTable::is_marked_free(inodeno_t id) const
197 {
198   return free.contains(id) || projected_free.contains(id);
199 }
200
201 bool InoTable::intersects_free(
202     const interval_set<inodeno_t> &other,
203     interval_set<inodeno_t> *intersection)
204 {
205   interval_set<inodeno_t> i;
206   i.intersection_of(free, other);
207   if (intersection != nullptr) {
208     *intersection = i;
209   }
210   return !(i.empty());
211 }
212
213 bool InoTable::repair(inodeno_t id)
214 {
215   if (projected_version != version) {
216     // Can't do the repair while other things are in flight
217     return false;
218   }
219
220   assert(is_marked_free(id));
221   dout(10) << "repair: before status. ino = 0x" << std::hex << id << " pver =" << projected_version << " ver= " << version << dendl;
222   free.erase(id);
223   projected_free.erase(id);
224   projected_version = ++version;
225   dout(10) << "repair: after status. ino = 0x" << std::hex <<id << " pver =" << projected_version << " ver= " << version << dendl;
226   return true;
227 }