|
@@ -778,8 +778,12 @@ retry:
|
|
|
ins.offset,
|
|
|
BTRFS_ORDERED_COMPRESSED,
|
|
|
async_extent->compress_type);
|
|
|
- if (ret)
|
|
|
+ if (ret) {
|
|
|
+ btrfs_drop_extent_cache(inode, async_extent->start,
|
|
|
+ async_extent->start +
|
|
|
+ async_extent->ram_size - 1, 0);
|
|
|
goto out_free_reserve;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* clear dirty, set writeback and unlock the pages.
|
|
@@ -971,14 +975,14 @@ static noinline int cow_file_range(struct inode *inode,
|
|
|
ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
|
|
|
ram_size, cur_alloc_size, 0);
|
|
|
if (ret)
|
|
|
- goto out_reserve;
|
|
|
+ goto out_drop_extent_cache;
|
|
|
|
|
|
if (root->root_key.objectid ==
|
|
|
BTRFS_DATA_RELOC_TREE_OBJECTID) {
|
|
|
ret = btrfs_reloc_clone_csums(inode, start,
|
|
|
cur_alloc_size);
|
|
|
if (ret)
|
|
|
- goto out_reserve;
|
|
|
+ goto out_drop_extent_cache;
|
|
|
}
|
|
|
|
|
|
if (disk_num_bytes < cur_alloc_size)
|
|
@@ -1006,6 +1010,8 @@ static noinline int cow_file_range(struct inode *inode,
|
|
|
out:
|
|
|
return ret;
|
|
|
|
|
|
+out_drop_extent_cache:
|
|
|
+ btrfs_drop_extent_cache(inode, start, start + ram_size - 1, 0);
|
|
|
out_reserve:
|
|
|
btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
|
|
|
out_unlock:
|
|
@@ -4242,7 +4248,8 @@ out:
|
|
|
btrfs_abort_transaction(trans, root, ret);
|
|
|
}
|
|
|
error:
|
|
|
- if (last_size != (u64)-1)
|
|
|
+ if (last_size != (u64)-1 &&
|
|
|
+ root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
|
|
|
btrfs_ordered_update_i_size(inode, last_size, NULL);
|
|
|
btrfs_free_path(path);
|
|
|
return err;
|
|
@@ -5627,6 +5634,17 @@ int btrfs_set_inode_index(struct inode *dir, u64 *index)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int btrfs_insert_inode_locked(struct inode *inode)
|
|
|
+{
|
|
|
+ struct btrfs_iget_args args;
|
|
|
+ args.location = &BTRFS_I(inode)->location;
|
|
|
+ args.root = BTRFS_I(inode)->root;
|
|
|
+
|
|
|
+ return insert_inode_locked4(inode,
|
|
|
+ btrfs_inode_hash(inode->i_ino, BTRFS_I(inode)->root),
|
|
|
+ btrfs_find_actor, &args);
|
|
|
+}
|
|
|
+
|
|
|
static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
|
|
struct btrfs_root *root,
|
|
|
struct inode *dir,
|
|
@@ -5719,10 +5737,19 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
|
|
sizes[1] = name_len + sizeof(*ref);
|
|
|
}
|
|
|
|
|
|
+ location = &BTRFS_I(inode)->location;
|
|
|
+ location->objectid = objectid;
|
|
|
+ location->offset = 0;
|
|
|
+ btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
|
|
|
+
|
|
|
+ ret = btrfs_insert_inode_locked(inode);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
path->leave_spinning = 1;
|
|
|
ret = btrfs_insert_empty_items(trans, root, path, key, sizes, nitems);
|
|
|
if (ret != 0)
|
|
|
- goto fail;
|
|
|
+ goto fail_unlock;
|
|
|
|
|
|
inode_init_owner(inode, dir, mode);
|
|
|
inode_set_bytes(inode, 0);
|
|
@@ -5745,11 +5772,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
|
|
btrfs_mark_buffer_dirty(path->nodes[0]);
|
|
|
btrfs_free_path(path);
|
|
|
|
|
|
- location = &BTRFS_I(inode)->location;
|
|
|
- location->objectid = objectid;
|
|
|
- location->offset = 0;
|
|
|
- btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
|
|
|
-
|
|
|
btrfs_inherit_iflags(inode, dir);
|
|
|
|
|
|
if (S_ISREG(mode)) {
|
|
@@ -5760,7 +5782,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
|
|
BTRFS_INODE_NODATASUM;
|
|
|
}
|
|
|
|
|
|
- btrfs_insert_inode_hash(inode);
|
|
|
inode_tree_add(inode);
|
|
|
|
|
|
trace_btrfs_inode_new(inode);
|
|
@@ -5775,6 +5796,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
|
|
btrfs_ino(inode), root->root_key.objectid, ret);
|
|
|
|
|
|
return inode;
|
|
|
+
|
|
|
+fail_unlock:
|
|
|
+ unlock_new_inode(inode);
|
|
|
fail:
|
|
|
if (dir && name)
|
|
|
BTRFS_I(dir)->index_cnt--;
|
|
@@ -5909,28 +5933,28 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
|
|
|
- err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
- if (err) {
|
|
|
- drop_inode = 1;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* If the active LSM wants to access the inode during
|
|
|
* d_instantiate it needs these. Smack checks to see
|
|
|
* if the filesystem supports xattrs by looking at the
|
|
|
* ops vector.
|
|
|
*/
|
|
|
-
|
|
|
inode->i_op = &btrfs_special_inode_operations;
|
|
|
- err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
|
|
|
+ init_special_inode(inode, inode->i_mode, rdev);
|
|
|
+
|
|
|
+ err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
if (err)
|
|
|
- drop_inode = 1;
|
|
|
- else {
|
|
|
- init_special_inode(inode, inode->i_mode, rdev);
|
|
|
+ goto out_unlock_inode;
|
|
|
+
|
|
|
+ err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
|
|
|
+ if (err) {
|
|
|
+ goto out_unlock_inode;
|
|
|
+ } else {
|
|
|
btrfs_update_inode(trans, root, inode);
|
|
|
+ unlock_new_inode(inode);
|
|
|
d_instantiate(dentry, inode);
|
|
|
}
|
|
|
+
|
|
|
out_unlock:
|
|
|
btrfs_end_transaction(trans, root);
|
|
|
btrfs_balance_delayed_items(root);
|
|
@@ -5940,6 +5964,12 @@ out_unlock:
|
|
|
iput(inode);
|
|
|
}
|
|
|
return err;
|
|
|
+
|
|
|
+out_unlock_inode:
|
|
|
+ drop_inode = 1;
|
|
|
+ unlock_new_inode(inode);
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
|
@@ -5974,15 +6004,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
drop_inode_on_err = 1;
|
|
|
-
|
|
|
- err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
- if (err)
|
|
|
- goto out_unlock;
|
|
|
-
|
|
|
- err = btrfs_update_inode(trans, root, inode);
|
|
|
- if (err)
|
|
|
- goto out_unlock;
|
|
|
-
|
|
|
/*
|
|
|
* If the active LSM wants to access the inode during
|
|
|
* d_instantiate it needs these. Smack checks to see
|
|
@@ -5991,14 +6012,23 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
|
|
*/
|
|
|
inode->i_fop = &btrfs_file_operations;
|
|
|
inode->i_op = &btrfs_file_inode_operations;
|
|
|
+ inode->i_mapping->a_ops = &btrfs_aops;
|
|
|
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
|
|
|
+
|
|
|
+ err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
+ if (err)
|
|
|
+ goto out_unlock_inode;
|
|
|
+
|
|
|
+ err = btrfs_update_inode(trans, root, inode);
|
|
|
+ if (err)
|
|
|
+ goto out_unlock_inode;
|
|
|
|
|
|
err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
|
|
|
if (err)
|
|
|
- goto out_unlock;
|
|
|
+ goto out_unlock_inode;
|
|
|
|
|
|
- inode->i_mapping->a_ops = &btrfs_aops;
|
|
|
- inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
|
|
|
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
|
|
|
+ unlock_new_inode(inode);
|
|
|
d_instantiate(dentry, inode);
|
|
|
|
|
|
out_unlock:
|
|
@@ -6010,6 +6040,11 @@ out_unlock:
|
|
|
btrfs_balance_delayed_items(root);
|
|
|
btrfs_btree_balance_dirty(root);
|
|
|
return err;
|
|
|
+
|
|
|
+out_unlock_inode:
|
|
|
+ unlock_new_inode(inode);
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
|
@@ -6117,25 +6152,30 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
|
}
|
|
|
|
|
|
drop_on_err = 1;
|
|
|
+ /* these must be set before we unlock the inode */
|
|
|
+ inode->i_op = &btrfs_dir_inode_operations;
|
|
|
+ inode->i_fop = &btrfs_dir_file_operations;
|
|
|
|
|
|
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
if (err)
|
|
|
- goto out_fail;
|
|
|
-
|
|
|
- inode->i_op = &btrfs_dir_inode_operations;
|
|
|
- inode->i_fop = &btrfs_dir_file_operations;
|
|
|
+ goto out_fail_inode;
|
|
|
|
|
|
btrfs_i_size_write(inode, 0);
|
|
|
err = btrfs_update_inode(trans, root, inode);
|
|
|
if (err)
|
|
|
- goto out_fail;
|
|
|
+ goto out_fail_inode;
|
|
|
|
|
|
err = btrfs_add_link(trans, dir, inode, dentry->d_name.name,
|
|
|
dentry->d_name.len, 0, index);
|
|
|
if (err)
|
|
|
- goto out_fail;
|
|
|
+ goto out_fail_inode;
|
|
|
|
|
|
d_instantiate(dentry, inode);
|
|
|
+ /*
|
|
|
+ * mkdir is special. We're unlocking after we call d_instantiate
|
|
|
+ * to avoid a race with nfsd calling d_instantiate.
|
|
|
+ */
|
|
|
+ unlock_new_inode(inode);
|
|
|
drop_on_err = 0;
|
|
|
|
|
|
out_fail:
|
|
@@ -6145,6 +6185,10 @@ out_fail:
|
|
|
btrfs_balance_delayed_items(root);
|
|
|
btrfs_btree_balance_dirty(root);
|
|
|
return err;
|
|
|
+
|
|
|
+out_fail_inode:
|
|
|
+ unlock_new_inode(inode);
|
|
|
+ goto out_fail;
|
|
|
}
|
|
|
|
|
|
/* helper for btfs_get_extent. Given an existing extent in the tree,
|
|
@@ -8100,6 +8144,7 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
|
|
|
|
|
|
set_nlink(inode, 1);
|
|
|
btrfs_i_size_write(inode, 0);
|
|
|
+ unlock_new_inode(inode);
|
|
|
|
|
|
err = btrfs_subvol_inherit_props(trans, new_root, parent_root);
|
|
|
if (err)
|
|
@@ -8760,12 +8805,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
|
|
|
- err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
- if (err) {
|
|
|
- drop_inode = 1;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* If the active LSM wants to access the inode during
|
|
|
* d_instantiate it needs these. Smack checks to see
|
|
@@ -8774,23 +8813,22 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
*/
|
|
|
inode->i_fop = &btrfs_file_operations;
|
|
|
inode->i_op = &btrfs_file_inode_operations;
|
|
|
+ inode->i_mapping->a_ops = &btrfs_aops;
|
|
|
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
|
|
|
+ BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
|
|
|
+
|
|
|
+ err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
|
|
+ if (err)
|
|
|
+ goto out_unlock_inode;
|
|
|
|
|
|
err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
|
|
|
if (err)
|
|
|
- drop_inode = 1;
|
|
|
- else {
|
|
|
- inode->i_mapping->a_ops = &btrfs_aops;
|
|
|
- inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
|
|
|
- BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
|
|
|
- }
|
|
|
- if (drop_inode)
|
|
|
- goto out_unlock;
|
|
|
+ goto out_unlock_inode;
|
|
|
|
|
|
path = btrfs_alloc_path();
|
|
|
if (!path) {
|
|
|
err = -ENOMEM;
|
|
|
- drop_inode = 1;
|
|
|
- goto out_unlock;
|
|
|
+ goto out_unlock_inode;
|
|
|
}
|
|
|
key.objectid = btrfs_ino(inode);
|
|
|
key.offset = 0;
|
|
@@ -8799,9 +8837,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
err = btrfs_insert_empty_item(trans, root, path, &key,
|
|
|
datasize);
|
|
|
if (err) {
|
|
|
- drop_inode = 1;
|
|
|
btrfs_free_path(path);
|
|
|
- goto out_unlock;
|
|
|
+ goto out_unlock_inode;
|
|
|
}
|
|
|
leaf = path->nodes[0];
|
|
|
ei = btrfs_item_ptr(leaf, path->slots[0],
|
|
@@ -8825,12 +8862,15 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
inode_set_bytes(inode, name_len);
|
|
|
btrfs_i_size_write(inode, name_len);
|
|
|
err = btrfs_update_inode(trans, root, inode);
|
|
|
- if (err)
|
|
|
+ if (err) {
|
|
|
drop_inode = 1;
|
|
|
+ goto out_unlock_inode;
|
|
|
+ }
|
|
|
+
|
|
|
+ unlock_new_inode(inode);
|
|
|
+ d_instantiate(dentry, inode);
|
|
|
|
|
|
out_unlock:
|
|
|
- if (!err)
|
|
|
- d_instantiate(dentry, inode);
|
|
|
btrfs_end_transaction(trans, root);
|
|
|
if (drop_inode) {
|
|
|
inode_dec_link_count(inode);
|
|
@@ -8838,6 +8878,11 @@ out_unlock:
|
|
|
}
|
|
|
btrfs_btree_balance_dirty(root);
|
|
|
return err;
|
|
|
+
|
|
|
+out_unlock_inode:
|
|
|
+ drop_inode = 1;
|
|
|
+ unlock_new_inode(inode);
|
|
|
+ goto out_unlock;
|
|
|
}
|
|
|
|
|
|
static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
|
|
@@ -9021,14 +9066,6 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret = btrfs_init_inode_security(trans, inode, dir, NULL);
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
- ret = btrfs_update_inode(trans, root, inode);
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
inode->i_fop = &btrfs_file_operations;
|
|
|
inode->i_op = &btrfs_file_inode_operations;
|
|
|
|
|
@@ -9036,9 +9073,16 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
|
inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
|
|
|
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
|
|
|
|
|
|
+ ret = btrfs_init_inode_security(trans, inode, dir, NULL);
|
|
|
+ if (ret)
|
|
|
+ goto out_inode;
|
|
|
+
|
|
|
+ ret = btrfs_update_inode(trans, root, inode);
|
|
|
+ if (ret)
|
|
|
+ goto out_inode;
|
|
|
ret = btrfs_orphan_add(trans, inode);
|
|
|
if (ret)
|
|
|
- goto out;
|
|
|
+ goto out_inode;
|
|
|
|
|
|
/*
|
|
|
* We set number of links to 0 in btrfs_new_inode(), and here we set
|
|
@@ -9048,6 +9092,7 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|
|
* d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
|
|
|
*/
|
|
|
set_nlink(inode, 1);
|
|
|
+ unlock_new_inode(inode);
|
|
|
d_tmpfile(dentry, inode);
|
|
|
mark_inode_dirty(inode);
|
|
|
|
|
@@ -9057,8 +9102,12 @@ out:
|
|
|
iput(inode);
|
|
|
btrfs_balance_delayed_items(root);
|
|
|
btrfs_btree_balance_dirty(root);
|
|
|
-
|
|
|
return ret;
|
|
|
+
|
|
|
+out_inode:
|
|
|
+ unlock_new_inode(inode);
|
|
|
+ goto out;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
static const struct inode_operations btrfs_dir_inode_operations = {
|