|
@@ -1531,12 +1531,11 @@ out_check:
|
|
}
|
|
}
|
|
btrfs_release_path(path);
|
|
btrfs_release_path(path);
|
|
|
|
|
|
- if (cur_offset <= end && cow_start == (u64)-1) {
|
|
|
|
|
|
+ if (cur_offset <= end && cow_start == (u64)-1)
|
|
cow_start = cur_offset;
|
|
cow_start = cur_offset;
|
|
- cur_offset = end;
|
|
|
|
- }
|
|
|
|
|
|
|
|
if (cow_start != (u64)-1) {
|
|
if (cow_start != (u64)-1) {
|
|
|
|
+ cur_offset = end;
|
|
ret = cow_file_range(inode, locked_page, cow_start, end, end,
|
|
ret = cow_file_range(inode, locked_page, cow_start, end, end,
|
|
page_started, nr_written, 1, NULL);
|
|
page_started, nr_written, 1, NULL);
|
|
if (ret)
|
|
if (ret)
|
|
@@ -3570,10 +3569,11 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
|
|
/*
|
|
/*
|
|
* read an inode from the btree into the in-memory inode
|
|
* read an inode from the btree into the in-memory inode
|
|
*/
|
|
*/
|
|
-static int btrfs_read_locked_inode(struct inode *inode)
|
|
|
|
|
|
+static int btrfs_read_locked_inode(struct inode *inode,
|
|
|
|
+ struct btrfs_path *in_path)
|
|
{
|
|
{
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
- struct btrfs_path *path;
|
|
|
|
|
|
+ struct btrfs_path *path = in_path;
|
|
struct extent_buffer *leaf;
|
|
struct extent_buffer *leaf;
|
|
struct btrfs_inode_item *inode_item;
|
|
struct btrfs_inode_item *inode_item;
|
|
struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
@@ -3589,15 +3589,18 @@ static int btrfs_read_locked_inode(struct inode *inode)
|
|
if (!ret)
|
|
if (!ret)
|
|
filled = true;
|
|
filled = true;
|
|
|
|
|
|
- path = btrfs_alloc_path();
|
|
|
|
- if (!path)
|
|
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ if (!path) {
|
|
|
|
+ path = btrfs_alloc_path();
|
|
|
|
+ if (!path)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
|
|
memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
|
|
memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
|
|
|
|
|
|
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
|
|
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
|
|
if (ret) {
|
|
if (ret) {
|
|
- btrfs_free_path(path);
|
|
|
|
|
|
+ if (path != in_path)
|
|
|
|
+ btrfs_free_path(path);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3722,7 +3725,8 @@ cache_acl:
|
|
btrfs_ino(BTRFS_I(inode)),
|
|
btrfs_ino(BTRFS_I(inode)),
|
|
root->root_key.objectid, ret);
|
|
root->root_key.objectid, ret);
|
|
}
|
|
}
|
|
- btrfs_free_path(path);
|
|
|
|
|
|
+ if (path != in_path)
|
|
|
|
+ btrfs_free_path(path);
|
|
|
|
|
|
if (!maybe_acls)
|
|
if (!maybe_acls)
|
|
cache_no_acl(inode);
|
|
cache_no_acl(inode);
|
|
@@ -5644,8 +5648,9 @@ static struct inode *btrfs_iget_locked(struct super_block *s,
|
|
/* Get an inode object given its location and corresponding root.
|
|
/* Get an inode object given its location and corresponding root.
|
|
* Returns in *is_new if the inode was read from disk
|
|
* Returns in *is_new if the inode was read from disk
|
|
*/
|
|
*/
|
|
-struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
|
|
|
- struct btrfs_root *root, int *new)
|
|
|
|
|
|
+struct inode *btrfs_iget_path(struct super_block *s, struct btrfs_key *location,
|
|
|
|
+ struct btrfs_root *root, int *new,
|
|
|
|
+ struct btrfs_path *path)
|
|
{
|
|
{
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
|
|
|
|
@@ -5656,7 +5661,7 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
|
if (inode->i_state & I_NEW) {
|
|
if (inode->i_state & I_NEW) {
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- ret = btrfs_read_locked_inode(inode);
|
|
|
|
|
|
+ ret = btrfs_read_locked_inode(inode, path);
|
|
if (!ret) {
|
|
if (!ret) {
|
|
inode_tree_add(inode);
|
|
inode_tree_add(inode);
|
|
unlock_new_inode(inode);
|
|
unlock_new_inode(inode);
|
|
@@ -5678,6 +5683,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
|
return inode;
|
|
return inode;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
|
|
|
+ struct btrfs_root *root, int *new)
|
|
|
|
+{
|
|
|
|
+ return btrfs_iget_path(s, location, root, new, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
static struct inode *new_simple_dir(struct super_block *s,
|
|
static struct inode *new_simple_dir(struct super_block *s,
|
|
struct btrfs_key *key,
|
|
struct btrfs_key *key,
|
|
struct btrfs_root *root)
|
|
struct btrfs_root *root)
|