ceph_assert(session->is_closing() || session->is_killing() ||
session->is_opening()); // re-open closing session
session->info.prealloc_inos.subtract(inos);
+ session->delegated_inos.clear();
mds->inotable->apply_release_ids(inos);
ceph_assert(mds->inotable->get_version() == piv);
}
bool allow_prealloc_inos = mdr->session->is_open();
// assign ino
- if (allow_prealloc_inos &&
- mdr->session->info.prealloc_inos.size()) {
+ if (allow_prealloc_inos && mdr->session->get_num_prealloc_inos()) {
mdr->used_prealloc_ino =
in->inode.ino = mdr->session->take_ino(useino); // prealloc -> used
mds->sessionmap.mark_projected(mdr->session);
<< " state " << p->second->get_state_name()
<< " completed " << p->second->info.completed_requests
<< " prealloc_inos " << p->second->info.prealloc_inos
+ << " delegated_inos " << p->second->delegated_inos
<< " used_inos " << p->second->info.used_inos
<< dendl;
}
p != session_map.end();
++p) {
p->second->pending_prealloc_inos.clear();
+ p->second->delegated_inos.clear();
p->second->info.prealloc_inos.clear();
p->second->info.used_inos.clear();
}
ceph_assert(!info.prealloc_inos.empty());
if (ino) {
- if (info.prealloc_inos.contains(ino))
+ if (info.prealloc_inos.contains(ino)) {
info.prealloc_inos.erase(ino);
- else
+ if (delegated_inos.contains(ino))
+ delegated_inos.erase(ino);
+ } else {
ino = 0;
+ }
}
if (!ino) {
- ino = info.prealloc_inos.range_start();
- info.prealloc_inos.erase(ino);
+ /* Grab first prealloc_ino that isn't delegated */
+ for (const auto& [start, len] : info.prealloc_inos) {
+ for (auto i = start ; i < start + len ; i += 1) {
+ inodeno_t dstart, dlen;
+ if (!delegated_inos.contains(i, &dstart, &dlen)) {
+ ino = i;
+ info.prealloc_inos.erase(ino);
+ break;
+ }
+ /* skip to end of delegated interval */
+ i = dstart + dlen - 1;
+ }
+ if (ino)
+ break;
+ }
}
+ ceph_assert(ino);
info.used_inos.insert(ino, 1);
return ino;
}
+ void delegate_inos(int want, interval_set<inodeno_t>& newinos) {
+ want -= (int)delegated_inos.size();
+ if (want <= 0)
+ return;
+
+ for (const auto& [start, len] : info.prealloc_inos) {
+ for (auto i = start ; i < start + len ; i += 1) {
+ inodeno_t dstart, dlen;
+ if (!delegated_inos.contains(i, &dstart, &dlen)) {
+ delegated_inos.insert(i);
+ newinos.insert(i);
+ if (--want == 0)
+ return;
+ } else {
+ /* skip to end of delegated interval */
+ i = dstart + dlen - 1;
+ }
+ }
+ }
+ }
+
+ // sans any delegated ones
+ int get_num_prealloc_inos() const {
+ return info.prealloc_inos.size() - delegated_inos.size();
+ }
+
int get_num_projected_prealloc_inos() const {
- return info.prealloc_inos.size() + pending_prealloc_inos.size();
+ return get_num_prealloc_inos() + pending_prealloc_inos.size();
}
client_t get_client() const {
void clear() {
pending_prealloc_inos.clear();
+ delegated_inos.clear();
info.clear_meta();
cap_push_seq = 0;
mutable elist<MDRequestImpl*> requests;
interval_set<inodeno_t> pending_prealloc_inos; // journaling prealloc, will be added to prealloc_inos
+ interval_set<inodeno_t> delegated_inos; // hand these out to client
xlist<Capability*> caps; // inodes with caps; front=most recently used
xlist<ClientLease*> leases; // metadata leases to clients