revert-mm-fix-blkdev-size-calculation-in-generic_write_checks
[linux-2.6/linux-trees-mm.git] / fs / reiser4 / context.c
blob4b3137f029d2b34934d1f88c488903b3e84d1d84
1 /* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
3 /* Manipulation of reiser4_context */
5 /*
6 * global context used during system call. Variable of this type is allocated
7 * on the stack at the beginning of the reiser4 part of the system call and
8 * pointer to it is stored in the current->fs_context. This allows us to avoid
9 * passing pointer to current transaction and current lockstack (both in
10 * one-to-one mapping with threads) all over the call chain.
12 * It's kind of like those global variables the prof used to tell you not to
13 * use in CS1, except thread specific.;-) Nikita, this was a good idea.
15 * In some situations it is desirable to have ability to enter reiser4_context
16 * more than once for the same thread (nested contexts). For example, there
17 * are some functions that can be called either directly from VFS/VM or from
18 * already active reiser4 context (->writepage, for example).
20 * In such situations "child" context acts like dummy: all activity is
21 * actually performed in the top level context, and get_current_context()
22 * always returns top level context.
23 * Of course, reiser4_init_context()/reiser4_done_context() have to be properly
24 * nested any way.
26 * Note that there is an important difference between reiser4 uses
27 * ->fs_context and the way other file systems use it. Other file systems
28 * (ext3 and reiserfs) use ->fs_context only for the duration of _transaction_
29 * (this is why ->fs_context was initially called ->journal_info). This means,
30 * that when ext3 or reiserfs finds that ->fs_context is not NULL on the entry
31 * to the file system, they assume that some transaction is already underway,
32 * and usually bail out, because starting nested transaction would most likely
33 * lead to the deadlock. This gives false positives with reiser4, because we
34 * set ->fs_context before starting transaction.
37 #include "debug.h"
38 #include "super.h"
39 #include "context.h"
41 #include <linux/writeback.h> /* balance_dirty_pages() */
42 #include <linux/hardirq.h>
44 static void _reiser4_init_context(reiser4_context * context,
45 struct super_block *super)
47 memset(context, 0, sizeof(*context));
49 context->super = super;
50 context->magic = context_magic;
51 context->outer = current->journal_info;
52 current->journal_info = (void *)context;
53 context->nr_children = 0;
54 context->gfp_mask = GFP_KERNEL;
56 init_lock_stack(&context->stack);
58 reiser4_txn_begin(context);
60 /* initialize head of tap list */
61 INIT_LIST_HEAD(&context->taps);
62 #if REISER4_DEBUG
63 context->task = current;
64 #endif
65 grab_space_enable();
68 /* initialize context and bind it to the current thread
70 This function should be called at the beginning of reiser4 part of
71 syscall.
73 reiser4_context * reiser4_init_context(struct super_block * super)
75 reiser4_context *context;
77 assert("nikita-2662", !in_interrupt() && !in_irq());
78 assert("nikita-3357", super != NULL);
79 assert("nikita-3358", super->s_op == NULL || is_reiser4_super(super));
81 context = get_current_context_check();
82 if (context && context->super == super) {
83 context = (reiser4_context *) current->journal_info;
84 context->nr_children++;
85 return context;
88 context = kmalloc(sizeof(*context), GFP_KERNEL);
89 if (context == NULL)
90 return ERR_PTR(RETERR(-ENOMEM));
92 _reiser4_init_context(context, super);
93 return context;
96 /* this is used in scan_mgr which is called with spinlock held and in
97 reiser4_fill_super magic */
98 void init_stack_context(reiser4_context *context, struct super_block *super)
100 assert("nikita-2662", !in_interrupt() && !in_irq());
101 assert("nikita-3357", super != NULL);
102 assert("nikita-3358", super->s_op == NULL || is_reiser4_super(super));
103 assert("vs-12", !is_in_reiser4_context());
105 _reiser4_init_context(context, super);
106 context->on_stack = 1;
107 return;
110 /* cast lock stack embedded into reiser4 context up to its container */
111 reiser4_context *get_context_by_lock_stack(lock_stack * owner)
113 return container_of(owner, reiser4_context, stack);
116 /* true if there is already _any_ reiser4 context for the current thread */
117 int is_in_reiser4_context(void)
119 reiser4_context *ctx;
121 ctx = current->journal_info;
122 return ctx != NULL && ((unsigned long)ctx->magic) == context_magic;
126 * call balance dirty pages for the current context.
128 * File system is expected to call balance_dirty_pages_ratelimited() whenever
129 * it dirties a page. reiser4 does this for unformatted nodes (that is, during
130 * write---this covers vast majority of all dirty traffic), but we cannot do
131 * this immediately when formatted node is dirtied, because long term lock is
132 * usually held at that time. To work around this, dirtying of formatted node
133 * simply increases ->nr_marked_dirty counter in the current reiser4
134 * context. When we are about to leave this context,
135 * balance_dirty_pages_ratelimited() is called, if necessary.
137 * This introduces another problem: sometimes we do not want to run
138 * balance_dirty_pages_ratelimited() when leaving a context, for example
139 * because some important lock (like ->i_mutex on the parent directory) is
140 * held. To achieve this, ->nobalance flag can be set in the current context.
142 static void balance_dirty_pages_at(reiser4_context *context)
144 reiser4_super_info_data *sbinfo = get_super_private(context->super);
147 * call balance_dirty_pages_ratelimited() to process formatted nodes
148 * dirtied during this system call. Do that only if we are not in mount
149 * and there were nodes dirtied in this context and we are not in
150 * writepage (to avoid deadlock) and not in pdflush
152 if (sbinfo != NULL && sbinfo->fake != NULL &&
153 context->nr_marked_dirty != 0 &&
154 !(current->flags & PF_MEMALLOC) &&
155 !current_is_pdflush())
156 balance_dirty_pages_ratelimited(sbinfo->fake->i_mapping);
159 /* release resources associated with context.
161 This function should be called at the end of "session" with reiser4,
162 typically just before leaving reiser4 driver back to VFS.
164 This is good place to put some degugging consistency checks, like that
165 thread released all locks and closed transcrash etc.
168 static void reiser4_done_context(reiser4_context * context /* context being released */ )
170 assert("nikita-860", context != NULL);
171 assert("nikita-859", context->magic == context_magic);
172 assert("vs-646", (reiser4_context *) current->journal_info == context);
173 assert("zam-686", !in_interrupt() && !in_irq());
175 /* only do anything when leaving top-level reiser4 context. All nested
176 * contexts are just dummies. */
177 if (context->nr_children == 0) {
178 assert("jmacd-673", context->trans == NULL);
179 assert("jmacd-1002", lock_stack_isclean(&context->stack));
180 assert("nikita-1936", reiser4_no_counters_are_held());
181 assert("nikita-2626", list_empty_careful(reiser4_taps_list()));
182 assert("zam-1004", ergo(get_super_private(context->super),
183 get_super_private(context->super)->delete_mutex_owner !=
184 current));
186 /* release all grabbed but as yet unused blocks */
187 if (context->grabbed_blocks != 0)
188 all_grabbed2free();
191 * synchronize against longterm_unlock_znode():
192 * wake_up_requestor() wakes up requestors without holding
193 * zlock (otherwise they will immediately bump into that lock
194 * after wake up on another CPU). To work around (rare)
195 * situation where requestor has been woken up asynchronously
196 * and managed to run until completion (and destroy its
197 * context and lock stack) before wake_up_requestor() called
198 * wake_up() on it, wake_up_requestor() synchronize on lock
199 * stack spin lock. It has actually been observed that spin
200 * lock _was_ locked at this point, because
201 * wake_up_requestor() took interrupt.
203 spin_lock_stack(&context->stack);
204 spin_unlock_stack(&context->stack);
206 assert("zam-684", context->nr_children == 0);
207 /* restore original ->fs_context value */
208 current->journal_info = context->outer;
209 if (context->on_stack == 0)
210 kfree(context);
211 } else {
212 context->nr_children--;
213 #if REISER4_DEBUG
214 assert("zam-685", context->nr_children >= 0);
215 #endif
220 * exit reiser4 context. Call balance_dirty_pages_at() if necessary. Close
221 * transaction. Call done_context() to do context related book-keeping.
223 void reiser4_exit_context(reiser4_context * context)
225 assert("nikita-3021", reiser4_schedulable());
227 if (context->nr_children == 0) {
228 if (!context->nobalance) {
229 reiser4_txn_restart(context);
230 balance_dirty_pages_at(context);
233 /* if filesystem is mounted with -o sync or -o dirsync - commit
234 transaction. FIXME: TXNH_DONT_COMMIT is used to avoid
235 commiting on exit_context when inode semaphore is held and
236 to have ktxnmgrd to do commit instead to get better
237 concurrent filesystem accesses. But, when one mounts with -o
238 sync, he cares more about reliability than about
239 performance. So, for now we have this simple mount -o sync
240 support. */
241 if (context->super->s_flags & (MS_SYNCHRONOUS | MS_DIRSYNC)) {
242 txn_atom *atom;
244 atom = get_current_atom_locked_nocheck();
245 if (atom) {
246 atom->flags |= ATOM_FORCE_COMMIT;
247 context->trans->flags &= ~TXNH_DONT_COMMIT;
248 spin_unlock_atom(atom);
251 reiser4_txn_end(context);
253 reiser4_done_context(context);
256 void reiser4_ctx_gfp_mask_set(void)
258 reiser4_context *ctx;
260 ctx = get_current_context();
261 if (ctx->entd == 0 &&
262 list_empty(&ctx->stack.locks) &&
263 ctx->trans->atom == NULL)
264 ctx->gfp_mask = GFP_KERNEL;
265 else
266 ctx->gfp_mask = GFP_NOFS;
269 void reiser4_ctx_gfp_mask_force (gfp_t mask)
271 reiser4_context *ctx;
272 ctx = get_current_context();
274 assert("edward-1454", ctx != NULL);
276 ctx->gfp_mask = mask;
280 * Local variables:
281 * c-indentation-style: "K&R"
282 * mode-name: "LC"
283 * c-basic-offset: 8
284 * tab-width: 8
285 * fill-column: 120
286 * scroll-step: 1
287 * End: