btrfs: Remove delay_iput parameter from __start_delalloc_inodes
[sfrench/cifs-2.6.git] / fs / btrfs / inode.c
index d241285a0d2a8dea0ff858f58a5590c18298f2b0..20a385b0668fb6c609f36f248ebe7e6feeffefe2 100644 (file)
@@ -1742,12 +1742,12 @@ static void btrfs_add_delalloc_inodes(struct btrfs_root *root,
        spin_unlock(&root->delalloc_lock);
 }
 
-static void btrfs_del_delalloc_inode(struct btrfs_root *root,
-                                    struct btrfs_inode *inode)
+
+void __btrfs_del_delalloc_inode(struct btrfs_root *root,
+                               struct btrfs_inode *inode)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
 
-       spin_lock(&root->delalloc_lock);
        if (!list_empty(&inode->delalloc_inodes)) {
                list_del_init(&inode->delalloc_inodes);
                clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
@@ -1760,6 +1760,13 @@ static void btrfs_del_delalloc_inode(struct btrfs_root *root,
                        spin_unlock(&fs_info->delalloc_root_lock);
                }
        }
+}
+
+static void btrfs_del_delalloc_inode(struct btrfs_root *root,
+                                    struct btrfs_inode *inode)
+{
+       spin_lock(&root->delalloc_lock);
+       __btrfs_del_delalloc_inode(root, inode);
        spin_unlock(&root->delalloc_lock);
 }
 
@@ -4238,7 +4245,7 @@ out:
        return ret;
 }
 
-int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
+static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct inode *dir, u64 objectid,
                        const char *name, int name_len)
@@ -4319,6 +4326,200 @@ out:
        return ret;
 }
 
+/*
+ * Helper to check if the subvolume references other subvolumes or if it's
+ * default.
+ */
+static noinline int may_destroy_subvol(struct btrfs_root *root)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_path *path;
+       struct btrfs_dir_item *di;
+       struct btrfs_key key;
+       u64 dir_id;
+       int ret;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       /* Make sure this root isn't set as the default subvol */
+       dir_id = btrfs_super_root_dir(fs_info->super_copy);
+       di = btrfs_lookup_dir_item(NULL, fs_info->tree_root, path,
+                                  dir_id, "default", 7, 0);
+       if (di && !IS_ERR(di)) {
+               btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key);
+               if (key.objectid == root->root_key.objectid) {
+                       ret = -EPERM;
+                       btrfs_err(fs_info,
+                                 "deleting default subvolume %llu is not allowed",
+                                 key.objectid);
+                       goto out;
+               }
+               btrfs_release_path(path);
+       }
+
+       key.objectid = root->root_key.objectid;
+       key.type = BTRFS_ROOT_REF_KEY;
+       key.offset = (u64)-1;
+
+       ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, path, 0, 0);
+       if (ret < 0)
+               goto out;
+       BUG_ON(ret == 0);
+
+       ret = 0;
+       if (path->slots[0] > 0) {
+               path->slots[0]--;
+               btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+               if (key.objectid == root->root_key.objectid &&
+                   key.type == BTRFS_ROOT_REF_KEY)
+                       ret = -ENOTEMPTY;
+       }
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry)
+{
+       struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb);
+       struct btrfs_root *root = BTRFS_I(dir)->root;
+       struct inode *inode = d_inode(dentry);
+       struct btrfs_root *dest = BTRFS_I(inode)->root;
+       struct btrfs_trans_handle *trans;
+       struct btrfs_block_rsv block_rsv;
+       u64 root_flags;
+       u64 qgroup_reserved;
+       int ret;
+       int err;
+
+       /*
+        * Don't allow to delete a subvolume with send in progress. This is
+        * inside the inode lock so the error handling that has to drop the bit
+        * again is not run concurrently.
+        */
+       spin_lock(&dest->root_item_lock);
+       root_flags = btrfs_root_flags(&dest->root_item);
+       if (dest->send_in_progress == 0) {
+               btrfs_set_root_flags(&dest->root_item,
+                               root_flags | BTRFS_ROOT_SUBVOL_DEAD);
+               spin_unlock(&dest->root_item_lock);
+       } else {
+               spin_unlock(&dest->root_item_lock);
+               btrfs_warn(fs_info,
+                          "attempt to delete subvolume %llu during send",
+                          dest->root_key.objectid);
+               return -EPERM;
+       }
+
+       down_write(&fs_info->subvol_sem);
+
+       err = may_destroy_subvol(dest);
+       if (err)
+               goto out_up_write;
+
+       btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
+       /*
+        * One for dir inode,
+        * two for dir entries,
+        * two for root ref/backref.
+        */
+       err = btrfs_subvolume_reserve_metadata(root, &block_rsv,
+                                              5, &qgroup_reserved, true);
+       if (err)
+               goto out_up_write;
+
+       trans = btrfs_start_transaction(root, 0);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto out_release;
+       }
+       trans->block_rsv = &block_rsv;
+       trans->bytes_reserved = block_rsv.size;
+
+       btrfs_record_snapshot_destroy(trans, BTRFS_I(dir));
+
+       ret = btrfs_unlink_subvol(trans, root, dir,
+                               dest->root_key.objectid,
+                               dentry->d_name.name,
+                               dentry->d_name.len);
+       if (ret) {
+               err = ret;
+               btrfs_abort_transaction(trans, ret);
+               goto out_end_trans;
+       }
+
+       btrfs_record_root_in_trans(trans, dest);
+
+       memset(&dest->root_item.drop_progress, 0,
+               sizeof(dest->root_item.drop_progress));
+       dest->root_item.drop_level = 0;
+       btrfs_set_root_refs(&dest->root_item, 0);
+
+       if (!test_and_set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &dest->state)) {
+               ret = btrfs_insert_orphan_item(trans,
+                                       fs_info->tree_root,
+                                       dest->root_key.objectid);
+               if (ret) {
+                       btrfs_abort_transaction(trans, ret);
+                       err = ret;
+                       goto out_end_trans;
+               }
+       }
+
+       ret = btrfs_uuid_tree_rem(trans, fs_info, dest->root_item.uuid,
+                                 BTRFS_UUID_KEY_SUBVOL,
+                                 dest->root_key.objectid);
+       if (ret && ret != -ENOENT) {
+               btrfs_abort_transaction(trans, ret);
+               err = ret;
+               goto out_end_trans;
+       }
+       if (!btrfs_is_empty_uuid(dest->root_item.received_uuid)) {
+               ret = btrfs_uuid_tree_rem(trans, fs_info,
+                                         dest->root_item.received_uuid,
+                                         BTRFS_UUID_KEY_RECEIVED_SUBVOL,
+                                         dest->root_key.objectid);
+               if (ret && ret != -ENOENT) {
+                       btrfs_abort_transaction(trans, ret);
+                       err = ret;
+                       goto out_end_trans;
+               }
+       }
+
+out_end_trans:
+       trans->block_rsv = NULL;
+       trans->bytes_reserved = 0;
+       ret = btrfs_end_transaction(trans);
+       if (ret && !err)
+               err = ret;
+       inode->i_flags |= S_DEAD;
+out_release:
+       btrfs_subvolume_release_metadata(fs_info, &block_rsv);
+out_up_write:
+       up_write(&fs_info->subvol_sem);
+       if (err) {
+               spin_lock(&dest->root_item_lock);
+               root_flags = btrfs_root_flags(&dest->root_item);
+               btrfs_set_root_flags(&dest->root_item,
+                               root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
+               spin_unlock(&dest->root_item_lock);
+       } else {
+               d_invalidate(dentry);
+               btrfs_invalidate_inodes(dest);
+               ASSERT(dest->send_in_progress == 0);
+
+               /* the last ref */
+               if (dest->ino_cache_inode) {
+                       iput(dest->ino_cache_inode);
+                       dest->ino_cache_inode = NULL;
+               }
+       }
+
+       return err;
+}
+
 static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
        struct inode *inode = d_inode(dentry);
@@ -4330,7 +4531,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
                return -ENOTEMPTY;
        if (btrfs_ino(BTRFS_I(inode)) == BTRFS_FIRST_FREE_OBJECTID)
-               return -EPERM;
+               return btrfs_delete_subvolume(dir, dentry);
 
        trans = __unlink_start_trans(dir);
        if (IS_ERR(trans))
@@ -6579,8 +6780,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
                goto out_unlock_inode;
        } else {
                btrfs_update_inode(trans, root, inode);
-               unlock_new_inode(inode);
-               d_instantiate(dentry, inode);
+               d_instantiate_new(dentry, inode);
        }
 
 out_unlock:
@@ -6656,8 +6856,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
                goto out_unlock_inode;
 
        BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
-       unlock_new_inode(inode);
-       d_instantiate(dentry, inode);
+       d_instantiate_new(dentry, inode);
 
 out_unlock:
        btrfs_end_transaction(trans);
@@ -6802,12 +7001,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        if (err)
                goto out_fail_inode;
 
-       d_instantiate(dentry, inode);
-       /*
-        * mkdir is special.  We're unlocking after we call d_instantiate
-        * to avoid a race with nfsd calling d_instantiate.
-        */
-       unlock_new_inode(inode);
+       d_instantiate_new(dentry, inode);
        drop_on_err = 0;
 
 out_fail:
@@ -7083,7 +7277,7 @@ insert:
 
        err = 0;
        write_lock(&em_tree->lock);
-       err = btrfs_add_extent_mapping(em_tree, &em, start, len);
+       err = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len);
        write_unlock(&em_tree->lock);
 out:
 
@@ -8131,7 +8325,6 @@ static void __endio_write_update_ordered(struct inode *inode,
        u64 ordered_offset = offset;
        u64 ordered_bytes = bytes;
        u64 last_offset;
-       int ret;
 
        if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
                wq = fs_info->endio_freespace_worker;
@@ -8141,32 +8334,31 @@ static void __endio_write_update_ordered(struct inode *inode,
                func = btrfs_endio_write_helper;
        }
 
-again:
-       last_offset = ordered_offset;
-       ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
-                                                  &ordered_offset,
-                                                  ordered_bytes,
-                                                  uptodate);
-       if (!ret)
-               goto out_test;
-
-       btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
-       btrfs_queue_work(wq, &ordered->work);
-out_test:
-       /*
-        * If btrfs_dec_test_ordered_pending does not find any ordered extent
-        * in the range, we can exit.
-        */
-       if (ordered_offset == last_offset)
-               return;
-       /*
-        * our bio might span multiple ordered extents.  If we haven't
-        * completed the accounting for the whole dio, go back and try again
-        */
-       if (ordered_offset < offset + bytes) {
-               ordered_bytes = offset + bytes - ordered_offset;
-               ordered = NULL;
-               goto again;
+       while (ordered_offset < offset + bytes) {
+               last_offset = ordered_offset;
+               if (btrfs_dec_test_first_ordered_pending(inode, &ordered,
+                                                          &ordered_offset,
+                                                          ordered_bytes,
+                                                          uptodate)) {
+                       btrfs_init_work(&ordered->work, func,
+                                       finish_ordered_fn,
+                                       NULL, NULL);
+                       btrfs_queue_work(wq, &ordered->work);
+               }
+               /*
+                * If btrfs_dec_test_ordered_pending does not find any ordered
+                * extent in the range, we can exit.
+                */
+               if (ordered_offset == last_offset)
+                       return;
+               /*
+                * Our bio might span multiple ordered extents. In this case
+                * we keep goin until we have accounted the whole dio.
+                */
+               if (ordered_offset < offset + bytes) {
+                       ordered_bytes = offset + bytes - ordered_offset;
+                       ordered = NULL;
+               }
        }
 }
 
@@ -8705,29 +8897,19 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
 static int btrfs_writepages(struct address_space *mapping,
                            struct writeback_control *wbc)
 {
-       struct extent_io_tree *tree;
-
-       tree = &BTRFS_I(mapping->host)->io_tree;
-       return extent_writepages(tree, mapping, wbc);
+       return extent_writepages(mapping, wbc);
 }
 
 static int
 btrfs_readpages(struct file *file, struct address_space *mapping,
                struct list_head *pages, unsigned nr_pages)
 {
-       struct extent_io_tree *tree;
-       tree = &BTRFS_I(mapping->host)->io_tree;
-       return extent_readpages(tree, mapping, pages, nr_pages);
+       return extent_readpages(mapping, pages, nr_pages);
 }
+
 static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags)
 {
-       struct extent_io_tree *tree;
-       struct extent_map_tree *map;
-       int ret;
-
-       tree = &BTRFS_I(page->mapping->host)->io_tree;
-       map = &BTRFS_I(page->mapping->host)->extent_tree;
-       ret = try_release_extent_mapping(map, tree, page, gfp_flags);
+       int ret = try_release_extent_mapping(page, gfp_flags);
        if (ret == 1) {
                ClearPagePrivate(page);
                set_page_private(page, 0);
@@ -9117,7 +9299,8 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback)
                                                 BTRFS_EXTENT_DATA_KEY);
                trans->block_rsv = &fs_info->trans_block_rsv;
                if (ret != -ENOSPC && ret != -EAGAIN) {
-                       err = ret;
+                       if (ret < 0)
+                               err = ret;
                        break;
                }
 
@@ -10003,18 +10186,11 @@ struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode,
        return work;
 }
 
-void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work)
-{
-       wait_for_completion(&work->completion);
-       kfree(work);
-}
-
 /*
  * some fairly slow code that needs optimization. This walks the list
  * of all the inodes with pending delalloc and forces them to disk.
  */
-static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput,
-                                  int nr)
+static int start_delalloc_inodes(struct btrfs_root *root, int nr)
 {
        struct btrfs_inode *binode;
        struct inode *inode;
@@ -10042,12 +10218,9 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput,
                }
                spin_unlock(&root->delalloc_lock);
 
-               work = btrfs_alloc_delalloc_work(inode, delay_iput);
+               work = btrfs_alloc_delalloc_work(inode, 0);
                if (!work) {
-                       if (delay_iput)
-                               btrfs_add_delayed_iput(inode);
-                       else
-                               iput(inode);
+                       iput(inode);
                        ret = -ENOMEM;
                        goto out;
                }
@@ -10065,10 +10238,11 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput,
 out:
        list_for_each_entry_safe(work, next, &works, list) {
                list_del_init(&work->list);
-               btrfs_wait_and_free_delalloc_work(work);
+               wait_for_completion(&work->completion);
+               kfree(work);
        }
 
-       if (!list_empty_careful(&splice)) {
+       if (!list_empty(&splice)) {
                spin_lock(&root->delalloc_lock);
                list_splice_tail(&splice, &root->delalloc_inodes);
                spin_unlock(&root->delalloc_lock);
@@ -10077,7 +10251,7 @@ out:
        return ret;
 }
 
-int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
+int btrfs_start_delalloc_inodes(struct btrfs_root *root)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        int ret;
@@ -10085,14 +10259,13 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
        if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
                return -EROFS;
 
-       ret = __start_delalloc_inodes(root, delay_iput, -1);
+       ret = start_delalloc_inodes(root, -1);
        if (ret > 0)
                ret = 0;
        return ret;
 }
 
-int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
-                              int nr)
+int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int nr)
 {
        struct btrfs_root *root;
        struct list_head splice;
@@ -10115,7 +10288,7 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
                               &fs_info->delalloc_roots);
                spin_unlock(&fs_info->delalloc_root_lock);
 
-               ret = __start_delalloc_inodes(root, delay_iput, nr);
+               ret = start_delalloc_inodes(root, nr);
                btrfs_put_fs_root(root);
                if (ret < 0)
                        goto out;
@@ -10130,7 +10303,7 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
 
        ret = 0;
 out:
-       if (!list_empty_careful(&splice)) {
+       if (!list_empty(&splice)) {
                spin_lock(&fs_info->delalloc_root_lock);
                list_splice_tail(&splice, &fs_info->delalloc_roots);
                spin_unlock(&fs_info->delalloc_root_lock);
@@ -10250,8 +10423,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                goto out_unlock_inode;
        }
 
-       unlock_new_inode(inode);
-       d_instantiate(dentry, inode);
+       d_instantiate_new(dentry, inode);
 
 out_unlock:
        btrfs_end_transaction(trans);