From: Greg Farnum Date: Wed, 3 Aug 2016 20:06:05 +0000 (-0700) Subject: client: replace Inode's "best" logic with a UserPerm over gid/uid pair X-Git-Tag: v11.0.1~36^2~28 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fa76047910a9e500df63bb6f01c48a7d58f12858;p=ceph.git client: replace Inode's "best" logic with a UserPerm over gid/uid pair Signed-off-by: Greg Farnum --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 7b0c3d8e80b0..5726e371e550 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -814,7 +814,7 @@ void Client::_fragmap_remove_non_leaves(Inode *in) Inode * Client::add_update_inode(InodeStat *st, utime_t from, MetaSession *session, - uid_t request_uid, gid_t request_gid) + const UserPerm& request_perms) { Inode *in; bool was_new = false; @@ -913,7 +913,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, if (in->snapid == CEPH_NOSNAP) { add_update_cap(in, session, st->cap.cap_id, st->cap.caps, st->cap.seq, st->cap.mseq, inodeno_t(st->cap.realm), st->cap.flags, - request_uid, request_gid); + request_perms); if (in->auth_cap && in->auth_cap->session == session) in->max_size = st->max_size; } else @@ -1148,7 +1148,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session, ldout(cct, 15) << "" << i << ": '" << dname << "'" << dendl; Inode *in = add_update_inode(&ist, request->sent_stamp, session, - request->get_uid(), request->get_gid()); + request->perms); Dentry *dn; if (diri->dir->dentries.count(dname)) { Dentry *olddn = diri->dir->dentries[dname]; @@ -1304,13 +1304,13 @@ Inode* Client::insert_trace(MetaRequest *request, MetaSession *session) } in = add_update_inode(&ist, request->sent_stamp, session, - request->get_uid(), request->get_gid()); + request->perms); } Inode *diri = NULL; if (reply->head.is_dentry) { diri = add_update_inode(&dirst, request->sent_stamp, session, - request->get_uid(), request->get_gid()); + request->perms); update_dir_dist(diri, &dst); // dir stat info is attached to .. if (in) { @@ -3741,7 +3741,7 @@ void Client::check_cap_issue(Inode *in, Cap *cap, unsigned issued) void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id, unsigned issued, unsigned seq, unsigned mseq, inodeno_t realm, - int flags, uid_t cap_uid, gid_t cap_gid) + int flags, const UserPerm& cap_perms) { Cap *cap = 0; mds_rank_t mds = mds_session->mds_num; @@ -3803,8 +3803,7 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id cap->seq = seq; cap->issue_seq = seq; cap->mseq = mseq; - cap->latest_uid = cap_uid; - cap->latest_gid = cap_gid; + cap->latest_perms = cap_perms; ldout(cct, 10) << "add_update_cap issued " << ccap_string(old_caps) << " -> " << ccap_string(cap->issued) << " from mds." << mds << " on " << *in @@ -4581,13 +4580,11 @@ void Client::handle_cap_import(MetaSession *session, Inode *in, MClientCaps *m) const mds_rank_t peer_mds = mds_rank_t(m->peer.mds); Cap *cap = NULL; - uid_t cap_uid = -1; - gid_t cap_gid = -1; + UserPerm cap_perms; if (m->peer.cap_id && in->caps.count(peer_mds)) { cap = in->caps[peer_mds]; if (cap) { - cap_uid = cap->latest_uid; - cap_gid = cap->latest_gid; + cap_perms = cap->latest_perms; } } @@ -4595,7 +4592,7 @@ void Client::handle_cap_import(MetaSession *session, Inode *in, MClientCaps *m) update_snap_trace(m->snapbl); add_update_cap(in, session, m->get_cap_id(), m->get_caps(), m->get_seq(), m->get_mseq(), m->get_realm(), - CEPH_CAP_FLAG_AUTH, cap_uid, cap_gid); + CEPH_CAP_FLAG_AUTH, cap_perms); if (cap && cap->cap_id == m->peer.cap_id) { remove_cap(cap, (m->peer.flags & CEPH_CAP_FLAG_RELEASE)); @@ -4645,7 +4642,7 @@ void Client::handle_cap_export(MetaSession *session, Inode *in, MClientCaps *m) add_update_cap(in, tsession, m->peer.cap_id, cap->issued, m->peer.seq - 1, m->peer.mseq, (uint64_t)-1, cap == in->auth_cap ? CEPH_CAP_FLAG_AUTH : 0, - cap->latest_uid, cap->latest_gid); + cap->latest_perms); } } else { if (cap == in->auth_cap) @@ -7864,7 +7861,11 @@ int Client::_renew_caps(Inode *in) req->head.args.open.mask = 0; req->set_inode(in); - UserPerm perms(in->get_best_cap_uid(), in->get_best_cap_gid()); + // duplicate in case Cap goes away; not sure if that race is a concern? + const UserPerm *pperm = in->get_best_perms(); + UserPerm perms; + if (pperm != NULL) + perms = *pperm; int ret = make_request(req, perms); return ret; } diff --git a/src/client/Client.h b/src/client/Client.h index a479d29be94f..df25eb978cef 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -620,7 +620,7 @@ protected: void check_cap_issue(Inode *in, Cap *cap, unsigned issued); void add_update_cap(Inode *in, MetaSession *session, uint64_t cap_id, unsigned issued, unsigned seq, unsigned mseq, inodeno_t realm, - int flags, uid_t cap_uid, gid_t cap_gid); + int flags, const UserPerm& perms); void remove_cap(Cap *cap, bool queue_release); void remove_all_caps(Inode *in); void remove_session_caps(MetaSession *session); @@ -705,7 +705,7 @@ protected: version_t inline_version, bufferlist& inline_data, int issued); Inode *add_update_inode(InodeStat *st, utime_t ttl, MetaSession *session, - uid_t request_uid, gid_t request_gid); + const UserPerm& request_perms); Dentry *insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dlease, Inode *in, utime_t from, MetaSession *session, Dentry *old_dentry = NULL); diff --git a/src/client/Inode.cc b/src/client/Inode.cc index de59869e943b..06e111c19b3f 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -288,26 +288,25 @@ int Inode::caps_dirty() return dirty_caps | flushing_caps; } -uid_t Inode::get_best_cap_uid() +const UserPerm* Inode::get_best_perms() { - uid_t any = -1; + const UserPerm *perms = NULL; for (const auto ci : caps) { - if (ci.second->latest_uid == uid) - return uid; - any = ci.second->latest_uid; - } - return any; -} - -gid_t Inode::get_best_cap_gid() -{ - gid_t any = -1; - for (const auto ci : caps) { - if (ci.second->latest_gid == uid) - return uid; - any = ci.second->latest_gid; + const UserPerm& iperm = ci.second->latest_perms; + if (!perms) { // we don't have any, take what's present + perms = &iperm; + } else if (iperm.uid() == uid) { + if (iperm.gid() == gid) { // we have the best possible, return + return &iperm; + } + if (perms->uid() != uid) { // take uid > gid every time + perms = &iperm; + } + } else if (perms->uid() != uid && iperm.gid() == gid) { + perms = &iperm; // a matching gid is better than nothing + } } - return any; + return perms; } bool Inode::have_valid_size() diff --git a/src/client/Inode.h b/src/client/Inode.h index 5115f6a794dd..2c74b8b1e641 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -13,6 +13,7 @@ #include "include/assert.h" #include "InodeRef.h" +#include "UserPerm.h" class Client; struct MetaSession; @@ -37,12 +38,11 @@ struct Cap { uint64_t seq, issue_seq; __u32 mseq; // migration seq __u32 gen; - uid_t latest_uid; - gid_t latest_gid; + UserPerm latest_perms; Cap() : session(NULL), inode(NULL), cap_item(this), cap_id(0), issued(0), implemented(0), wanted(0), seq(0), issue_seq(0), mseq(0), gen(0), - latest_uid(-1), latest_gid(-1) {} + latest_perms() {} void dump(Formatter *f) const; }; @@ -279,8 +279,7 @@ struct Inode { int caps_wanted(); int caps_mds_wanted(); int caps_dirty(); - uid_t get_best_cap_uid(); - gid_t get_best_cap_gid(); + const UserPerm *get_best_perms(); bool have_valid_size(); Dir *open_dir();