Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
[pandora-kernel.git] / fs / btrfs / ioctl.c
index ac37040..0b980af 100644 (file)
@@ -323,7 +323,7 @@ static noinline int create_subvol(struct btrfs_root *root,
        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;
@@ -332,10 +332,8 @@ static noinline int create_subvol(struct btrfs_root *root,
        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;
 
@@ -346,10 +344,8 @@ static noinline int create_subvol(struct btrfs_root *root,
         * 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);
@@ -439,7 +435,6 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        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);
@@ -456,7 +451,6 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                           bool readonly)
 {
        struct inode *inode;
-       struct dentry *parent;
        struct btrfs_pending_snapshot *pending_snapshot;
        struct btrfs_trans_handle *trans;
        int ret;
@@ -482,8 +476,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        ret = btrfs_snap_reserve_metadata(trans, pending_snapshot);
        BUG_ON(ret);
 
+       spin_lock(&root->fs_info->trans_lock);
        list_add(&pending_snapshot->list,
                 &trans->transaction->pending_snapshots);
+       spin_unlock(&root->fs_info->trans_lock);
        if (async_transid) {
                *async_transid = trans->transid;
                ret = btrfs_commit_transaction_async(trans,
@@ -502,9 +498,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        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;
@@ -865,8 +859,8 @@ again:
        /* 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;
 
@@ -936,7 +930,9 @@ again:
                          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);
        }
@@ -2054,29 +2050,34 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
 
 static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg)
 {
-       struct btrfs_ioctl_fs_info_args fi_args;
+       struct btrfs_ioctl_fs_info_args *fi_args;
        struct btrfs_device *device;
        struct btrfs_device *next;
        struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
+       int ret = 0;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       fi_args.num_devices = fs_devices->num_devices;
-       fi_args.max_id = 0;
-       memcpy(&fi_args.fsid, root->fs_info->fsid, sizeof(fi_args.fsid));
+       fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL);
+       if (!fi_args)
+               return -ENOMEM;
+
+       fi_args->num_devices = fs_devices->num_devices;
+       memcpy(&fi_args->fsid, root->fs_info->fsid, sizeof(fi_args->fsid));
 
        mutex_lock(&fs_devices->device_list_mutex);
        list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) {
-               if (device->devid > fi_args.max_id)
-                       fi_args.max_id = device->devid;
+               if (device->devid > fi_args->max_id)
+                       fi_args->max_id = device->devid;
        }
        mutex_unlock(&fs_devices->device_list_mutex);
 
-       if (copy_to_user(arg, &fi_args, sizeof(fi_args)))
-               return -EFAULT;
+       if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
+               ret = -EFAULT;
 
-       return 0;
+       kfree(fi_args);
+       return ret;
 }
 
 static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)