struct btrfs_inode_item *inode_item;
struct extent_buffer *leaf;
struct btrfs_root *new_root;
- struct dentry *parent = dget_parent(dentry);
+ struct dentry *parent = dentry->d_parent;
struct inode *dir;
int ret;
int err;
u64 index = 0;
ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
- if (ret) {
- dput(parent);
+ if (ret)
return ret;
- }
dir = parent->d_inode;
* 2 - dir items
*/
trans = btrfs_start_transaction(root, 6);
- if (IS_ERR(trans)) {
- dput(parent);
+ if (IS_ERR(trans))
return PTR_ERR(trans);
- }
leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
0, objectid, NULL, 0, 0, 0);
d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
fail:
- dput(parent);
if (async_transid) {
*async_transid = trans->transid;
err = btrfs_commit_transaction_async(trans, root, 1);
bool readonly)
{
struct inode *inode;
- struct dentry *parent;
struct btrfs_pending_snapshot *pending_snapshot;
struct btrfs_trans_handle *trans;
int ret;
if (ret)
goto fail;
- parent = dget_parent(dentry);
- inode = btrfs_lookup_dentry(parent->d_inode, dentry);
- dput(parent);
+ inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
goto fail;
/* step one, lock all the pages */
for (i = 0; i < num_pages; i++) {
struct page *page;
- page = grab_cache_page(inode->i_mapping,
- start_index + i);
+ page = find_or_create_page(inode->i_mapping,
+ start_index + i, GFP_NOFS);
if (!page)
break;
GFP_NOFS);
if (i_done != num_pages) {
- atomic_inc(&BTRFS_I(inode)->outstanding_extents);
+ spin_lock(&BTRFS_I(inode)->lock);
+ BTRFS_I(inode)->outstanding_extents++;
+ spin_unlock(&BTRFS_I(inode)->lock);
btrfs_delalloc_release_space(inode,
(num_pages - i_done) << PAGE_CACHE_SHIFT);
}
key.objectid = key.offset;
key.offset = (u64)-1;
dirid = key.objectid;
-
}
if (ptr < name)
goto out;
- memcpy(name, ptr, total_len);
+ memmove(name, ptr, total_len);
name[total_len]='\0';
ret = 0;
out:
!IS_ALIGNED(destoff, bs))
goto out_unlock;
+ if (destoff > inode->i_size) {
+ ret = btrfs_cont_expand(inode, inode->i_size, destoff);
+ if (ret)
+ goto out_unlock;
+ }
+
/* do any pending delalloc/csum calc on src, one way or
another, and lock file content */
while (1) {
btrfs_wait_ordered_range(src, off, len);
}
+ /* truncate page cache pages from target inode range */
+ truncate_inode_pages_range(&inode->i_data, off,
+ ALIGN(off + len, PAGE_CACHE_SIZE) - 1);
+
/* clone data */
key.objectid = btrfs_ino(src);
key.type = BTRFS_EXTENT_DATA_KEY;
if (type == BTRFS_FILE_EXTENT_REG ||
type == BTRFS_FILE_EXTENT_PREALLOC) {
+ /*
+ * a | --- range to clone ---| b
+ * | ------------- extent ------------- |
+ */
+
+ /* substract range b */
+ if (key.offset + datal > off + len)
+ datal = off + len - key.offset;
+
+ /* substract range a */
if (off > key.offset) {
datao += off - key.offset;
datal -= off - key.offset;
}
- if (key.offset + datal > off + len)
- datal = off + len - key.offset;
-
ret = btrfs_drop_extents(trans, inode,
new_key.offset,
new_key.offset + datal,