1 |
1275 |
phoenix |
/*
|
2 |
|
|
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
|
3 |
|
|
*/
|
4 |
|
|
|
5 |
|
|
#include <linux/config.h>
|
6 |
|
|
#include <linux/sched.h>
|
7 |
|
|
#include <linux/locks.h>
|
8 |
|
|
#include <linux/reiserfs_fs.h>
|
9 |
|
|
#include <linux/smp_lock.h>
|
10 |
|
|
#include <linux/kernel_stat.h>
|
11 |
|
|
|
12 |
|
|
/*
|
13 |
|
|
* wait_buffer_until_released
|
14 |
|
|
* reiserfs_bread
|
15 |
|
|
*/
|
16 |
|
|
|
17 |
|
|
/* when we allocate a new block (get_new_buffer, get_empty_nodes) and
|
18 |
|
|
get buffer for it, it is possible that it is held by someone else
|
19 |
|
|
or even by this process. In this function we wait until all other
|
20 |
|
|
holders release buffer. To make sure, that current process does not
|
21 |
|
|
hold we did free all buffers in tree balance structure
|
22 |
|
|
(get_empty_nodes and get_nodes_for_preserving) or in path structure
|
23 |
|
|
only (get_new_buffer) just before calling this */
|
24 |
|
|
void wait_buffer_until_released (const struct buffer_head * bh)
|
25 |
|
|
{
|
26 |
|
|
int repeat_counter = 0;
|
27 |
|
|
|
28 |
|
|
while (atomic_read (&(bh->b_count)) > 1) {
|
29 |
|
|
|
30 |
|
|
if ( !(++repeat_counter % 30000000) ) {
|
31 |
|
|
reiserfs_warning (NULL, "vs-3050: wait_buffer_until_released: nobody releases buffer (%b). Still waiting (%d) %cJDIRTY %cJWAIT\n",
|
32 |
|
|
bh, repeat_counter, buffer_journaled(bh) ? ' ' : '!',
|
33 |
|
|
buffer_journal_dirty(bh) ? ' ' : '!');
|
34 |
|
|
}
|
35 |
|
|
run_task_queue(&tq_disk);
|
36 |
|
|
yield();
|
37 |
|
|
}
|
38 |
|
|
if (repeat_counter > 30000000) {
|
39 |
|
|
reiserfs_warning(NULL, "vs-3051: done waiting, ignore vs-3050 messages for (%b)\n", bh) ;
|
40 |
|
|
}
|
41 |
|
|
}
|
42 |
|
|
|
43 |
|
|
/*
|
44 |
|
|
* reiserfs_bread() reads a specified block and returns the buffer that contains
|
45 |
|
|
* it. It returns NULL if the block was unreadable.
|
46 |
|
|
*/
|
47 |
|
|
/* It first tries to find the block in cache, and if it cannot do so
|
48 |
|
|
then it creates a new buffer and schedules I/O to read the
|
49 |
|
|
block. */
|
50 |
|
|
/* The function is NOT SCHEDULE-SAFE! */
|
51 |
|
|
struct buffer_head * reiserfs_bread (struct super_block *super, int n_block, int n_size)
|
52 |
|
|
{
|
53 |
|
|
struct buffer_head *result;
|
54 |
|
|
PROC_EXP( unsigned int ctx_switches = kstat.context_swtch );
|
55 |
|
|
|
56 |
|
|
result = bread (super -> s_dev, n_block, n_size);
|
57 |
|
|
PROC_INFO_INC( super, breads );
|
58 |
|
|
PROC_EXP( if( kstat.context_swtch != ctx_switches )
|
59 |
|
|
PROC_INFO_INC( super, bread_miss ) );
|
60 |
|
|
return result;
|
61 |
|
|
}
|
62 |
|
|
|
63 |
|
|
struct buffer_head * journal_bread (struct super_block *s, int block)
|
64 |
|
|
{
|
65 |
|
|
return bread (SB_JOURNAL_DEV(s), block, s->s_blocksize );
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
struct buffer_head * journal_getblk (struct super_block *s, int block)
|
69 |
|
|
{
|
70 |
|
|
return getblk (SB_JOURNAL_DEV(s), block, s->s_blocksize );
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
struct buffer_head * journal_get_hash_table (struct super_block *s, int block)
|
74 |
|
|
{
|
75 |
|
|
return get_hash_table (SB_JOURNAL_DEV(s), block, s->s_blocksize );
|
76 |
|
|
}
|