Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
6b80053d
Commit
6b80053d
authored
Oct 15, 2007
by
Chris Mason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Add back the online defragging code
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
09e71a32
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
166 additions
and
106 deletions
+166
-106
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+88
-89
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+60
-0
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+7
-0
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+1
-7
fs/btrfs/extent_map.h
fs/btrfs/extent_map.h
+2
-0
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+2
-2
fs/btrfs/tree-defrag.c
fs/btrfs/tree-defrag.c
+6
-8
No files found.
fs/btrfs/ctree.c
View file @
6b80053d
...
...
@@ -155,55 +155,49 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
return
ret
;
}
#if 0
static int close_blocks(u64 blocknr, u64 other)
static
int
close_blocks
(
u64
blocknr
,
u64
other
,
u32
blocksize
)
{
if (blocknr < other && other -
blocknr <
8)
if
(
blocknr
<
other
&&
other
-
(
blocknr
+
blocksize
)
<
3276
8
)
return
1
;
if (blocknr > other && blocknr -
other <
8)
if
(
blocknr
>
other
&&
blocknr
-
(
other
+
blocksize
)
<
3276
8
)
return
1
;
return
0
;
}
static int should_defrag_leaf(struct extent_buffer *
eb
)
static
int
should_defrag_leaf
(
struct
extent_buffer
*
leaf
)
{
return 0;
struct btrfs_leaf *leaf = btrfs_buffer_leaf(eb);
struct btrfs_disk_key *key;
struct
btrfs_key
key
;
u32
nritems
;
if (b
uffer_defrag(bh
))
if
(
b
trfs_buffer_defrag
(
leaf
))
return
1
;
nritems = btrfs_header_nritems(
&leaf->header
);
nritems
=
btrfs_header_nritems
(
leaf
);
if
(
nritems
==
0
)
return
0
;
key = &leaf->items[0].key
;
if (
btrfs_disk_key_type(key)
== BTRFS_DIR_ITEM_KEY)
btrfs_item_key_to_cpu
(
leaf
,
&
key
,
0
)
;
if
(
key
.
type
==
BTRFS_DIR_ITEM_KEY
)
return
1
;
key = &leaf->items[nritems-1].key;
if (btrfs_disk_key_type(key) == BTRFS_DIR_ITEM_KEY)
btrfs_item_key_to_cpu
(
leaf
,
&
key
,
nritems
-
1
);
if
(
key
.
type
==
BTRFS_DIR_ITEM_KEY
)
return
1
;
if
(
nritems
>
4
)
{
key = &leaf->items[nritems/2].key
;
if (
btrfs_disk_key_type(key)
== BTRFS_DIR_ITEM_KEY)
btrfs_item_key_to_cpu
(
leaf
,
&
key
,
nritems
/
2
)
;
if
(
key
.
type
==
BTRFS_DIR_ITEM_KEY
)
return
1
;
}
return
0
;
}
#endif
int
btrfs_realloc_node
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
extent_buffer
*
parent
,
int
cache_only
,
u64
*
last_ret
)
{
return
0
;
#if 0
struct btrfs_node *parent_node;
struct extent_buffer *cur_eb;
struct extent_buffer *tmp_eb;
struct
extent_buffer
*
cur
;
struct
extent_buffer
*
tmp
;
u64
blocknr
;
u64
search_start
=
*
last_ret
;
u64
last_block
=
0
;
...
...
@@ -214,6 +208,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
int
i
;
int
err
=
0
;
int
parent_level
;
int
uptodate
;
u32
blocksize
;
if
(
trans
->
transaction
!=
root
->
fs_info
->
running_transaction
)
{
printk
(
KERN_CRIT
"trans %Lu running %Lu
\n
"
,
trans
->
transid
,
...
...
@@ -225,12 +221,12 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
root
->
fs_info
->
generation
);
WARN_ON
(
1
);
}
if (buffer_defrag_done(parent))
if
(
b
trfs_b
uffer_defrag_done
(
parent
))
return
0
;
parent_n
ode = btrfs_buffer_node
(parent);
parent_
nritems = btrfs_header_nritems(&parent_node->header
);
parent_level = btrfs_header_level(&parent_node->header
);
parent_n
ritems
=
btrfs_header_nritems
(
parent
);
parent_
level
=
btrfs_header_level
(
parent
);
blocksize
=
btrfs_level_size
(
root
,
parent_level
-
1
);
start_slot
=
0
;
end_slot
=
parent_nritems
;
...
...
@@ -240,56 +236,60 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
for
(
i
=
start_slot
;
i
<
end_slot
;
i
++
)
{
int
close
=
1
;
blocknr = btrfs_node_blockptr(parent
_node
, i);
blocknr
=
btrfs_node_blockptr
(
parent
,
i
);
if
(
last_block
==
0
)
last_block
=
blocknr
;
if
(
i
>
0
)
{
other = btrfs_node_blockptr(parent
_node
, i - 1);
close = close_blocks(blocknr, other);
other
=
btrfs_node_blockptr
(
parent
,
i
-
1
);
close
=
close_blocks
(
blocknr
,
other
,
blocksize
);
}
if
(
close
&&
i
<
end_slot
-
1
)
{
other = btrfs_node_blockptr(parent
_node
, i + 1);
close = close_blocks(blocknr, other);
other
=
btrfs_node_blockptr
(
parent
,
i
+
1
);
close
=
close_blocks
(
blocknr
,
other
,
blocksize
);
}
if
(
close
)
{
last_block
=
blocknr
;
continue
;
}
cur_bh = btrfs_find_tree_block(root, blocknr);
if (!cur_bh || !buffer_uptodate(cur_bh) ||
buffer_locked(cur_bh) ||
(parent_level != 1 && !buffer_defrag(cur_bh)) ||
(parent_level == 1 && !should_defrag_leaf(cur_bh))) {
cur
=
btrfs_find_tree_block
(
root
,
blocknr
,
blocksize
);
if
(
cur
)
uptodate
=
btrfs_buffer_uptodate
(
cur
);
else
uptodate
=
0
;
if
(
!
cur
||
!
uptodate
||
(
parent_level
!=
1
&&
!
btrfs_buffer_defrag
(
cur
))
||
(
parent_level
==
1
&&
!
should_defrag_leaf
(
cur
)))
{
if
(
cache_only
)
{
brelse(cur_bh
);
free_extent_buffer
(
cur
);
continue
;
}
if (!cur_bh || !buffer_uptodate(cur_bh) ||
buffer_locked(cur_bh)) {
brelse(cur_bh);
cur_bh = read_tree_block(root, blocknr);
if
(
!
cur
)
{
cur
=
read_tree_block
(
root
,
blocknr
,
blocksize
);
}
else
if
(
!
uptodate
)
{
btrfs_read_buffer
(
cur
);
}
}
if
(
search_start
==
0
)
search_start = last_block
& ~((u64)65535)
;
search_start
=
last_block
;
err = __btrfs_cow_block(trans, root, cur_bh, parent, i,
&tmp_bh, search_start,
min(8, end_slot - i));
err
=
__btrfs_cow_block
(
trans
,
root
,
cur
,
parent
,
i
,
&
tmp
,
search_start
,
min
(
16
*
blocksize
,
(
end_slot
-
i
)
*
blocksize
));
if
(
err
)
{
brelse(cur_bh
);
free_extent_buffer
(
cur
);
break
;
}
search_start =
bh_blocknr(tmp_bh)
;
search_start
=
tmp
->
start
;
*
last_ret
=
search_start
;
if
(
parent_level
==
1
)
clear_buffer_defrag(tmp_bh
);
set_buffer_defrag_done(tmp_bh
);
brelse(tmp_bh
);
btrfs_clear_buffer_defrag
(
tmp
);
btrfs_set_buffer_defrag_done
(
tmp
);
free_extent_buffer
(
tmp
);
}
return
err
;
#endif
}
/*
...
...
@@ -892,22 +892,17 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
static
void
reada_for_search
(
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
,
int
slot
)
{
return
;
#if 0
struct
extent_buffer
*
node
;
int i;
u32
nritems
;
u64 bytenr;
u64
search
;
u64
cluster_start
;
int ret
;
int
nread = 0;
u64
lowest_read
;
u64
highest_read
;
u64
nread
=
0
;
int
direction
=
path
->
reada
;
int level;
struct radix_tree_root found;
unsigned long gang[8];
struct
extent_buffer
*
eb
;
u32
nr
;
u32
blocksize
;
u32
nscan
=
0
;
if
(
level
==
0
)
return
;
...
...
@@ -917,42 +912,46 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
node
=
path
->
nodes
[
level
];
search
=
btrfs_node_blockptr
(
node
,
slot
);
eb = btrfs_find_tree_block(root, search);
blocksize
=
btrfs_level_size
(
root
,
level
-
1
);
eb
=
btrfs_find_tree_block
(
root
,
search
,
blocksize
);
if
(
eb
)
{
free_extent_buffer
(
eb
);
return
;
}
init_bit_radix(&found);
highest_read
=
search
;
lowest_read
=
search
;
nritems
=
btrfs_header_nritems
(
node
);
level = btrfs_header_level(node) - 1;
for (i = slot; i < nritems; i++) {
bytenr = btrfs_node_blockptr(node, i);
set_radix_bit(&found, blocknr);
}
if (direction > 0) {
cluster_start = search - 4;
if (cluster_start > search)
cluster_start = 0;
} else
cluster_start = search + 4;
nr
=
slot
;
while
(
1
)
{
ret = find_first_radix_bit(&found, gang, 0, ARRAY_SIZE(gang));
if (!ret)
break;
for (i = 0; i < ret; i++) {
blocknr = gang[i];
clear_radix_bit(&found, blocknr);
if (path->reada == 1 && nread > 16)
continue;
if (close_blocks(cluster_start, blocknr)) {
readahead_tree_block(root, blocknr);
nread++;
cluster_start = blocknr;
}
if
(
direction
<
0
)
{
if
(
nr
==
0
)
break
;
nr
--
;
}
else
if
(
direction
>
0
)
{
nr
++
;
if
(
nr
>=
nritems
)
break
;
}
search
=
btrfs_node_blockptr
(
node
,
nr
);
if
((
search
>=
lowest_read
&&
search
<=
highest_read
)
||
(
search
<
lowest_read
&&
lowest_read
-
search
<=
32768
)
||
(
search
>
highest_read
&&
search
-
highest_read
<=
32768
))
{
readahead_tree_block
(
root
,
search
,
blocksize
);
nread
+=
blocksize
;
}
nscan
++
;
if
(
path
->
reada
<
2
&&
(
nread
>
(
256
*
1024
)
||
nscan
>
32
))
break
;
if
(
nread
>
(
1024
*
1024
)
||
nscan
>
128
)
break
;
if
(
search
<
lowest_read
)
lowest_read
=
search
;
if
(
search
>
highest_read
)
highest_read
=
search
;
}
#endif
}
/*
* look for key in the tree. path is filled in with nodes along the way
...
...
fs/btrfs/disk-io.c
View file @
6b80053d
...
...
@@ -678,3 +678,63 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
balance_dirty_pages_ratelimited_nr
(
root
->
fs_info
->
btree_inode
->
i_mapping
,
nr
);
}
void
btrfs_set_buffer_defrag
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
set_extent_bits
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_DEFRAG
,
GFP_NOFS
);
}
void
btrfs_set_buffer_defrag_done
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
set_extent_bits
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_DEFRAG_DONE
,
GFP_NOFS
);
}
int
btrfs_buffer_defrag
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
return
test_range_bit
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_DEFRAG
,
0
);
}
int
btrfs_buffer_defrag_done
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
return
test_range_bit
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_DEFRAG_DONE
,
0
);
}
int
btrfs_clear_buffer_defrag_done
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
return
clear_extent_bits
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_DEFRAG_DONE
,
GFP_NOFS
);
}
int
btrfs_clear_buffer_defrag
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
return
clear_extent_bits
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
EXTENT_DEFRAG
,
GFP_NOFS
);
}
int
btrfs_read_buffer
(
struct
extent_buffer
*
buf
)
{
struct
btrfs_root
*
root
=
BTRFS_I
(
buf
->
pages
[
0
]
->
mapping
->
host
)
->
root
;
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
return
read_extent_buffer_pages
(
&
BTRFS_I
(
btree_inode
)
->
extent_tree
,
buf
,
1
);
}
fs/btrfs/disk-io.h
View file @
6b80053d
...
...
@@ -51,4 +51,11 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf);
int
btrfs_set_buffer_uptodate
(
struct
extent_buffer
*
buf
);
int
wait_on_tree_block_writeback
(
struct
btrfs_root
*
root
,
struct
extent_buffer
*
buf
);
void
btrfs_set_buffer_defrag
(
struct
extent_buffer
*
buf
);
void
btrfs_set_buffer_defrag_done
(
struct
extent_buffer
*
buf
);
int
btrfs_buffer_defrag
(
struct
extent_buffer
*
buf
);
int
btrfs_buffer_defrag_done
(
struct
extent_buffer
*
buf
);
int
btrfs_clear_buffer_defrag
(
struct
extent_buffer
*
buf
);
int
btrfs_clear_buffer_defrag_done
(
struct
extent_buffer
*
buf
);
int
btrfs_read_buffer
(
struct
extent_buffer
*
buf
);
#endif
fs/btrfs/extent-tree.c
View file @
6b80053d
...
...
@@ -1173,13 +1173,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
buf
->
alloc_addr
=
(
unsigned
long
)
__builtin_return_address
(
0
);
set_extent_dirty
(
&
trans
->
transaction
->
dirty_pages
,
buf
->
start
,
buf
->
start
+
buf
->
len
-
1
,
GFP_NOFS
);
/*
set_buffer_checked(buf);
set_buffer_defrag(buf);
*/
/* FIXME!!!!!!!!!!!!!!!!
set_radix_bit(&trans->transaction->dirty_pages, buf->pages[0]->index);
*/
btrfs_set_buffer_defrag
(
buf
);
trans
->
blocks_used
++
;
return
buf
;
}
...
...
fs/btrfs/extent_map.h
View file @
6b80053d
...
...
@@ -14,6 +14,8 @@
#define EXTENT_LOCKED (1 << 3)
#define EXTENT_NEW (1 << 4)
#define EXTENT_DELALLOC (1 << 5)
#define EXTENT_DEFRAG (1 << 6)
#define EXTENT_DEFRAG_DONE (1 << 7)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
...
...
fs/btrfs/transaction.c
View file @
6b80053d
...
...
@@ -355,7 +355,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
return
0
;
trans
=
btrfs_start_transaction
(
root
,
1
);
while
(
0
)
{
while
(
1
)
{
root
->
defrag_running
=
1
;
ret
=
btrfs_defrag_leaves
(
trans
,
root
,
cacheonly
);
nr
=
trans
->
blocks_used
;
...
...
@@ -400,7 +400,7 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
btrfs_defrag_root
(
root
,
1
);
}
}
//
btrfs_defrag_root(info->extent_root, 1);
btrfs_defrag_root
(
info
->
extent_root
,
1
);
return
err
;
}
...
...
fs/btrfs/tree-defrag.c
View file @
6b80053d
...
...
@@ -116,10 +116,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
}
WARN_ON
(
*
level
<
0
);
WARN_ON
(
*
level
>=
BTRFS_MAX_LEVEL
);
#if 0
clear_buffer_defrag(path->nodes[*level]);
clear_buffer_defrag_done(path->nodes[*level]);
#endif
btrfs_
clear_buffer_defrag
(
path
->
nodes
[
*
level
]);
btrfs_
clear_buffer_defrag_done
(
path
->
nodes
[
*
level
]);
free_extent_buffer
(
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
*
level
+=
1
;
...
...
@@ -148,10 +148,8 @@ static int defrag_walk_up(struct btrfs_trans_handle *trans,
root
->
defrag_level
=
i
;
return
0
;
}
else
{
/*
clear_buffer_defrag(path->nodes[*level]);
clear_buffer_defrag_done(path->nodes[*level]);
*/
btrfs_clear_buffer_defrag
(
path
->
nodes
[
*
level
]);
btrfs_clear_buffer_defrag_done
(
path
->
nodes
[
*
level
]);
free_extent_buffer
(
path
->
nodes
[
*
level
]);
path
->
nodes
[
*
level
]
=
NULL
;
*
level
=
i
+
1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment