1 /* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
3 /* Manipulation of reiser4_context */
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
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.
40 #include "vfs_ops.h" /* for reiser4_throttle_write() */
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
);
63 context
->task
= current
;
68 /* initialize context and bind it to the current thread
70 This function should be called at the beginning of reiser4 part of
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
++;
88 context
= kmalloc(sizeof(*context
), GFP_KERNEL
);
90 return ERR_PTR(RETERR(-ENOMEM
));
92 _reiser4_init_context(context
, super
);
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;
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 reiser4_throttle_write_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 /* FIXME-EDWARD: throttle with nr_marked_dirty? */
156 reiser4_throttle_write(sbinfo
->fake
, 1);
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
)
169 /* context being released */
171 assert("nikita-860", context
!= NULL
);
172 assert("nikita-859", context
->magic
== context_magic
);
173 assert("vs-646", (reiser4_context
*) current
->journal_info
== context
);
174 assert("zam-686", !in_interrupt() && !in_irq());
176 /* only do anything when leaving top-level reiser4 context. All nested
177 * contexts are just dummies. */
178 if (context
->nr_children
== 0) {
179 assert("jmacd-673", context
->trans
== NULL
);
180 assert("jmacd-1002", lock_stack_isclean(&context
->stack
));
181 assert("nikita-1936", reiser4_no_counters_are_held());
182 assert("nikita-2626", list_empty_careful(reiser4_taps_list()));
183 assert("zam-1004", ergo(get_super_private(context
->super
),
184 get_super_private(context
->super
)->delete_mutex_owner
!=
187 /* release all grabbed but as yet unused blocks */
188 if (context
->grabbed_blocks
!= 0)
192 * synchronize against longterm_unlock_znode():
193 * wake_up_requestor() wakes up requestors without holding
194 * zlock (otherwise they will immediately bump into that lock
195 * after wake up on another CPU). To work around (rare)
196 * situation where requestor has been woken up asynchronously
197 * and managed to run until completion (and destroy its
198 * context and lock stack) before wake_up_requestor() called
199 * wake_up() on it, wake_up_requestor() synchronize on lock
200 * stack spin lock. It has actually been observed that spin
201 * lock _was_ locked at this point, because
202 * wake_up_requestor() took interrupt.
204 spin_lock_stack(&context
->stack
);
205 spin_unlock_stack(&context
->stack
);
207 assert("zam-684", context
->nr_children
== 0);
208 /* restore original ->fs_context value */
209 current
->journal_info
= context
->outer
;
210 if (context
->on_stack
== 0)
213 context
->nr_children
--;
215 assert("zam-685", context
->nr_children
>= 0);
221 * exit reiser4 context. Call balance_dirty_pages_at() if necessary. Close
222 * transaction. Call done_context() to do context related book-keeping.
224 void reiser4_exit_context(reiser4_context
* context
)
226 assert("nikita-3021", reiser4_schedulable());
228 if (context
->nr_children
== 0) {
229 if (!context
->nobalance
)
230 reiser4_throttle_write_at(context
);
232 /* if filesystem is mounted with -o sync or -o dirsync - commit
233 transaction. FIXME: TXNH_DONT_COMMIT is used to avoid
234 commiting on exit_context when inode semaphore is held and
235 to have ktxnmgrd to do commit instead to get better
236 concurrent filesystem accesses. But, when one mounts with -o
237 sync, he cares more about reliability than about
238 performance. So, for now we have this simple mount -o sync
240 if (context
->super
->s_flags
& (MS_SYNCHRONOUS
| MS_DIRSYNC
)) {
243 atom
= get_current_atom_locked_nocheck();
245 atom
->flags
|= ATOM_FORCE_COMMIT
;
246 context
->trans
->flags
&= ~TXNH_DONT_COMMIT
;
247 spin_unlock_atom(atom
);
250 reiser4_txn_end(context
);
252 reiser4_done_context(context
);
255 void reiser4_ctx_gfp_mask_set(void)
257 reiser4_context
*ctx
;
259 ctx
= get_current_context();
260 if (ctx
->entd
== 0 &&
261 list_empty(&ctx
->stack
.locks
) &&
262 ctx
->trans
->atom
== NULL
)
263 ctx
->gfp_mask
= GFP_KERNEL
;
265 ctx
->gfp_mask
= GFP_NOFS
;
268 void reiser4_ctx_gfp_mask_force(gfp_t mask
)
270 reiser4_context
*ctx
;
271 ctx
= get_current_context();
273 assert("edward-1454", ctx
!= NULL
);
275 ctx
->gfp_mask
= mask
;
280 * c-indentation-style: "K&R"