#include <linux/compat.h>
#include <linux/bit_spinlock.h>
#include <linux/security.h>
-#include <linux/version.h>
#include <linux/xattr.h>
#include <linux/vmalloc.h>
#include "compat.h"
u64 index = 0;
unsigned long nr = 1;
- ret = btrfs_check_free_space(root, 1, 0);
+ ret = btrfs_check_metadata_free_space(root);
if (ret)
goto fail_commit;
if (ret)
goto fail;
+ btrfs_i_size_write(dir, dir->i_size + namelen * 2);
+ ret = btrfs_update_inode(trans, root, dir);
+ BUG_ON(ret);
+
/* add the backref first */
ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
objectid, BTRFS_ROOT_BACKREF_KEY,
trans = btrfs_start_transaction(new_root, 1);
BUG_ON(!trans);
- ret = btrfs_create_subvol_root(new_root, dentry, trans, new_dirid,
+ ret = btrfs_create_subvol_root(trans, new_root, dentry, new_dirid,
BTRFS_I(dir)->block_group);
if (ret)
goto fail;
if (!root->ref_cows)
return -EINVAL;
- ret = btrfs_check_free_space(root, 1, 0);
+ ret = btrfs_check_metadata_free_space(root);
if (ret)
goto fail_unlock;
goto out_dput;
if (!IS_POSIXACL(parent->dentry->d_inode))
- mode &= ~current->fs->umask;
+ mode &= ~current_umask();
error = mnt_want_write(parent->mnt);
if (error)
* to see if is references the subvolume where we are
* placing this new snapshot.
*/
- while(1) {
+ while (1) {
if (!test ||
dir == snap_src->fs_info->sb->s_root ||
test == snap_src->fs_info->sb->s_root ||
break;
}
if (S_ISLNK(test->d_inode->i_mode)) {
- printk("Symlink in snapshot path, failed\n");
+ printk(KERN_INFO "Btrfs symlink in snapshot "
+ "path, failed\n");
error = -EMLINK;
btrfs_free_path(path);
goto out_drop_write;
ret = btrfs_find_root_ref(snap_src->fs_info->tree_root,
path, test_oid, parent_oid);
if (ret == 0) {
- printk("Snapshot creation failed, looping\n");
+ printk(KERN_INFO "Btrfs snapshot creation "
+ "failed, looping\n");
error = -EMLINK;
btrfs_free_path(path);
goto out_drop_write;
unsigned long i;
int ret;
- ret = btrfs_check_free_space(root, inode->i_size, 0);
+ ret = btrfs_check_data_free_space(root, inode, inode->i_size);
if (ret)
return -ENOSPC;
if (root->fs_info->sb->s_flags & MS_RDONLY)
return -EROFS;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
if (!vol_args)
src_inode = src_file->f_path.dentry->d_inode;
if (src_inode->i_sb != file->f_path.dentry->d_inode->i_sb) {
- printk("btrfs: Snapshot src from another FS\n");
+ printk(KERN_INFO "btrfs: Snapshot src from "
+ "another FS\n");
ret = -EINVAL;
fput(src_file);
goto out;
switch (inode->i_mode & S_IFMT) {
case S_IFDIR:
+ if (!capable(CAP_SYS_ADMIN)) {
+ ret = -EPERM;
+ goto out;
+ }
btrfs_defrag_root(root, 0);
btrfs_defrag_root(root->fs_info->extent_root, 0);
break;
case S_IFREG:
+ if (!(file->f_mode & FMODE_WRITE)) {
+ ret = -EINVAL;
+ goto out;
+ }
btrfs_defrag_file(file);
break;
}
-
- return 0;
+out:
+ mnt_drop_write(file->f_path.mnt);
+ return ret;
}
static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
struct btrfs_ioctl_vol_args *vol_args;
int ret;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
if (!vol_args)
struct btrfs_ioctl_vol_args *vol_args;
int ret;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
if (root->fs_info->sb->s_flags & MS_RDONLY)
return -EROFS;
* they don't overlap)?
*/
+ /* the destination must be opened for writing */
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+
ret = mnt_want_write(file->f_path.mnt);
if (ret)
return ret;
src_file = fget(srcfd);
- if (!src_file)
- return -EBADF;
+ if (!src_file) {
+ ret = -EBADF;
+ goto out_drop_write;
+ }
src = src_file->f_dentry->d_inode;
ret = -EINVAL;
((off + len) & (bs-1)))
goto out_unlock;
- printk("final src extent is %llu~%llu\n", off, len);
- printk("final dst extent is %llu~%llu\n", destoff, len);
-
/* do any pending delalloc/csum calc on src, one way or
another, and lock file content */
while (1) {
comp = btrfs_file_extent_compression(leaf, extent);
type = btrfs_file_extent_type(leaf, extent);
if (type == BTRFS_FILE_EXTENT_REG) {
- disko = btrfs_file_extent_disk_bytenr(leaf, extent);
- diskl = btrfs_file_extent_disk_num_bytes(leaf, extent);
+ disko = btrfs_file_extent_disk_bytenr(leaf,
+ extent);
+ diskl = btrfs_file_extent_disk_num_bytes(leaf,
+ extent);
datao = btrfs_file_extent_offset(leaf, extent);
- datal = btrfs_file_extent_num_bytes(leaf, extent);
+ datal = btrfs_file_extent_num_bytes(leaf,
+ extent);
} else if (type == BTRFS_FILE_EXTENT_INLINE) {
/* take upper bound, may be compressed */
datal = btrfs_file_extent_ram_bytes(leaf,
extent = btrfs_item_ptr(leaf, slot,
struct btrfs_file_extent_item);
- printk(" orig disk %llu~%llu data %llu~%llu\n",
- disko, diskl, datao, datal);
if (off > key.offset) {
datao += off - key.offset;
/* disko == 0 means it's a hole */
if (!disko)
datao = 0;
- printk(" final disk %llu~%llu data %llu~%llu\n",
- disko, diskl, datao, datal);
btrfs_set_file_extent_offset(leaf, extent,
datao);
skip = off - key.offset;
new_key.offset += skip;
}
+
if (key.offset + datal > off+len)
trim = key.offset + datal - (off+len);
- printk("len %lld skip %lld trim %lld\n",
- datal, skip, trim);
+
if (comp && (skip || trim)) {
- printk("btrfs clone_range can't split compressed inline extents yet\n");
ret = -EINVAL;
goto out;
}
goto out;
if (skip) {
- u32 start = btrfs_file_extent_calc_inline_size(0);
+ u32 start =
+ btrfs_file_extent_calc_inline_size(0);
memmove(buf+start, buf+start+skip,
datal);
}
btrfs_mark_buffer_dirty(leaf);
}
- next:
+next:
btrfs_release_path(root, path);
key.offset++;
}
btrfs_free_path(path);
out_fput:
fput(src_file);
+out_drop_write:
+ mnt_drop_write(file->f_path.mnt);
return ret;
}