From: Yan, Zheng Date: Mon, 25 Apr 2016 02:50:17 +0000 (+0800) Subject: client: record 'offset' for each entry of dir_result_t::buffer X-Git-Tag: v10.2.2~8^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a65b3ef30123e5d9d3199cf2f5dafd7d9ab8a755;p=ceph.git client: record 'offset' for each entry of dir_result_t::buffer This is preparation for using hash value as dentry 'offset' Signed-off-by: Yan, Zheng (cherry picked from commit bd6546e5e8bfb4ef8927807492d63d5285534618) Signed-off-by: Greg Farnum buffer_frag = fg; - dirp->this_offset = readdir_offset; _readdir_drop_dirp_buffer(dirp); dirp->buffer.reserve(numdn); @@ -1167,7 +1166,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session, dn->offset = dir_result_t::make_fpos(fg, readdir_offset++); // add to cached result list - dirp->buffer.push_back(pair(dname, in)); + dirp->buffer.push_back(dir_result_t::dentry(dn->offset, dname, in)); ldout(cct, 15) << __func__ << " " << hex << dn->offset << dec << ": '" << dname << "' -> " << in->ino << dendl; } @@ -6961,8 +6960,7 @@ int Client::_readdir_get_frag(dir_result_t *dirp) if (res == 0) { ldout(cct, 10) << "_readdir_get_frag " << dirp << " got frag " << dirp->buffer_frag - << " this_offset " << dirp->this_offset - << " size " << dirp->buffer.size() << dendl; + << " size " << dirp->buffer.size() << dendl; } else { ldout(cct, 10) << "_readdir_get_frag got error " << res << ", setting end flag" << dendl; dirp->set_end(); @@ -7020,13 +7018,14 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p) struct stat st; struct dirent de; int stmask = fill_stat(dn->inode, &st); - fill_dirent(&de, dn->name.c_str(), st.st_mode, st.st_ino, dirp->offset + 1); - + uint64_t next_off = dn->offset + 1; ++pd; if (pd.end()) next_off = dir_result_t::END; + fill_dirent(&de, dn->name.c_str(), st.st_mode, st.st_ino, next_off); + dn_name = dn->name; // fill in name while we have lock client_lock.Unlock(); @@ -7036,11 +7035,14 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p) << " = " << r << dendl; if (r < 0) { - dirp->next_offset = next_off - 1; return r; } - dirp->next_offset = dirp->offset = next_off; + dirp->offset = next_off; + if (dirp->at_end()) + dirp->next_offset = 2; + else + dirp->next_offset = dirp->fragpos(); dirp->at_cache_name = dn_name; // we successfully returned this one; update! if (r > 0) return r; @@ -7068,7 +7070,6 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p) memset(&st, 0, sizeof(st)); frag_t fg = dirp->frag(); - uint32_t off = dirp->fragpos(); InodeRef& diri = dirp->inode; @@ -7090,31 +7091,30 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p) return r; dirp->offset = next_off; - off = next_off; if (r > 0) return r; } if (dirp->offset == 1) { ldout(cct, 15) << " including .." << dendl; + uint64_t next_off = 2; if (!diri->dn_set.empty()) { InodeRef& in = diri->get_first_parent()->inode; fill_stat(in, &st); - fill_dirent(&de, "..", S_IFDIR, st.st_ino, 2); + fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off); } else { /* must be at the root (no parent), * so we add the dotdot with a special inode (3) */ - fill_dirent(&de, "..", S_IFDIR, CEPH_INO_DOTDOT, 2); + fill_dirent(&de, "..", S_IFDIR, CEPH_INO_DOTDOT, next_off); } client_lock.Unlock(); - int r = cb(p, &de, &st, -1, 2); + int r = cb(p, &de, &st, -1, next_off); client_lock.Lock(); if (r < 0) return r; - dirp->offset = 2; - off = 2; + dirp->offset = next_off; if (r > 0) return r; } @@ -7149,30 +7149,31 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p) // _readdir_get_frag () may updates dirp->offset if the replied dirfrag is // different than the requested one. (our dirfragtree was outdated) fg = dirp->buffer_frag; - off = dirp->fragpos(); } - ldout(cct, 10) << "off " << off << " this_offset " << hex << dirp->this_offset << dec << " size " << dirp->buffer.size() - << " frag " << fg << dendl; + ldout(cct, 10) << "frag " << fg << " buffer size " << dirp->buffer.size() + << " offset " << hex << dirp->offset << dendl; - while (off >= dirp->this_offset && - off - dirp->this_offset < dirp->buffer.size()) { - pair& ent = dirp->buffer[off - dirp->this_offset]; + for (auto it = std::lower_bound(dirp->buffer.begin(), dirp->buffer.end(), + dirp->offset, dir_result_t::dentry_off_lt()); + it != dirp->buffer.end(); + ++it) { + dir_result_t::dentry &entry = *it; + + uint64_t next_off = entry.offset + 1; + int stmask = fill_stat(entry.inode, &st); + fill_dirent(&de, entry.name.c_str(), st.st_mode, st.st_ino, next_off); - int stmask = fill_stat(ent.second, &st); - fill_dirent(&de, ent.first.c_str(), st.st_mode, st.st_ino, dirp->offset + 1); - client_lock.Unlock(); - int r = cb(p, &de, &st, stmask, dirp->offset + 1); // _next_ offset + int r = cb(p, &de, &st, stmask, next_off); // _next_ offset client_lock.Lock(); - ldout(cct, 15) << " de " << de.d_name << " off " << hex << dirp->offset << dec - << " = " << r - << dendl; + + ldout(cct, 15) << " de " << de.d_name << " off " << hex << next_off - 1 << dec + << " = " << r << dendl; if (r < 0) return r; - - off++; - dirp->offset++; + + dirp->offset = next_off; if (r > 0) return r; } @@ -7188,7 +7189,6 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p) _readdir_next_frag(dirp); ldout(cct, 10) << " advancing to next frag: " << fg << " -> " << dirp->frag() << dendl; fg = dirp->frag(); - off = 0; continue; } diff --git a/src/client/Client.h b/src/client/Client.h index b03e770cda28..df8ed79aa11b 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -188,8 +188,7 @@ struct dir_result_t { int64_t offset; // high bits: frag_t, low bits: an offset - uint64_t this_offset; // offset of last chunk, adjusted for . and .. - uint64_t next_offset; // offset of next chunk (last_name's + 1) + unsigned next_offset; // offset of next chunk (last_name's + 1) string last_name; // last entry in previous chunk uint64_t release_count; @@ -197,7 +196,21 @@ struct dir_result_t { int start_shared_gen; // dir shared_gen at start of readdir frag_t buffer_frag; - vector > buffer; + + struct dentry { + int64_t offset; + string name; + InodeRef inode; + dentry(int64_t o) : offset(o) {} + dentry(int64_t o, const string& n, const InodeRef& in) : + offset(o), name(n), inode(in) {} + }; + struct dentry_off_lt { + bool operator()(const dentry& d, int64_t off) const { + return dir_result_t::fpos_cmp(d.offset, off) < 0; + } + }; + vector buffer; string at_cache_name; // last entry we successfully returned @@ -224,7 +237,6 @@ struct dir_result_t { last_name.clear(); at_cache_name.clear(); next_offset = 2; - this_offset = 0; offset = 0; buffer.clear(); } diff --git a/src/client/Dentry.h b/src/client/Dentry.h index 198b375ce098..192ef01a80b4 100644 --- a/src/client/Dentry.h +++ b/src/client/Dentry.h @@ -17,7 +17,7 @@ class Dentry : public LRUObject { Dir *dir; InodeRef inode; int ref; // 1 if there's a dir beneath me. - uint64_t offset; + int64_t offset; mds_rank_t lease_mds; utime_t lease_ttl; uint64_t lease_gen;