Merge PR #19825 into master

* refs/pull/19825/head:
	client: properly choose target mds for rmsnap/renamesnap
	mds: properly setup need_snapflush for snapped inode
	mds: ignore MClientCaps::FLAG_NO_CAPSNAP

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
Patrick Donnelly 2018-01-30 15:18:01 -08:00
commit 90687e499c
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
3 changed files with 36 additions and 36 deletions

View File

@ -3296,9 +3296,7 @@ void Client::send_cap(Inode *in, MetaSession *session, Cap *cap,
m->change_attr = in->change_attr;
if (sync)
m->flags |= MClientCaps::FLAG_SYNC;
if (in->cap_snaps.empty())
m->flags |= MClientCaps::FLAG_NO_CAPSNAP;
else
if (!in->cap_snaps.empty())
m->flags |= MClientCaps::FLAG_PENDING_CAPSNAP;
if (flush & CEPH_CAP_FILE_WR) {
@ -11991,6 +11989,7 @@ int Client::_rmdir(Inode *dir, const char *name, const UserPerm& perms)
dir->make_nosnap_relative_path(path);
path.push_dentry(name);
req->set_filepath(path);
req->set_inode(dir);
req->dentry_drop = CEPH_CAP_FILE_SHARED;
req->dentry_unless = CEPH_CAP_FILE_EXCL;
@ -12010,14 +12009,12 @@ int Client::_rmdir(Inode *dir, const char *name, const UserPerm& perms)
res = _lookup(dir, name, 0, &in, perms);
if (res < 0)
goto fail;
if (op == CEPH_MDS_OP_RMDIR) {
req->set_inode(dir);
req->set_other_inode(in.get());
} else {
if (op == CEPH_MDS_OP_RMSNAP) {
unlink(de, true, true);
de->put();
req->set_other_inode(in.get());
}
req->set_other_inode(in.get());
res = make_request(req, perms);
@ -12144,6 +12141,8 @@ int Client::_rename(Inode *fromdir, const char *fromname, Inode *todir, const ch
// dentry manually
unlink(oldde, true, true);
unlink(de, true, true);
req->set_inode(todir);
}
res = make_request(req, perm, &target);

View File

@ -2868,36 +2868,13 @@ void Locker::handle_client_caps(MClientCaps *m)
caps &= cap->issued();
}
cap->confirm_receipt(m->get_seq(), caps);
dout(10) << " follows " << follows
<< " retains " << ccap_string(m->get_caps())
<< " dirty " << ccap_string(m->get_dirty())
<< " on " << *in << dendl;
// missing/skipped snapflush?
// The client MAY send a snapflush if it is issued WR/EXCL caps, but
// presently only does so when it has actual dirty metadata. But, we
// set up the need_snapflush stuff based on the issued caps.
// We can infer that the client WONT send a FLUSHSNAP once they have
// released all WR/EXCL caps (the FLUSHSNAP always comes before the cap
// update/release).
if (!head_in->client_need_snapflush.empty()) {
if ((m->flags & MClientCaps::FLAG_NO_CAPSNAP) ||
(!(cap->issued() & CEPH_CAP_ANY_FILE_WR) &&
!(m->flags & MClientCaps::FLAG_PENDING_CAPSNAP))) {
head_in->auth_pin(this); // prevent subtree frozen
need_unpin = true;
_do_null_snapflush(head_in, client);
} else {
dout(10) << " revocation in progress, not making any conclusions about null snapflushes" << dendl;
}
}
if (cap->need_snapflush() && (m->flags & MClientCaps::FLAG_NO_CAPSNAP))
cap->clear_needsnapflush();
if (m->get_dirty() && in->is_auth()) {
dout(7) << " flush client." << client << " dirty " << ccap_string(m->get_dirty())
dout(7) << " flush client." << client << " dirty " << ccap_string(m->get_dirty())
<< " seq " << m->get_seq() << " on " << *in << dendl;
ack = new MClientCaps(CEPH_CAP_OP_FLUSH_ACK, in->ino(), 0, cap->get_cap_id(), m->get_seq(),
m->get_caps(), 0, m->get_dirty(), 0, mds->get_osd_epoch_barrier());
@ -2905,8 +2882,33 @@ void Locker::handle_client_caps(MClientCaps *m)
ack->set_oldest_flush_tid(m->get_oldest_flush_tid());
}
// filter wanted based on what we could ever give out (given auth/replica status)
bool need_flush = m->flags & MClientCaps::FLAG_SYNC;
bool updated = in->is_auth() &&
_do_cap_update(in, cap, m->get_dirty(), follows, m, ack, &need_flush);
cap->confirm_receipt(m->get_seq(), caps);
// missing/skipped snapflush?
// The client MAY send a snapflush if it is issued WR/EXCL caps,
// but only does so when it has actual dirty metadata. We set up
// the need_snapflush stuff based on the issued caps. We can infer
// that the client WONT send a FLUSHSNAP once they have released
// all WR/EXCL caps (the FLUSHSNAP always comes before the cap
// update/release).
if (!head_in->client_need_snapflush.empty()) {
if (!(cap->issued() & CEPH_CAP_ANY_FILE_WR) &&
!(m->flags & MClientCaps::FLAG_PENDING_CAPSNAP)) {
head_in->auth_pin(this); // prevent subtree frozen
need_unpin = true;
_do_null_snapflush(head_in, client);
} else {
dout(10) << " revocation in progress, not making any conclusions about null snapflushes" << dendl;
}
}
if (cap->need_snapflush() && !(m->flags & MClientCaps::FLAG_PENDING_CAPSNAP))
cap->clear_needsnapflush();
// filter wanted based on what we could ever give out (given auth/replica status)
int new_wanted = m->get_wanted() & head_in->get_caps_allowed_ever();
if (new_wanted != cap->wanted()) {
if (!need_flush && (new_wanted & ~cap->pending())) {
@ -2917,8 +2919,7 @@ void Locker::handle_client_caps(MClientCaps *m)
adjust_cap_wanted(cap, new_wanted, m->get_issue_seq());
}
if (in->is_auth() &&
_do_cap_update(in, cap, m->get_dirty(), follows, m, ack, &need_flush)) {
if (updated) {
// updated
eval(in, CEPH_CAP_LOCKS);

View File

@ -24,7 +24,7 @@ class MClientCaps : public Message {
public:
static const unsigned FLAG_SYNC = (1<<0);
static const unsigned FLAG_NO_CAPSNAP = (1<<1);
static const unsigned FLAG_NO_CAPSNAP = (1<<1); // unused
static const unsigned FLAG_PENDING_CAPSNAP = (1<<2);
struct ceph_mds_caps_head head;