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
Kirill Smelkov
linux
Commits
d4dbff95
Commit
d4dbff95
authored
Apr 04, 2007
by
Chris Mason
Committed by
David Woodhouse
Apr 04, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: support for items bigger than 1/2 the blocksize
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
df24a2b9
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
110 additions
and
38 deletions
+110
-38
fs/btrfs/ctree.c
fs/btrfs/ctree.c
+97
-35
fs/btrfs/super.c
fs/btrfs/super.c
+13
-3
No files found.
fs/btrfs/ctree.c
View file @
d4dbff95
...
@@ -6,7 +6,8 @@
...
@@ -6,7 +6,8 @@
static
int
split_node
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
static
int
split_node
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
level
);
*
root
,
struct
btrfs_path
*
path
,
int
level
);
static
int
split_leaf
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
static
int
split_leaf
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
data_size
);
*
root
,
struct
btrfs_key
*
ins_key
,
struct
btrfs_path
*
path
,
int
data_size
);
static
int
push_node_left
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
static
int
push_node_left
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
buffer_head
*
dst
,
struct
buffer_head
*
root
,
struct
buffer_head
*
dst
,
struct
buffer_head
*
src
);
*
src
);
...
@@ -101,19 +102,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root,
...
@@ -101,19 +102,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root,
return
btrfs_item_offset
(
leaf
->
items
+
nr
-
1
);
return
btrfs_item_offset
(
leaf
->
items
+
nr
-
1
);
}
}
/*
* The space between the end of the leaf items and
* the start of the leaf data. IOW, how much room
* the leaf has left for both items and data
*/
int
btrfs_leaf_free_space
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
leaf
)
{
int
data_end
=
leaf_data_end
(
root
,
leaf
);
int
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
char
*
items_end
=
(
char
*
)(
leaf
->
items
+
nritems
+
1
);
return
(
char
*
)(
btrfs_leaf_data
(
leaf
)
+
data_end
)
-
(
char
*
)
items_end
;
}
/*
/*
* compare two keys in a memcmp fashion
* compare two keys in a memcmp fashion
*/
*/
...
@@ -510,8 +498,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -510,8 +498,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if
(
ret
&&
slot
>
0
)
if
(
ret
&&
slot
>
0
)
slot
-=
1
;
slot
-=
1
;
p
->
slots
[
level
]
=
slot
;
p
->
slots
[
level
]
=
slot
;
if
(
ins_len
>
0
&&
btrfs_header_nritems
(
&
c
->
header
)
=
=
if
(
ins_len
>
0
&&
btrfs_header_nritems
(
&
c
->
header
)
>
=
BTRFS_NODEPTRS_PER_BLOCK
(
root
))
{
BTRFS_NODEPTRS_PER_BLOCK
(
root
)
-
1
)
{
int
sret
=
split_node
(
trans
,
root
,
p
,
level
);
int
sret
=
split_node
(
trans
,
root
,
p
,
level
);
BUG_ON
(
sret
>
0
);
BUG_ON
(
sret
>
0
);
if
(
sret
)
if
(
sret
)
...
@@ -537,7 +525,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -537,7 +525,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
p
->
slots
[
level
]
=
slot
;
p
->
slots
[
level
]
=
slot
;
if
(
ins_len
>
0
&&
btrfs_leaf_free_space
(
root
,
l
)
<
if
(
ins_len
>
0
&&
btrfs_leaf_free_space
(
root
,
l
)
<
sizeof
(
struct
btrfs_item
)
+
ins_len
)
{
sizeof
(
struct
btrfs_item
)
+
ins_len
)
{
int
sret
=
split_leaf
(
trans
,
root
,
p
,
ins_len
);
int
sret
=
split_leaf
(
trans
,
root
,
key
,
p
,
ins_len
);
BUG_ON
(
sret
>
0
);
BUG_ON
(
sret
>
0
);
if
(
sret
)
if
(
sret
)
return
sret
;
return
sret
;
...
@@ -825,16 +814,29 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -825,16 +814,29 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
static
int
leaf_space_used
(
struct
btrfs_leaf
*
l
,
int
start
,
int
nr
)
static
int
leaf_space_used
(
struct
btrfs_leaf
*
l
,
int
start
,
int
nr
)
{
{
int
data_len
;
int
data_len
;
int
end
=
start
+
nr
-
1
;
int
nritems
=
btrfs_header_nritems
(
&
l
->
header
);
int
end
=
min
(
nritems
,
start
+
nr
)
-
1
;
if
(
!
nr
)
if
(
!
nr
)
return
0
;
return
0
;
data_len
=
btrfs_item_end
(
l
->
items
+
start
);
data_len
=
btrfs_item_end
(
l
->
items
+
start
);
data_len
=
data_len
-
btrfs_item_offset
(
l
->
items
+
end
);
data_len
=
data_len
-
btrfs_item_offset
(
l
->
items
+
end
);
data_len
+=
sizeof
(
struct
btrfs_item
)
*
nr
;
data_len
+=
sizeof
(
struct
btrfs_item
)
*
nr
;
WARN_ON
(
data_len
<
0
);
return
data_len
;
return
data_len
;
}
}
/*
* The space between the end of the leaf items and
* the start of the leaf data. IOW, how much room
* the leaf has left for both items and data
*/
int
btrfs_leaf_free_space
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
leaf
)
{
int
nritems
=
btrfs_header_nritems
(
&
leaf
->
header
);
return
BTRFS_LEAF_DATA_SIZE
(
root
)
-
leaf_space_used
(
leaf
,
0
,
nritems
);
}
/*
/*
* push some data in the path leaf to the right, trying to free up at
* push some data in the path leaf to the right, trying to free up at
* least data_size bytes. returns zero if the push worked, nonzero otherwise
* least data_size bytes. returns zero if the push worked, nonzero otherwise
...
@@ -1084,7 +1086,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -1084,7 +1086,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
* returns 0 if all went well and < 0 on failure.
* returns 0 if all went well and < 0 on failure.
*/
*/
static
int
split_leaf
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
static
int
split_leaf
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
int
data_size
)
*
root
,
struct
btrfs_key
*
ins_key
,
struct
btrfs_path
*
path
,
int
data_size
)
{
{
struct
buffer_head
*
l_buf
;
struct
buffer_head
*
l_buf
;
struct
btrfs_leaf
*
l
;
struct
btrfs_leaf
*
l
;
...
@@ -1097,8 +1100,10 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -1097,8 +1100,10 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
int
data_copy_size
;
int
data_copy_size
;
int
rt_data_off
;
int
rt_data_off
;
int
i
;
int
i
;
int
ret
;
int
ret
=
0
;
int
wret
;
int
wret
;
int
double_split
=
0
;
struct
btrfs_disk_key
disk_key
;
/* first try to make some room by pushing left and right */
/* first try to make some room by pushing left and right */
wret
=
push_leaf_left
(
trans
,
root
,
path
,
data_size
);
wret
=
push_leaf_left
(
trans
,
root
,
path
,
data_size
);
...
@@ -1127,26 +1132,58 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -1127,26 +1132,58 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
mid
=
(
nritems
+
1
)
/
2
;
mid
=
(
nritems
+
1
)
/
2
;
right_buffer
=
btrfs_alloc_free_block
(
trans
,
root
);
right_buffer
=
btrfs_alloc_free_block
(
trans
,
root
);
BUG_ON
(
!
right_buffer
);
BUG_ON
(
!
right_buffer
);
BUG_ON
(
mid
==
nritems
);
right
=
btrfs_buffer_leaf
(
right_buffer
);
right
=
btrfs_buffer_leaf
(
right_buffer
);
memset
(
&
right
->
header
,
0
,
sizeof
(
right
->
header
));
memset
(
&
right
->
header
,
0
,
sizeof
(
right
->
header
));
if
(
mid
<=
slot
)
{
/* FIXME, just alloc a new leaf here */
if
(
leaf_space_used
(
l
,
mid
,
nritems
-
mid
)
+
space_needed
>
BTRFS_LEAF_DATA_SIZE
(
root
))
BUG
();
}
else
{
/* FIXME, just alloc a new leaf here */
if
(
leaf_space_used
(
l
,
0
,
mid
+
1
)
+
space_needed
>
BTRFS_LEAF_DATA_SIZE
(
root
))
BUG
();
}
btrfs_set_header_nritems
(
&
right
->
header
,
nritems
-
mid
);
btrfs_set_header_blocknr
(
&
right
->
header
,
right_buffer
->
b_blocknr
);
btrfs_set_header_blocknr
(
&
right
->
header
,
right_buffer
->
b_blocknr
);
btrfs_set_header_generation
(
&
right
->
header
,
trans
->
transid
);
btrfs_set_header_generation
(
&
right
->
header
,
trans
->
transid
);
btrfs_set_header_level
(
&
right
->
header
,
0
);
btrfs_set_header_level
(
&
right
->
header
,
0
);
btrfs_set_header_parentid
(
&
right
->
header
,
btrfs_set_header_parentid
(
&
right
->
header
,
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)));
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)));
if
(
mid
<=
slot
)
{
if
(
nritems
==
1
||
leaf_space_used
(
l
,
mid
,
nritems
-
mid
)
+
space_needed
>
BTRFS_LEAF_DATA_SIZE
(
root
))
{
if
(
slot
>=
nritems
)
{
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
&
right
->
header
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
right_buffer
->
b_blocknr
,
path
->
slots
[
1
]
+
1
,
1
);
if
(
wret
)
ret
=
wret
;
btrfs_block_release
(
root
,
path
->
nodes
[
0
]);
path
->
nodes
[
0
]
=
right_buffer
;
path
->
slots
[
0
]
=
0
;
path
->
slots
[
1
]
+=
1
;
return
ret
;
}
mid
=
slot
;
double_split
=
1
;
}
}
else
{
if
(
leaf_space_used
(
l
,
0
,
mid
+
1
)
+
space_needed
>
BTRFS_LEAF_DATA_SIZE
(
root
))
{
if
(
slot
==
0
)
{
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
&
right
->
header
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
right_buffer
->
b_blocknr
,
path
->
slots
[
1
]
-
1
,
1
);
if
(
wret
)
ret
=
wret
;
btrfs_block_release
(
root
,
path
->
nodes
[
0
]);
path
->
nodes
[
0
]
=
right_buffer
;
path
->
slots
[
0
]
=
0
;
path
->
slots
[
1
]
-=
1
;
return
ret
;
}
mid
=
slot
;
double_split
=
1
;
}
}
btrfs_set_header_nritems
(
&
right
->
header
,
nritems
-
mid
);
data_copy_size
=
btrfs_item_end
(
l
->
items
+
mid
)
-
data_copy_size
=
btrfs_item_end
(
l
->
items
+
mid
)
-
leaf_data_end
(
root
,
l
);
leaf_data_end
(
root
,
l
);
btrfs_memcpy
(
root
,
right
,
right
->
items
,
l
->
items
+
mid
,
btrfs_memcpy
(
root
,
right
,
right
->
items
,
l
->
items
+
mid
,
...
@@ -1180,6 +1217,31 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -1180,6 +1217,31 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
}
else
}
else
btrfs_block_release
(
root
,
right_buffer
);
btrfs_block_release
(
root
,
right_buffer
);
BUG_ON
(
path
->
slots
[
0
]
<
0
);
BUG_ON
(
path
->
slots
[
0
]
<
0
);
if
(
!
double_split
)
return
ret
;
right_buffer
=
btrfs_alloc_free_block
(
trans
,
root
);
BUG_ON
(
!
right_buffer
);
right
=
btrfs_buffer_leaf
(
right_buffer
);
memset
(
&
right
->
header
,
0
,
sizeof
(
right
->
header
));
btrfs_set_header_blocknr
(
&
right
->
header
,
right_buffer
->
b_blocknr
);
btrfs_set_header_generation
(
&
right
->
header
,
trans
->
transid
);
btrfs_set_header_level
(
&
right
->
header
,
0
);
btrfs_set_header_parentid
(
&
right
->
header
,
btrfs_header_parentid
(
btrfs_buffer_header
(
root
->
node
)));
btrfs_cpu_key_to_disk
(
&
disk_key
,
ins_key
);
btrfs_set_header_nritems
(
&
right
->
header
,
0
);
wret
=
insert_ptr
(
trans
,
root
,
path
,
&
disk_key
,
right_buffer
->
b_blocknr
,
path
->
slots
[
1
],
1
);
if
(
wret
)
ret
=
wret
;
btrfs_block_release
(
root
,
path
->
nodes
[
0
]);
path
->
nodes
[
0
]
=
right_buffer
;
path
->
slots
[
0
]
=
0
;
check_node
(
root
,
path
,
1
);
check_leaf
(
root
,
path
,
0
);
return
ret
;
return
ret
;
}
}
...
@@ -1220,9 +1282,9 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
...
@@ -1220,9 +1282,9 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
data_end
=
leaf_data_end
(
root
,
leaf
);
data_end
=
leaf_data_end
(
root
,
leaf
);
if
(
btrfs_leaf_free_space
(
root
,
leaf
)
<
if
(
btrfs_leaf_free_space
(
root
,
leaf
)
<
sizeof
(
struct
btrfs_item
)
+
data_size
)
sizeof
(
struct
btrfs_item
)
+
data_size
)
{
BUG
();
BUG
();
}
slot
=
path
->
slots
[
0
];
slot
=
path
->
slots
[
0
];
BUG_ON
(
slot
<
0
);
BUG_ON
(
slot
<
0
);
if
(
slot
!=
nritems
)
{
if
(
slot
!=
nritems
)
{
...
...
fs/btrfs/super.c
View file @
d4dbff95
...
@@ -136,8 +136,11 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
...
@@ -136,8 +136,11 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
err:
err:
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
if
(
ret
==
0
)
if
(
ret
==
0
)
{
inode_dec_link_count
(
dentry
->
d_inode
);
inode_dec_link_count
(
dentry
->
d_inode
);
dir
->
i_size
-=
name_len
;
mark_inode_dirty
(
dir
);
}
return
ret
;
return
ret
;
}
}
...
@@ -290,6 +293,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
...
@@ -290,6 +293,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
key
.
objectid
=
inode
->
i_ino
;
key
.
objectid
=
inode
->
i_ino
;
key
.
offset
=
(
u64
)
-
1
;
key
.
offset
=
(
u64
)
-
1
;
key
.
flags
=
0
;
key
.
flags
=
0
;
/*
* use BTRFS_CSUM_ITEM_KEY because it is larger than inline keys
* or extent data
*/
btrfs_set_key_type
(
&
key
,
BTRFS_CSUM_ITEM_KEY
);
btrfs_set_key_type
(
&
key
,
BTRFS_CSUM_ITEM_KEY
);
while
(
1
)
{
while
(
1
)
{
btrfs_init_path
(
path
);
btrfs_init_path
(
path
);
...
@@ -306,6 +313,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
...
@@ -306,6 +313,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
if
(
btrfs_disk_key_objectid
(
found_key
)
!=
inode
->
i_ino
)
if
(
btrfs_disk_key_objectid
(
found_key
)
!=
inode
->
i_ino
)
break
;
break
;
if
(
btrfs_disk_key_type
(
found_key
)
!=
BTRFS_CSUM_ITEM_KEY
&&
if
(
btrfs_disk_key_type
(
found_key
)
!=
BTRFS_CSUM_ITEM_KEY
&&
btrfs_disk_key_type
(
found_key
)
!=
BTRFS_INLINE_DATA_KEY
&&
btrfs_disk_key_type
(
found_key
)
!=
BTRFS_EXTENT_DATA_KEY
)
btrfs_disk_key_type
(
found_key
)
!=
BTRFS_EXTENT_DATA_KEY
)
break
;
break
;
if
(
btrfs_disk_key_offset
(
found_key
)
<
inode
->
i_size
)
if
(
btrfs_disk_key_offset
(
found_key
)
<
inode
->
i_size
)
...
@@ -1036,7 +1044,7 @@ static void btrfs_truncate(struct inode *inode)
...
@@ -1036,7 +1044,7 @@ static void btrfs_truncate(struct inode *inode)
if
(
IS_APPEND
(
inode
)
||
IS_IMMUTABLE
(
inode
))
if
(
IS_APPEND
(
inode
)
||
IS_IMMUTABLE
(
inode
))
return
;
return
;
nobh_truncate_page
(
inode
->
i_mapping
,
inode
->
i_size
);
//
nobh_truncate_page(inode->i_mapping, inode->i_size);
/* FIXME, add redo link to tree so we don't leak on crash */
/* FIXME, add redo link to tree so we don't leak on crash */
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
...
@@ -1309,7 +1317,9 @@ static ssize_t inline_one_page(struct btrfs_root *root, struct inode *inode,
...
@@ -1309,7 +1317,9 @@ static ssize_t inline_one_page(struct btrfs_root *root, struct inode *inode,
}
}
insert:
insert:
btrfs_release_path
(
root
,
path
);
btrfs_release_path
(
root
,
path
);
copy_size
=
min
(
write_bytes
,
(
size_t
)
512
);
copy_size
=
min
(
write_bytes
,
(
size_t
)
BTRFS_LEAF_DATA_SIZE
(
root
)
-
sizeof
(
struct
btrfs_item
)
*
4
);
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
&
key
,
copy_size
);
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
&
key
,
copy_size
);
BUG_ON
(
ret
);
BUG_ON
(
ret
);
dst
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
dst
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
...
...
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