]> Pileus Git - ~andy/linux/blobdiff - fs/btrfs/ioctl.c
Btrfs: join the transaction in __btrfs_setxattr
[~andy/linux] / fs / btrfs / ioctl.c
index ab429fe0fa0f5fbe6fef0f586dc9b7bc18e09c1d..988fdc8b49ebb92b7ad7d5d9163f3fc23e866d16 100644 (file)
@@ -38,7 +38,6 @@
 #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"
@@ -147,6 +146,10 @@ static noinline int create_subvol(struct btrfs_root *root,
        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,
@@ -307,7 +310,7 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name,
                 * 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 ||
@@ -315,7 +318,8 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name,
                                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;
@@ -325,7 +329,8 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name,
                        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;
@@ -453,6 +458,9 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
        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)
@@ -610,7 +618,8 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
 
                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;
@@ -638,16 +647,24 @@ static int btrfs_ioctl_defrag(struct file *file)
 
        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;
        }
-
+out:
        mnt_drop_write(file->f_path.mnt);
-       return 0;
+       return ret;
 }
 
 static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
@@ -655,6 +672,9 @@ 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)
@@ -677,6 +697,9 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
        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;
 
@@ -726,6 +749,10 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
         *   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;
@@ -785,9 +812,6 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
            ((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) {
@@ -858,10 +882,13 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                        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,
@@ -891,8 +918,6 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
 
                                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;
@@ -904,8 +929,6 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                /* 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);
@@ -927,12 +950,11 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                        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;
                                }
@@ -944,7 +966,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                        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);
                                }
@@ -960,7 +983,7 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                        btrfs_mark_buffer_dirty(leaf);
                }
 
-       next:
+next:
                btrfs_release_path(root, path);
                key.offset++;
        }