Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2014 Red Hat
7  *
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.
12  *
13  */
14
15 #ifndef SCRUBSTACK_H_
16 #define SCRUBSTACK_H_
17
18 #include "CDir.h"
19 #include "CDentry.h"
20 #include "CInode.h"
21 #include "MDSContext.h"
22 #include "ScrubHeader.h"
23
24 #include "include/elist.h"
25
26 class MDCache;
27 class Finisher;
28
29 class ScrubStack {
30 protected:
31   /// A finisher needed so that we don't re-enter kick_off_scrubs
32   Finisher *finisher;
33
34   /// The stack of dentries we want to scrub
35   elist<CInode*> inode_stack;
36   /// current number of dentries we're actually scrubbing
37   int scrubs_in_progress;
38   ScrubStack *scrubstack; // hack for dout
39   int stack_size;
40
41   class C_KickOffScrubs : public MDSInternalContext {
42     ScrubStack *stack;
43   public:
44     C_KickOffScrubs(MDCache *mdcache, ScrubStack *s);
45     void finish(int r) override { }
46     void complete(int r) override {
47       stack->scrubs_in_progress--;
48       stack->kick_off_scrubs();
49       // don't delete self
50     }
51   };
52   C_KickOffScrubs scrub_kick;
53
54 public:
55   MDCache *mdcache;
56   ScrubStack(MDCache *mdc, Finisher *finisher_) :
57     finisher(finisher_),
58     inode_stack(member_offset(CInode, item_scrub)),
59     scrubs_in_progress(0),
60     scrubstack(this),
61     stack_size(0),
62     scrub_kick(mdc, this),
63     mdcache(mdc) {}
64   ~ScrubStack() {
65     assert(inode_stack.empty());
66     assert(!scrubs_in_progress);
67   }
68   /**
69    * Put a inode on the top of the scrub stack, so it is the highest priority.
70    * If there are other scrubs in progress, they will not continue scrubbing new
71    * entries until this one is completed.
72    * @param in The inodey to scrub
73    * @param header The ScrubHeader propagated from whereever this scrub
74    *               was initiated
75    */
76   void enqueue_inode_top(CInode *in, const ScrubHeaderRefConst& header,
77                          MDSInternalContextBase *on_finish) {
78     enqueue_inode(in, header, on_finish, true);
79   }
80   /** Like enqueue_inode_top, but we wait for all pending scrubs before
81    * starting this one.
82    */
83   void enqueue_inode_bottom(CInode *in, const ScrubHeaderRefConst& header,
84                             MDSInternalContextBase *on_finish) {
85     enqueue_inode(in, header, on_finish, false);
86   }
87
88 private:
89   /**
90    * Put the inode at either the top or bottom of the stack, with
91    * the given scrub params, and then try and kick off more scrubbing.
92    */
93   void enqueue_inode(CInode *in, const ScrubHeaderRefConst& header,
94                       MDSInternalContextBase *on_finish, bool top);
95   void _enqueue_inode(CInode *in, CDentry *parent, const ScrubHeaderRefConst& header,
96                       MDSInternalContextBase *on_finish, bool top);
97   /**
98    * Kick off as many scrubs as are appropriate, based on the current
99    * state of the stack.
100    */
101   void kick_off_scrubs();
102   /**
103    * Push a indoe on top of the stack.
104    */
105   inline void push_inode(CInode *in);
106   /**
107    * Push a inode to the bottom of the stack.
108    */
109   inline void push_inode_bottom(CInode *in);
110   /**
111    * Pop the given inode off the stack.
112    */
113   inline void pop_inode(CInode *in);
114
115   /**
116    * Scrub a file inode.
117    * @param in The indoe to scrub
118    */
119   void scrub_file_inode(CInode *in);
120
121   /**
122    * Callback from completion of CInode::validate_disk_state
123    * @param in The inode we were validating
124    * @param r The return status from validate_disk_state
125    * @param result Populated results from validate_disk_state
126    */
127   void _validate_inode_done(CInode *in, int r,
128                             const CInode::validated_data &result);
129   friend class C_InodeValidated;
130
131   /**
132    * Make progress on scrubbing a directory-representing dirfrag and
133    * its children..
134    *
135    * 1) Select the next dirfrag which hasn't been scrubbed, and make progress
136    * on it if possible.
137    *
138    * 2) If not, move on to the next dirfrag and start it up, if any.
139    *
140    * 3) If waiting for results from dirfrag scrubs, do nothing.
141    *
142    * 4) If all dirfrags have been scrubbed, scrub my inode.
143    *
144    * @param in The CInode to scrub as a directory
145    * @param added_dentries set to true if we pushed some of our children
146    * onto the ScrubStack
147    * @param is_terminal set to true if there are no descendant dentries
148    * remaining to start scrubbing.
149    * @param done set to true if we and all our children have finished scrubbing
150    */
151   void scrub_dir_inode(CInode *in, bool *added_children, bool *is_terminal,
152                        bool *done);
153   /**
154    * Make progress on scrubbing a dirfrag. It may return after each of the
155    * following steps, but will report making progress on each one.
156    *
157    * 1) enqueues the next unscrubbed child directory dentry at the
158    * top of the stack.
159    *
160    * 2) Initiates a scrub on the next unscrubbed file dentry
161    *
162    * If there are scrubs currently in progress on child dentries, no more child
163    * dentries to scrub, and this function is invoked, it will report no
164    * progress. Try again later.
165    *
166    */
167   void scrub_dirfrag(CDir *dir, const ScrubHeaderRefConst& header,
168                      bool *added_children, bool *is_terminal, bool *done);
169   /**
170    * Scrub a directory-representing dentry.
171    *
172    * @param in The directory inode we're doing final scrub on.
173    */
174   void scrub_dir_inode_final(CInode *in);
175
176   /**
177    * Get a CDir into memory, and return it if it's already complete.
178    * Otherwise, fetch it and kick off scrubbing when done.
179    *
180    * @param in The Inode to get the next directory from
181    * @param new_dir The CDir we're returning to you. NULL if
182    * not ready yet or there aren't any.
183    * @returns false if you have to wait, true if there's no work
184    * left to do (we returned it, or there are none left in this inode).
185    */
186   bool get_next_cdir(CInode *in, CDir **new_dir);
187
188 };
189
190 #endif /* SCRUBSTACK_H_ */