]>
git.proxmox.com Git - ceph.git/blob - ceph/src/mds/ScrubStack.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014 Red Hat
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
21 #include "MDSContext.h"
22 #include "ScrubHeader.h"
24 #include "common/LogClient.h"
25 #include "include/elist.h"
26 #include "messages/MMDSScrub.h"
27 #include "messages/MMDSScrubStats.h"
34 ScrubStack(MDCache
*mdc
, LogChannelRef
&clog
, Finisher
*finisher_
) :
38 scrub_stack(member_offset(MDSCacheObject
, item_scrub
)),
39 scrub_waiting(member_offset(MDSCacheObject
, item_scrub
)) {}
41 ceph_assert(scrub_stack
.empty());
42 ceph_assert(!scrubs_in_progress
);
45 * Put the inode at either the top or bottom of the stack, with the
46 * given scrub params, and kick off more scrubbing.
47 * @param in The inode to scrub
48 * @param header The ScrubHeader propagated from wherever this scrub
50 int enqueue(CInode
*in
, ScrubHeaderRef
& header
, bool top
);
52 * Abort an ongoing scrub operation. The abort operation could be
53 * delayed if there are in-progress scrub operations on going. The
54 * caller should provide a context which is completed after all
55 * in-progress scrub operations are completed and pending inodes
56 * are removed from the scrub stack (with the context callbacks for
57 * inodes completed with -CEPHFS_ECANCELED).
58 * @param on_finish Context callback to invoke after abort
60 void scrub_abort(Context
*on_finish
);
63 * Pause scrub operations. Similar to abort, pause is delayed if
64 * there are in-progress scrub operations on going. The caller
65 * should provide a context which is completed after all in-progress
66 * scrub operations are completed. Subsequent scrub operations are
67 * queued until scrub is resumed.
68 * @param on_finish Context callback to invoke after pause
70 void scrub_pause(Context
*on_finish
);
73 * Resume a paused scrub. Unlike abort or pause, this is instantaneous.
74 * Pending pause operations are cancelled (context callbacks are
75 * invoked with -CEPHFS_ECANCELED).
76 * @returns 0 (success) if resumed, -CEPHFS_EINVAL if an abort is in-progress.
81 * Get the current scrub status as human readable string. Some basic
82 * information is returned such as number of inodes pending abort/pause.
84 void scrub_status(Formatter
*f
);
87 * Get a high level scrub status summary such as current scrub state
90 std::string_view
scrub_summary();
92 static bool is_idle(std::string_view state_str
) {
93 return state_str
== "idle";
96 bool is_scrubbing() const { return !scrub_stack
.empty(); }
98 void advance_scrub_status();
100 void handle_mds_failure(mds_rank_t mds
);
102 void dispatch(const cref_t
<Message
> &m
);
104 bool remove_inode_if_stacked(CInode
*in
);
110 // reference to global cluster log client
113 /// A finisher needed so that we don't re-enter kick_off_scrubs
116 /// The stack of inodes we want to scrub
117 elist
<MDSCacheObject
*> scrub_stack
;
118 elist
<MDSCacheObject
*> scrub_waiting
;
119 /// current number of dentries we're actually scrubbing
120 int scrubs_in_progress
= 0;
123 struct scrub_remote_t
{
125 std::set
<mds_rank_t
> gather_set
;
127 std::map
<CInode
*, scrub_remote_t
> remote_scrubs
;
129 unsigned scrub_epoch
= 2;
130 unsigned scrub_epoch_fully_acked
= 0;
131 unsigned scrub_epoch_last_abort
= 2;
132 // check if any mds is aborting scrub after mds.0 starts
133 bool scrub_any_peer_aborting
= true;
135 struct scrub_stat_t
{
136 unsigned epoch_acked
= 0;
137 std::set
<std::string
> scrubbing_tags
;
138 bool aborting
= false;
140 std::vector
<scrub_stat_t
> mds_scrub_stats
;
142 std::map
<std::string
, ScrubHeaderRef
> scrubbing_map
;
144 friend class C_RetryScrub
;
146 // scrub abort is _not_ a state, rather it's an operation that's
147 // performed after in-progress scrubs are finished.
154 friend std::ostream
&operator<<(std::ostream
&os
, const State
&state
);
156 friend class C_InodeValidated
;
158 int _enqueue(MDSCacheObject
*obj
, ScrubHeaderRef
& header
, bool top
);
160 * Remove the inode/dirfrag from the stack.
162 inline void dequeue(MDSCacheObject
*obj
);
165 * Kick off as many scrubs as are appropriate, based on the current
166 * state of the stack.
168 void kick_off_scrubs();
171 * Move the inode/dirfrag that can't be scrubbed immediately
172 * from scrub queue to waiting list.
174 void add_to_waiting(MDSCacheObject
*obj
);
176 * Move the inode/dirfrag back to scrub queue.
178 void remove_from_waiting(MDSCacheObject
*obj
, bool kick
=true);
180 * Validate authority of the inode. If current mds is not auth of the inode,
181 * forword scrub to auth mds.
183 bool validate_inode_auth(CInode
*in
);
186 * Scrub a file inode.
187 * @param in The inode to scrub
189 void scrub_file_inode(CInode
*in
);
192 * Callback from completion of CInode::validate_disk_state
193 * @param in The inode we were validating
194 * @param r The return status from validate_disk_state
195 * @param result Populated results from validate_disk_state
197 void _validate_inode_done(CInode
*in
, int r
,
198 const CInode::validated_data
&result
);
201 * Scrub a directory inode. It queues child dirfrags, then does
202 * final scrub of the inode.
204 * @param in The directory indoe to scrub
205 * @param added_children set to true if we pushed some of our children
206 * @param done set to true if we started to do final scrub
208 void scrub_dir_inode(CInode
*in
, bool *added_children
, bool *done
);
210 * Scrub a dirfrag. It queues child dentries, then does final
211 * scrub of the dirfrag.
213 * @param dir The dirfrag to scrub (must be auth)
214 * @param done set to true if we started to do final scrub
216 void scrub_dirfrag(CDir
*dir
, bool *done
);
218 * Scrub a directory-representing dentry.
220 * @param in The directory inode we're doing final scrub on.
222 void scrub_dir_inode_final(CInode
*in
);
225 * @param next_state State to move the scrub to.
227 void set_state(State next_state
);
230 * Is scrub in one of transition states (running, pausing)
232 bool scrub_in_transition_state();
235 * complete queued up contexts
236 * @param r return value to complete contexts.
238 void complete_control_contexts(int r
);
241 * ask peer mds (rank > 0) to abort/pause/resume scrubs
243 void send_state_message(int op
);
246 * Abort pending scrubs for inodes waiting in the inode stack.
247 * Completion context is complete with -CEPHFS_ECANCELED.
249 void abort_pending_scrubs();
252 * Return path for a given inode.
253 * @param in inode to make path entry.
255 std::string
scrub_inode_path(CInode
*in
) {
257 in
->make_path_string(path
, true);
258 return (path
.empty() ? "/" : path
.c_str());
262 * Send scrub information (queued/finished scrub path and summary)
264 * @param in inode for which scrub has been queued or finished.
266 void clog_scrub_summary(CInode
*in
=nullptr);
268 void handle_scrub(const cref_t
<MMDSScrub
> &m
);
269 void handle_scrub_stats(const cref_t
<MMDSScrubStats
> &m
);
271 State state
= STATE_IDLE
;
272 bool clear_stack
= false;
274 // list of pending context completions for asynchronous scrub
275 // control operations.
276 std::vector
<Context
*> control_ctxs
;
279 #endif /* SCRUBSTACK_H_ */