From f180ad149ab510626fcd6cbd8221f550f9858126 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 11 Jul 2016 11:07:01 +0800 Subject: [PATCH] client: invalidate snap inodes after removing snapshot Signed-off-by: Yan, Zheng --- src/client/Client.cc | 44 ++++++++++++++++++++++++++++---------------- src/client/Client.h | 2 +- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 5ee8aedcce55..fae1fecea3af 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1779,8 +1779,10 @@ void Client::put_request(MetaRequest *request) if (other_in) { if (other_in->dir && - (op == CEPH_MDS_OP_RMDIR || op == CEPH_MDS_OP_RENAME)) - _try_to_trim_inode(other_in.get()); + (op == CEPH_MDS_OP_RMDIR || + op == CEPH_MDS_OP_RENAME || + op == CEPH_MDS_OP_RMSNAP)) + _try_to_trim_inode(other_in.get(), false); } } } @@ -4797,7 +4799,7 @@ void Client::_schedule_invalidate_dentry_callback(Dentry *dn, bool del) async_dentry_invalidator.queue(new C_Client_DentryInvalidate(this, dn, del)); } -void Client::_try_to_trim_inode(Inode *in) +void Client::_try_to_trim_inode(Inode *in, bool sched_inval) { int ref = in->get_num_ref(); @@ -4806,22 +4808,31 @@ void Client::_try_to_trim_inode(Inode *in) p != in->dir->dentries.end(); ) { Dentry *dn = p->second; ++p; + /* rmsnap removes whole subtree, need trim inodes recursively. + * we don't need to invalidate dentries recursively. because + * invalidating a directory dentry effectively invalidate + * whole subtree */ + if (in->snapid != CEPH_NOSNAP && dn->inode && dn->inode->is_dir()) + _try_to_trim_inode(dn->inode.get(), false); + if (dn->lru_is_expireable()) - unlink(dn, false, false); // close dir, drop dentry + unlink(dn, true, false); // keep dir, drop dentry + } + if (in->dir->dentries.empty()) { + close_dir(in->dir); + --ref; } - --ref; } - // make sure inode was not freed when closing dir - if (ref == 0) - return; - set::iterator q = in->dn_set.begin(); - while (q != in->dn_set.end()) { - Dentry *dn = *q++; - // FIXME: we play lots of unlink/link tricks when handling MDS replies, - // so in->dn_set doesn't always reflect the state of kernel's dcache. - _schedule_invalidate_dentry_callback(dn, true); - unlink(dn, true, true); + if (ref > 0 && in->ll_ref > 0 && sched_inval) { + set::iterator q = in->dn_set.begin(); + while (q != in->dn_set.end()) { + Dentry *dn = *q++; + // FIXME: we play lots of unlink/link tricks when handling MDS replies, + // so in->dn_set doesn't always reflect the state of kernel's dcache. + _schedule_invalidate_dentry_callback(dn, true); + unlink(dn, true, true); + } } } @@ -4932,7 +4943,7 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient // may drop inode's last ref if (deleted_inode) - _try_to_trim_inode(in); + _try_to_trim_inode(in, true); m->put(); } @@ -10905,6 +10916,7 @@ int Client::_rmdir(Inode *dir, const char *name, int uid, int gid) req->set_other_inode(in.get()); } else { unlink(de, true, true); + req->set_other_inode(in.get()); } res = make_request(req, uid, gid); diff --git a/src/client/Client.h b/src/client/Client.h index 075b841f2fa1..775cfdcd4f58 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -657,7 +657,7 @@ protected: void _schedule_invalidate_dentry_callback(Dentry *dn, bool del); void _async_dentry_invalidate(vinodeno_t dirino, vinodeno_t ino, string& name); - void _try_to_trim_inode(Inode *in); + void _try_to_trim_inode(Inode *in, bool sched_inval); void _schedule_invalidate_callback(Inode *in, int64_t off, int64_t len); void _invalidate_inode_cache(Inode *in); -- 2.47.3