From: Xiubo Li Date: Mon, 13 Dec 2021 04:45:40 +0000 (+0800) Subject: client: move dirty_list to MetaSession X-Git-Tag: v17.1.0~153^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F44255%2Fhead;p=ceph.git client: move dirty_list to MetaSession Then we can easily use the last dirty cap to flush the mdlog. This will be useful when syncing the whole filesystem. The delayed_list will hold both dirty and release caps. The dirty caps will be checked by the dirty_list in each session and it makes no sense to flush the release caps when syncing the filesystem. Fixes: https://tracker.ceph.com/issues/44916 Signed-off-by: Xiubo Li --- diff --git a/src/client/Client.cc b/src/client/Client.cc index dd18cb51d48b..1f20eedf60da 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4652,35 +4652,25 @@ void Client::adjust_session_flushing_caps(Inode *in, MetaSession *old_s, MetaSe } /* - * Flush all caps back to the MDS. Because the callers generally wait on the - * result of this function (syncfs and umount cases), we set - * CHECK_CAPS_SYNCHRONOUS on the last check_caps call. + * Flush all the dirty caps back to the MDS. Because the callers + * generally wait on the result of this function (syncfs and umount + * cases), we set CHECK_CAPS_SYNCHRONOUS on the last check_caps call. */ void Client::flush_caps_sync() { ldout(cct, 10) << __func__ << dendl; - xlist::iterator p = delayed_list.begin(); - while (!p.end()) { - unsigned flags = CHECK_CAPS_NODELAY; - Inode *in = *p; - - ++p; - delayed_list.pop_front(); - if (p.end() && dirty_list.empty()) - flags |= CHECK_CAPS_SYNCHRONOUS; - check_caps(in, flags); - } - - // other caps, too - p = dirty_list.begin(); - while (!p.end()) { - unsigned flags = CHECK_CAPS_NODELAY; - Inode *in = *p; + for (auto &q : mds_sessions) { + auto s = q.second; + xlist::iterator p = s->dirty_list.begin(); + while (!p.end()) { + unsigned flags = CHECK_CAPS_NODELAY; + Inode *in = *p; - ++p; - if (p.end()) - flags |= CHECK_CAPS_SYNCHRONOUS; - check_caps(in, flags); + ++p; + if (p.end()) + flags |= CHECK_CAPS_SYNCHRONOUS; + check_caps(in, flags); + } } } @@ -6455,13 +6445,16 @@ void Client::_unmount(bool abort) } if (abort || blocklisted) { - for (auto p = dirty_list.begin(); !p.end(); ) { - Inode *in = *p; - ++p; - if (in->dirty_caps) { - ldout(cct, 0) << " drop dirty caps on " << *in << dendl; - in->mark_caps_clean(); - put_inode(in); + for (auto &q : mds_sessions) { + auto s = q.second; + for (auto p = s->dirty_list.begin(); !p.end(); ) { + Inode *in = *p; + ++p; + if (in->dirty_caps) { + ldout(cct, 0) << " drop dirty caps on " << *in << dendl; + in->mark_caps_clean(); + put_inode(in); + } } } } else { diff --git a/src/client/Client.h b/src/client/Client.h index c6ba9bbf1bd4..d7139983ef5e 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -875,8 +875,6 @@ public: return std::make_pair(opened_inodes, inode_map.size()); } - xlist &get_dirty_list() { return dirty_list; } - /* timer_lock for 'timer' */ ceph::mutex timer_lock = ceph::make_mutex("Client::timer_lock"); SafeTimer timer; @@ -1530,8 +1528,7 @@ private: // cap flushing ceph_tid_t last_flush_tid = 1; - // dirty_list keeps all the dirty inodes before flushing. - xlist delayed_list, dirty_list; + xlist delayed_list; int num_flushing_caps = 0; ceph::unordered_map snap_realms; std::map metadata; diff --git a/src/client/Inode.cc b/src/client/Inode.cc index 0b3200bb0fa0..5c1523f2f427 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -777,12 +777,26 @@ void Inode::unset_deleg(Fh *fh) */ void Inode::mark_caps_dirty(int caps) { + /* + * If auth_cap is nullptr means the reonnecting is not finished or + * already rejected. + */ + if (!auth_cap) { + ceph_assert(!dirty_caps); + + lsubdout(client->cct, client, 1) << __func__ << " " << *this << " dirty caps '" << ccap_string(caps) + << "', but no auth cap." << dendl; + return; + } + lsubdout(client->cct, client, 10) << __func__ << " " << *this << " " << ccap_string(dirty_caps) << " -> " << ccap_string(dirty_caps | caps) << dendl; + if (caps && !caps_dirty()) iget(); + dirty_caps |= caps; - client->get_dirty_list().push_back(&dirty_cap_item); + auth_cap->session->get_dirty_list().push_back(&dirty_cap_item); client->cap_delay_requeue(this); } diff --git a/src/client/MetaSession.h b/src/client/MetaSession.h index cfeb26a471c9..4eae49b9d69a 100644 --- a/src/client/MetaSession.h +++ b/src/client/MetaSession.h @@ -49,6 +49,8 @@ struct MetaSession { std::list waiting_for_open; xlist caps; + // dirty_list keeps all the dirty inodes before flushing in current session. + xlist dirty_list; xlist flushing_caps; xlist requests; xlist unsafe_requests; @@ -60,6 +62,8 @@ struct MetaSession { : mds_num(mds_num), con(con), addrs(addrs) { } + xlist &get_dirty_list() { return dirty_list; } + const char *get_state_name() const; void dump(Formatter *f, bool cap_dump=false) const;