btrfs: restrict snapshotting to own subvolumes
[pandora-kernel.git] / fs / btrfs / ioctl.c
index 72d4616..7cbe2f8 100644 (file)
@@ -252,11 +252,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
        trans = btrfs_join_transaction(root);
        BUG_ON(IS_ERR(trans));
 
+       btrfs_update_iflags(inode);
+       inode->i_ctime = CURRENT_TIME;
        ret = btrfs_update_inode(trans, root, inode);
        BUG_ON(ret);
 
-       btrfs_update_iflags(inode);
-       inode->i_ctime = CURRENT_TIME;
        btrfs_end_transaction(trans, root);
 
        mnt_drop_write(file->f_path.mnt);
@@ -858,8 +858,10 @@ static int cluster_pages_for_defrag(struct inode *inode,
                return 0;
        file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
 
+       mutex_lock(&inode->i_mutex);
        ret = btrfs_delalloc_reserve_space(inode,
                                           num_pages << PAGE_CACHE_SHIFT);
+       mutex_unlock(&inode->i_mutex);
        if (ret)
                return ret;
 again:
@@ -1325,12 +1327,17 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
                        printk(KERN_INFO "btrfs: Snapshot src from "
                               "another FS\n");
                        ret = -EINVAL;
-                       fput(src_file);
-                       goto out;
+               } else if (!inode_owner_or_capable(src_inode)) {
+                       /*
+                        * Subvolume creation is not restricted, but snapshots
+                        * are limited to own subvolumes only
+                        */
+                       ret = -EPERM;
+               } else {
+                       ret = btrfs_mksubvol(&file->f_path, name, namelen,
+                                            BTRFS_I(src_inode)->root,
+                                            transid, readonly);
                }
-               ret = btrfs_mksubvol(&file->f_path, name, namelen,
-                                    BTRFS_I(src_inode)->root,
-                                    transid, readonly);
                fput(src_file);
        }
 out:
@@ -1569,7 +1576,11 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                item_off = btrfs_item_ptr_offset(leaf, i);
                item_len = btrfs_item_size_nr(leaf, i);
 
-               if (item_len > BTRFS_SEARCH_ARGS_BUFSIZE)
+               btrfs_item_key_to_cpu(leaf, key, i);
+               if (!key_in_sk(key, sk))
+                       continue;
+
+               if (sizeof(sh) + item_len > BTRFS_SEARCH_ARGS_BUFSIZE)
                        item_len = 0;
 
                if (sizeof(sh) + item_len + *sk_offset >
@@ -1578,10 +1589,6 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                        goto overflow;
                }
 
-               btrfs_item_key_to_cpu(leaf, key, i);
-               if (!key_in_sk(key, sk))
-                       continue;
-
                sh.objectid = key->objectid;
                sh.offset = key->offset;
                sh.type = key->type;