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
5d9cd9ec
Commit
5d9cd9ec
authored
May 05, 2008
by
Chris Mason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: Fix clone ioctl to not hold the path over inserts
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
b9d86667
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
47 additions
and
32 deletions
+47
-32
fs/btrfs/inode.c
fs/btrfs/inode.c
+47
-32
No files found.
fs/btrfs/inode.c
View file @
5d9cd9ec
...
...
@@ -3101,7 +3101,7 @@ long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
return
ret
;
}
void
dup_item_to_inode
(
struct
btrfs_trans_handle
*
trans
,
int
dup_item_to_inode
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
extent_buffer
*
leaf
,
...
...
@@ -3109,19 +3109,22 @@ void dup_item_to_inode(struct btrfs_trans_handle *trans,
struct
btrfs_key
*
key
,
u64
destino
)
{
struct
btrfs_path
*
cpath
=
btrfs_alloc_path
()
;
char
*
dup
;
int
len
=
btrfs_item_size_nr
(
leaf
,
slot
);
int
dstoff
;
struct
btrfs_key
ckey
=
*
key
;
int
ret
;
int
ret
=
0
;
dup
=
kmalloc
(
len
,
GFP_NOFS
);
if
(
!
dup
)
return
-
ENOMEM
;
read_extent_buffer
(
leaf
,
dup
,
btrfs_item_ptr_offset
(
leaf
,
slot
),
len
);
btrfs_release_path
(
root
,
path
);
ckey
.
objectid
=
destino
;
ret
=
btrfs_insert_empty_item
(
trans
,
root
,
cpath
,
&
ckey
,
len
);
dstoff
=
btrfs_item_ptr_offset
(
cpath
->
nodes
[
0
],
cpath
->
slots
[
0
]);
copy_extent_buffer
(
cpath
->
nodes
[
0
],
leaf
,
dstoff
,
btrfs_item_ptr_offset
(
leaf
,
slot
),
len
);
btrfs_release_path
(
root
,
cpath
);
ret
=
btrfs_insert_item
(
trans
,
root
,
&
ckey
,
dup
,
len
);
kfree
(
dup
);
return
ret
;
}
long
btrfs_ioctl_clone
(
struct
file
*
file
,
unsigned
long
src_fd
)
...
...
@@ -3137,7 +3140,6 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
struct
btrfs_key
key
;
struct
extent_buffer
*
leaf
;
u32
nritems
;
int
nextret
;
int
slot
;
src_file
=
fget
(
src_fd
);
...
...
@@ -3174,20 +3176,32 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
0
);
path
=
btrfs_alloc_path
();
if
(
!
path
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
key
.
offset
=
0
;
key
.
type
=
BTRFS_EXTENT_DATA_KEY
;
key
.
objectid
=
src
->
i_ino
;
pos
=
0
;
path
->
reada
=
2
;
while
(
1
)
{
ret
=
btrfs_lookup_file_extent
(
trans
,
root
,
path
,
src
->
i_ino
,
pos
,
0
);
/*
* note the key will change type as we walk through the
* tree.
*/
ret
=
btrfs_search_slot
(
trans
,
root
,
&
key
,
path
,
0
,
0
);
if
(
ret
<
0
)
goto
out
;
if
(
ret
>
0
)
{
if
(
path
->
slots
[
0
]
==
0
)
{
ret
=
0
;
if
(
path
->
slots
[
0
]
>=
btrfs_header_nritems
(
path
->
nodes
[
0
]))
{
ret
=
btrfs_next_leaf
(
root
,
path
);
if
(
ret
<
0
)
goto
out
;
}
path
->
slots
[
0
]
--
;
if
(
ret
>
0
)
break
;
}
next_slot:
leaf
=
path
->
nodes
[
0
];
slot
=
path
->
slots
[
0
];
btrfs_item_key_to_cpu
(
leaf
,
&
key
,
slot
);
...
...
@@ -3195,7 +3209,8 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
if
(
btrfs_key_type
(
&
key
)
>
BTRFS_CSUM_ITEM_KEY
||
key
.
objectid
!=
src
->
i_ino
)
goto
out
;
break
;
if
(
btrfs_key_type
(
&
key
)
==
BTRFS_EXTENT_DATA_KEY
)
{
struct
btrfs_file_extent_item
*
extent
;
int
found_type
;
...
...
@@ -3225,28 +3240,28 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
}
pos
=
key
.
offset
+
len
;
}
else
if
(
found_type
==
BTRFS_FILE_EXTENT_INLINE
)
{
dup_item_to_inode
(
trans
,
root
,
path
,
leaf
,
slot
,
&
key
,
inode
->
i_ino
);
ret
=
dup_item_to_inode
(
trans
,
root
,
path
,
leaf
,
slot
,
&
key
,
inode
->
i_ino
);
if
(
ret
)
goto
out
;
pos
=
key
.
offset
+
btrfs_item_size_nr
(
leaf
,
slot
);
}
}
else
if
(
btrfs_key_type
(
&
key
)
==
BTRFS_CSUM_ITEM_KEY
)
dup_item_to_inode
(
trans
,
root
,
path
,
leaf
,
slot
,
&
key
,
inode
->
i_ino
);
}
else
if
(
btrfs_key_type
(
&
key
)
==
BTRFS_CSUM_ITEM_KEY
)
{
ret
=
dup_item_to_inode
(
trans
,
root
,
path
,
leaf
,
slot
,
&
key
,
inode
->
i_ino
);
if
(
slot
>=
nritems
-
1
)
{
nextret
=
btrfs_next_leaf
(
root
,
path
);
if
(
nextret
)
if
(
ret
)
goto
out
;
}
else
{
path
->
slots
[
0
]
++
;
}
goto
next_slot
;
key
.
offset
++
;
btrfs_release_path
(
root
,
path
);
}
ret
=
0
;
out:
btrfs_free_path
(
path
);
ret
=
0
;
inode
->
i_blocks
=
src
->
i_blocks
;
i_size_write
(
inode
,
src
->
i_size
);
...
...
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