blob: a492fd238c887a145af5a9634d33c7417e275861 [file] [log] [blame]
Chris Mason6cbd5572007-06-12 09:07:21 -04001/*
2 * Copyright (C) 2007 Oracle. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
17 */
18
Chris Mason8f18cf12008-04-25 16:53:30 -040019#include <linux/kernel.h>
Chris Mason065631f2008-02-20 12:07:25 -050020#include <linux/bio.h>
Chris Mason39279cc2007-06-12 06:35:45 -040021#include <linux/buffer_head.h>
Sage Weilf2eb0a22008-05-02 14:43:14 -040022#include <linux/file.h>
Chris Mason39279cc2007-06-12 06:35:45 -040023#include <linux/fs.h>
24#include <linux/pagemap.h>
25#include <linux/highmem.h>
26#include <linux/time.h>
27#include <linux/init.h>
28#include <linux/string.h>
29#include <linux/smp_lock.h>
30#include <linux/backing-dev.h>
31#include <linux/mpage.h>
32#include <linux/swap.h>
33#include <linux/writeback.h>
34#include <linux/statfs.h>
35#include <linux/compat.h>
Chris Mason9ebefb182007-06-15 13:50:00 -040036#include <linux/bit_spinlock.h>
Chris Mason92fee662007-07-25 12:31:35 -040037#include <linux/version.h>
Josef Bacik5103e942007-11-16 11:45:54 -050038#include <linux/xattr.h>
Chris Mason39279cc2007-06-12 06:35:45 -040039#include "ctree.h"
40#include "disk-io.h"
41#include "transaction.h"
42#include "btrfs_inode.h"
43#include "ioctl.h"
44#include "print-tree.h"
Chris Mason0b86a832008-03-24 15:01:56 -040045#include "volumes.h"
Chris Mason39279cc2007-06-12 06:35:45 -040046
47struct btrfs_iget_args {
48 u64 ino;
49 struct btrfs_root *root;
50};
51
52static struct inode_operations btrfs_dir_inode_operations;
53static struct inode_operations btrfs_symlink_inode_operations;
54static struct inode_operations btrfs_dir_ro_inode_operations;
Josef Bacik618e21d2007-07-11 10:18:17 -040055static struct inode_operations btrfs_special_inode_operations;
Chris Mason39279cc2007-06-12 06:35:45 -040056static struct inode_operations btrfs_file_inode_operations;
57static struct address_space_operations btrfs_aops;
58static struct address_space_operations btrfs_symlink_aops;
59static struct file_operations btrfs_dir_file_operations;
Chris Masond1310b22008-01-24 16:13:08 -050060static struct extent_io_ops btrfs_extent_io_ops;
Chris Mason39279cc2007-06-12 06:35:45 -040061
62static struct kmem_cache *btrfs_inode_cachep;
63struct kmem_cache *btrfs_trans_handle_cachep;
64struct kmem_cache *btrfs_transaction_cachep;
65struct kmem_cache *btrfs_bit_radix_cachep;
66struct kmem_cache *btrfs_path_cachep;
67
68#define S_SHIFT 12
69static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
70 [S_IFREG >> S_SHIFT] = BTRFS_FT_REG_FILE,
71 [S_IFDIR >> S_SHIFT] = BTRFS_FT_DIR,
72 [S_IFCHR >> S_SHIFT] = BTRFS_FT_CHRDEV,
73 [S_IFBLK >> S_SHIFT] = BTRFS_FT_BLKDEV,
74 [S_IFIFO >> S_SHIFT] = BTRFS_FT_FIFO,
75 [S_IFSOCK >> S_SHIFT] = BTRFS_FT_SOCK,
76 [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK,
77};
78
Chris Mason1832a6d2007-12-21 16:27:21 -050079int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
80 int for_del)
81{
82 u64 total = btrfs_super_total_bytes(&root->fs_info->super_copy);
83 u64 used = btrfs_super_bytes_used(&root->fs_info->super_copy);
84 u64 thresh;
Chris Masonbcbfce82008-04-22 13:26:47 -040085 unsigned long flags;
Chris Mason1832a6d2007-12-21 16:27:21 -050086 int ret = 0;
87
88 if (for_del)
Chris Masonf9ef6602008-01-03 09:22:38 -050089 thresh = total * 90;
Chris Mason1832a6d2007-12-21 16:27:21 -050090 else
Chris Masonf9ef6602008-01-03 09:22:38 -050091 thresh = total * 85;
92
93 do_div(thresh, 100);
Chris Mason1832a6d2007-12-21 16:27:21 -050094
Chris Masonbcbfce82008-04-22 13:26:47 -040095 spin_lock_irqsave(&root->fs_info->delalloc_lock, flags);
Chris Mason1832a6d2007-12-21 16:27:21 -050096 if (used + root->fs_info->delalloc_bytes + num_required > thresh)
97 ret = -ENOSPC;
Chris Masonbcbfce82008-04-22 13:26:47 -040098 spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags);
Chris Mason1832a6d2007-12-21 16:27:21 -050099 return ret;
100}
101
Chris Masonbe20aa92007-12-17 20:14:01 -0500102static int cow_file_range(struct inode *inode, u64 start, u64 end)
Chris Masonb888db22007-08-27 16:49:44 -0400103{
104 struct btrfs_root *root = BTRFS_I(inode)->root;
105 struct btrfs_trans_handle *trans;
Chris Masonb888db22007-08-27 16:49:44 -0400106 u64 alloc_hint = 0;
Chris Masondb945352007-10-15 16:15:53 -0400107 u64 num_bytes;
Chris Masonc59f8952007-12-17 20:14:04 -0500108 u64 cur_alloc_size;
Chris Masondb945352007-10-15 16:15:53 -0400109 u64 blocksize = root->sectorsize;
Chris Masond1310b22008-01-24 16:13:08 -0500110 u64 orig_start = start;
111 u64 orig_num_bytes;
Chris Masonbe20aa92007-12-17 20:14:01 -0500112 struct btrfs_key ins;
113 int ret;
Chris Masonb888db22007-08-27 16:49:44 -0400114
Chris Masonb888db22007-08-27 16:49:44 -0400115 trans = btrfs_start_transaction(root, 1);
Chris Masonb888db22007-08-27 16:49:44 -0400116 BUG_ON(!trans);
Chris Masonbe20aa92007-12-17 20:14:01 -0500117 btrfs_set_trans_block_group(trans, inode);
118
Chris Masondb945352007-10-15 16:15:53 -0400119 num_bytes = (end - start + blocksize) & ~(blocksize - 1);
Chris Masonbe20aa92007-12-17 20:14:01 -0500120 num_bytes = max(blocksize, num_bytes);
Chris Masonb888db22007-08-27 16:49:44 -0400121 ret = btrfs_drop_extents(trans, root, inode,
Chris Mason3326d1b2007-10-15 16:18:25 -0400122 start, start + num_bytes, start, &alloc_hint);
Chris Masond1310b22008-01-24 16:13:08 -0500123 orig_num_bytes = num_bytes;
Chris Masondb945352007-10-15 16:15:53 -0400124
Chris Mason179e29e2007-11-01 11:28:41 -0400125 if (alloc_hint == EXTENT_MAP_INLINE)
126 goto out;
127
Chris Mason3b951512008-04-17 11:29:12 -0400128 BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy));
129
Chris Masonc59f8952007-12-17 20:14:04 -0500130 while(num_bytes > 0) {
131 cur_alloc_size = min(num_bytes, root->fs_info->max_extent);
132 ret = btrfs_alloc_extent(trans, root, cur_alloc_size,
Chris Mason98d20f62008-04-14 09:46:10 -0400133 root->sectorsize,
Chris Masonc59f8952007-12-17 20:14:04 -0500134 root->root_key.objectid,
135 trans->transid,
136 inode->i_ino, start, 0,
137 alloc_hint, (u64)-1, &ins, 1);
138 if (ret) {
139 WARN_ON(1);
140 goto out;
141 }
Chris Mason98d20f62008-04-14 09:46:10 -0400142 cur_alloc_size = ins.offset;
Chris Masonc59f8952007-12-17 20:14:04 -0500143 ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
144 start, ins.objectid, ins.offset,
Sage Weilf2eb0a22008-05-02 14:43:14 -0400145 ins.offset, 0);
Chris Mason90692182008-02-08 13:49:28 -0500146 inode->i_blocks += ins.offset >> 9;
Chris Mason5f564062008-01-22 16:47:59 -0500147 btrfs_check_file(root, inode);
Chris Mason3b951512008-04-17 11:29:12 -0400148 if (num_bytes < cur_alloc_size) {
149 printk("num_bytes %Lu cur_alloc %Lu\n", num_bytes,
150 cur_alloc_size);
151 break;
152 }
Chris Masonc59f8952007-12-17 20:14:04 -0500153 num_bytes -= cur_alloc_size;
154 alloc_hint = ins.objectid + ins.offset;
155 start += cur_alloc_size;
Chris Masonb888db22007-08-27 16:49:44 -0400156 }
Chris Masond1310b22008-01-24 16:13:08 -0500157 btrfs_drop_extent_cache(inode, orig_start,
158 orig_start + orig_num_bytes - 1);
Chris Masondc17ff82008-01-08 15:46:30 -0500159 btrfs_add_ordered_inode(inode);
Chris Mason90692182008-02-08 13:49:28 -0500160 btrfs_update_inode(trans, root, inode);
Chris Masonb888db22007-08-27 16:49:44 -0400161out:
162 btrfs_end_transaction(trans, root);
Chris Masonbe20aa92007-12-17 20:14:01 -0500163 return ret;
164}
165
166static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end)
167{
168 u64 extent_start;
169 u64 extent_end;
170 u64 bytenr;
171 u64 cow_end;
Chris Mason1832a6d2007-12-21 16:27:21 -0500172 u64 loops = 0;
Chris Masonc31f8832008-01-08 15:46:31 -0500173 u64 total_fs_bytes;
Chris Masonbe20aa92007-12-17 20:14:01 -0500174 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masona68d5932008-05-08 14:11:56 -0400175 struct btrfs_block_group_cache *block_group;
Chris Masonbe20aa92007-12-17 20:14:01 -0500176 struct extent_buffer *leaf;
177 int found_type;
178 struct btrfs_path *path;
179 struct btrfs_file_extent_item *item;
180 int ret;
181 int err;
182 struct btrfs_key found_key;
183
Chris Masonc31f8832008-01-08 15:46:31 -0500184 total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
Chris Masonbe20aa92007-12-17 20:14:01 -0500185 path = btrfs_alloc_path();
186 BUG_ON(!path);
187again:
188 ret = btrfs_lookup_file_extent(NULL, root, path,
189 inode->i_ino, start, 0);
190 if (ret < 0) {
191 btrfs_free_path(path);
192 return ret;
193 }
194
195 cow_end = end;
196 if (ret != 0) {
197 if (path->slots[0] == 0)
198 goto not_found;
199 path->slots[0]--;
200 }
201
202 leaf = path->nodes[0];
203 item = btrfs_item_ptr(leaf, path->slots[0],
204 struct btrfs_file_extent_item);
205
206 /* are we inside the extent that was found? */
207 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
208 found_type = btrfs_key_type(&found_key);
209 if (found_key.objectid != inode->i_ino ||
Chris Masonbbaf5492008-05-08 16:31:21 -0400210 found_type != BTRFS_EXTENT_DATA_KEY)
Chris Masonbe20aa92007-12-17 20:14:01 -0500211 goto not_found;
Chris Masonbe20aa92007-12-17 20:14:01 -0500212
213 found_type = btrfs_file_extent_type(leaf, item);
214 extent_start = found_key.offset;
215 if (found_type == BTRFS_FILE_EXTENT_REG) {
Chris Masonc31f8832008-01-08 15:46:31 -0500216 u64 extent_num_bytes;
217
218 extent_num_bytes = btrfs_file_extent_num_bytes(leaf, item);
219 extent_end = extent_start + extent_num_bytes;
Chris Masonbe20aa92007-12-17 20:14:01 -0500220 err = 0;
221
Chris Mason1832a6d2007-12-21 16:27:21 -0500222 if (loops && start != extent_start)
223 goto not_found;
224
Chris Masonbe20aa92007-12-17 20:14:01 -0500225 if (start < extent_start || start >= extent_end)
226 goto not_found;
227
228 cow_end = min(end, extent_end - 1);
229 bytenr = btrfs_file_extent_disk_bytenr(leaf, item);
230 if (bytenr == 0)
231 goto not_found;
232
Chris Masona68d5932008-05-08 14:11:56 -0400233 if (btrfs_count_snapshots_in_path(root, path, inode->i_ino,
234 bytenr) != 1) {
235 goto not_found;
236 }
237
Chris Masonc31f8832008-01-08 15:46:31 -0500238 /*
239 * we may be called by the resizer, make sure we're inside
240 * the limits of the FS
241 */
Chris Masona68d5932008-05-08 14:11:56 -0400242 block_group = btrfs_lookup_block_group(root->fs_info,
243 bytenr);
244 if (!block_group || block_group->ro)
Chris Masonc31f8832008-01-08 15:46:31 -0500245 goto not_found;
246
Chris Masonbe20aa92007-12-17 20:14:01 -0500247 start = extent_end;
Chris Masonbd098352008-01-03 13:23:19 -0500248 } else {
Chris Masonbe20aa92007-12-17 20:14:01 -0500249 goto not_found;
250 }
251loop:
252 if (start > end) {
253 btrfs_free_path(path);
254 return 0;
255 }
256 btrfs_release_path(root, path);
Chris Mason1832a6d2007-12-21 16:27:21 -0500257 loops++;
Chris Masonbe20aa92007-12-17 20:14:01 -0500258 goto again;
259
260not_found:
Chris Masonbbaf5492008-05-08 16:31:21 -0400261 cow_file_range(inode, start, end);
262 start = end + 1;
Chris Masonbe20aa92007-12-17 20:14:01 -0500263 goto loop;
264}
265
266static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
267{
268 struct btrfs_root *root = BTRFS_I(inode)->root;
269 int ret;
Chris Masonbe20aa92007-12-17 20:14:01 -0500270 mutex_lock(&root->fs_info->fs_mutex);
Yanb98b6762008-01-08 15:54:37 -0500271 if (btrfs_test_opt(root, NODATACOW) ||
272 btrfs_test_flag(inode, NODATACOW))
Chris Masonbe20aa92007-12-17 20:14:01 -0500273 ret = run_delalloc_nocow(inode, start, end);
274 else
275 ret = cow_file_range(inode, start, end);
Chris Mason1832a6d2007-12-21 16:27:21 -0500276
Chris Masonb888db22007-08-27 16:49:44 -0400277 mutex_unlock(&root->fs_info->fs_mutex);
278 return ret;
279}
280
Chris Mason291d6732008-01-29 15:55:23 -0500281int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
Chris Masonb0c68f82008-01-31 11:05:37 -0500282 unsigned long old, unsigned long bits)
Chris Mason291d6732008-01-29 15:55:23 -0500283{
Chris Masonbcbfce82008-04-22 13:26:47 -0400284 unsigned long flags;
Chris Masonb0c68f82008-01-31 11:05:37 -0500285 if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
Chris Mason291d6732008-01-29 15:55:23 -0500286 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masonbcbfce82008-04-22 13:26:47 -0400287 spin_lock_irqsave(&root->fs_info->delalloc_lock, flags);
Chris Mason90692182008-02-08 13:49:28 -0500288 BTRFS_I(inode)->delalloc_bytes += end - start + 1;
Chris Mason291d6732008-01-29 15:55:23 -0500289 root->fs_info->delalloc_bytes += end - start + 1;
Chris Masonbcbfce82008-04-22 13:26:47 -0400290 spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags);
Chris Mason291d6732008-01-29 15:55:23 -0500291 }
292 return 0;
293}
294
295int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
Chris Masonb0c68f82008-01-31 11:05:37 -0500296 unsigned long old, unsigned long bits)
Chris Mason291d6732008-01-29 15:55:23 -0500297{
Chris Masonb0c68f82008-01-31 11:05:37 -0500298 if ((old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
Chris Mason291d6732008-01-29 15:55:23 -0500299 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masonbcbfce82008-04-22 13:26:47 -0400300 unsigned long flags;
301
302 spin_lock_irqsave(&root->fs_info->delalloc_lock, flags);
Chris Masonb0c68f82008-01-31 11:05:37 -0500303 if (end - start + 1 > root->fs_info->delalloc_bytes) {
304 printk("warning: delalloc account %Lu %Lu\n",
305 end - start + 1, root->fs_info->delalloc_bytes);
306 root->fs_info->delalloc_bytes = 0;
Chris Mason90692182008-02-08 13:49:28 -0500307 BTRFS_I(inode)->delalloc_bytes = 0;
Chris Masonb0c68f82008-01-31 11:05:37 -0500308 } else {
309 root->fs_info->delalloc_bytes -= end - start + 1;
Chris Mason90692182008-02-08 13:49:28 -0500310 BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
Chris Masonb0c68f82008-01-31 11:05:37 -0500311 }
Chris Masonbcbfce82008-04-22 13:26:47 -0400312 spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags);
Chris Mason291d6732008-01-29 15:55:23 -0500313 }
314 return 0;
315}
316
Chris Mason239b14b2008-03-24 15:02:07 -0400317int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
318 size_t size, struct bio *bio)
319{
320 struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
321 struct btrfs_mapping_tree *map_tree;
Chris Mason239b14b2008-03-24 15:02:07 -0400322 u64 logical = bio->bi_sector << 9;
Chris Mason239b14b2008-03-24 15:02:07 -0400323 u64 length = 0;
324 u64 map_length;
Chris Mason239b14b2008-03-24 15:02:07 -0400325 int ret;
326
Chris Masonf2d8d742008-04-21 10:03:05 -0400327 length = bio->bi_size;
Chris Mason239b14b2008-03-24 15:02:07 -0400328 map_tree = &root->fs_info->mapping_tree;
329 map_length = length;
Chris Masoncea9e442008-04-09 16:28:12 -0400330 ret = btrfs_map_block(map_tree, READ, logical,
Chris Masonf1885912008-04-09 16:28:12 -0400331 &map_length, NULL, 0);
Chris Masoncea9e442008-04-09 16:28:12 -0400332
Chris Mason239b14b2008-03-24 15:02:07 -0400333 if (map_length < length + size) {
Chris Mason239b14b2008-03-24 15:02:07 -0400334 return 1;
335 }
336 return 0;
337}
338
Chris Mason44b8bd72008-04-16 11:14:51 -0400339int __btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
Chris Masonf1885912008-04-09 16:28:12 -0400340 int mirror_num)
Chris Mason065631f2008-02-20 12:07:25 -0500341{
Chris Mason065631f2008-02-20 12:07:25 -0500342 struct btrfs_root *root = BTRFS_I(inode)->root;
343 struct btrfs_trans_handle *trans;
344 int ret = 0;
Chris Masone0156402008-04-16 11:15:20 -0400345 char *sums = NULL;
346
347 ret = btrfs_csum_one_bio(root, bio, &sums);
348 BUG_ON(ret);
Chris Mason065631f2008-02-20 12:07:25 -0500349
Chris Mason44b8bd72008-04-16 11:14:51 -0400350 mutex_lock(&root->fs_info->fs_mutex);
351 trans = btrfs_start_transaction(root, 1);
Chris Masone0156402008-04-16 11:15:20 -0400352
Chris Mason44b8bd72008-04-16 11:14:51 -0400353 btrfs_set_trans_block_group(trans, inode);
Chris Masone0156402008-04-16 11:15:20 -0400354 btrfs_csum_file_blocks(trans, root, inode, bio, sums);
355
Chris Mason44b8bd72008-04-16 11:14:51 -0400356 ret = btrfs_end_transaction(trans, root);
357 BUG_ON(ret);
358 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masone0156402008-04-16 11:15:20 -0400359
360 kfree(sums);
361
Chris Mason44b8bd72008-04-16 11:14:51 -0400362 return btrfs_map_bio(root, rw, bio, mirror_num);
363}
364
365int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
366 int mirror_num)
367{
368 struct btrfs_root *root = BTRFS_I(inode)->root;
369 int ret = 0;
370
Chris Mason22c59942008-04-09 16:28:12 -0400371 if (!(rw & (1 << BIO_RW))) {
372 ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
373 BUG_ON(ret);
Chris Mason0b86a832008-03-24 15:01:56 -0400374 goto mapit;
375 }
Chris Mason065631f2008-02-20 12:07:25 -0500376
377 if (btrfs_test_opt(root, NODATASUM) ||
Chris Mason0b86a832008-03-24 15:01:56 -0400378 btrfs_test_flag(inode, NODATASUM)) {
379 goto mapit;
380 }
Chris Mason065631f2008-02-20 12:07:25 -0500381
Chris Mason44b8bd72008-04-16 11:14:51 -0400382 return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info,
383 inode, rw, bio, mirror_num,
384 __btrfs_submit_bio_hook);
Chris Mason0b86a832008-03-24 15:01:56 -0400385mapit:
Chris Masonf1885912008-04-09 16:28:12 -0400386 return btrfs_map_bio(root, rw, bio, mirror_num);
Chris Mason065631f2008-02-20 12:07:25 -0500387}
Chris Mason6885f302008-02-20 16:11:05 -0500388
Chris Mason07157aa2007-08-30 08:50:51 -0400389int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
390{
391 int ret = 0;
392 struct inode *inode = page->mapping->host;
393 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masond1310b22008-01-24 16:13:08 -0500394 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
Chris Mason07157aa2007-08-30 08:50:51 -0400395 struct btrfs_csum_item *item;
396 struct btrfs_path *path = NULL;
Chris Masonff79f812007-10-15 16:22:25 -0400397 u32 csum;
Chris Mason699122f2008-04-16 12:59:22 -0400398
Yanb98b6762008-01-08 15:54:37 -0500399 if (btrfs_test_opt(root, NODATASUM) ||
400 btrfs_test_flag(inode, NODATASUM))
Chris Masonb6cda9b2007-12-14 15:30:32 -0500401 return 0;
Chris Mason699122f2008-04-16 12:59:22 -0400402
Chris Mason07157aa2007-08-30 08:50:51 -0400403 mutex_lock(&root->fs_info->fs_mutex);
404 path = btrfs_alloc_path();
405 item = btrfs_lookup_csum(NULL, root, path, inode->i_ino, start, 0);
406 if (IS_ERR(item)) {
407 ret = PTR_ERR(item);
408 /* a csum that isn't present is a preallocated region. */
409 if (ret == -ENOENT || ret == -EFBIG)
410 ret = 0;
Chris Masonff79f812007-10-15 16:22:25 -0400411 csum = 0;
Chris Masonaadfeb62008-01-29 09:10:27 -0500412 printk("no csum found for inode %lu start %Lu\n", inode->i_ino, start);
Chris Mason07157aa2007-08-30 08:50:51 -0400413 goto out;
414 }
Chris Masonff79f812007-10-15 16:22:25 -0400415 read_extent_buffer(path->nodes[0], &csum, (unsigned long)item,
416 BTRFS_CRC32_SIZE);
Chris Masond1310b22008-01-24 16:13:08 -0500417 set_state_private(io_tree, start, csum);
Chris Mason07157aa2007-08-30 08:50:51 -0400418out:
419 if (path)
420 btrfs_free_path(path);
421 mutex_unlock(&root->fs_info->fs_mutex);
422 return ret;
423}
424
Chris Mason7e383262008-04-09 16:28:12 -0400425struct io_failure_record {
426 struct page *page;
427 u64 start;
428 u64 len;
429 u64 logical;
430 int last_mirror;
431};
432
433int btrfs_readpage_io_failed_hook(struct bio *failed_bio,
434 struct page *page, u64 start, u64 end,
435 struct extent_state *state)
436{
437 struct io_failure_record *failrec = NULL;
438 u64 private;
439 struct extent_map *em;
440 struct inode *inode = page->mapping->host;
441 struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree;
Chris Mason3b951512008-04-17 11:29:12 -0400442 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
Chris Mason7e383262008-04-09 16:28:12 -0400443 struct bio *bio;
444 int num_copies;
445 int ret;
446 u64 logical;
447
448 ret = get_state_private(failure_tree, start, &private);
449 if (ret) {
Chris Mason7e383262008-04-09 16:28:12 -0400450 failrec = kmalloc(sizeof(*failrec), GFP_NOFS);
451 if (!failrec)
452 return -ENOMEM;
453 failrec->start = start;
454 failrec->len = end - start + 1;
455 failrec->last_mirror = 0;
456
Chris Mason3b951512008-04-17 11:29:12 -0400457 spin_lock(&em_tree->lock);
458 em = lookup_extent_mapping(em_tree, start, failrec->len);
459 if (em->start > start || em->start + em->len < start) {
460 free_extent_map(em);
461 em = NULL;
462 }
463 spin_unlock(&em_tree->lock);
Chris Mason7e383262008-04-09 16:28:12 -0400464
465 if (!em || IS_ERR(em)) {
466 kfree(failrec);
467 return -EIO;
468 }
469 logical = start - em->start;
470 logical = em->block_start + logical;
471 failrec->logical = logical;
472 free_extent_map(em);
473 set_extent_bits(failure_tree, start, end, EXTENT_LOCKED |
474 EXTENT_DIRTY, GFP_NOFS);
Chris Mason587f7702008-04-11 12:16:46 -0400475 set_state_private(failure_tree, start,
476 (u64)(unsigned long)failrec);
Chris Mason7e383262008-04-09 16:28:12 -0400477 } else {
Chris Mason587f7702008-04-11 12:16:46 -0400478 failrec = (struct io_failure_record *)(unsigned long)private;
Chris Mason7e383262008-04-09 16:28:12 -0400479 }
480 num_copies = btrfs_num_copies(
481 &BTRFS_I(inode)->root->fs_info->mapping_tree,
482 failrec->logical, failrec->len);
483 failrec->last_mirror++;
484 if (!state) {
485 spin_lock_irq(&BTRFS_I(inode)->io_tree.lock);
486 state = find_first_extent_bit_state(&BTRFS_I(inode)->io_tree,
487 failrec->start,
488 EXTENT_LOCKED);
489 if (state && state->start != failrec->start)
490 state = NULL;
491 spin_unlock_irq(&BTRFS_I(inode)->io_tree.lock);
492 }
493 if (!state || failrec->last_mirror > num_copies) {
494 set_state_private(failure_tree, failrec->start, 0);
495 clear_extent_bits(failure_tree, failrec->start,
496 failrec->start + failrec->len - 1,
497 EXTENT_LOCKED | EXTENT_DIRTY, GFP_NOFS);
498 kfree(failrec);
499 return -EIO;
500 }
501 bio = bio_alloc(GFP_NOFS, 1);
502 bio->bi_private = state;
503 bio->bi_end_io = failed_bio->bi_end_io;
504 bio->bi_sector = failrec->logical >> 9;
505 bio->bi_bdev = failed_bio->bi_bdev;
Chris Masone1c4b742008-04-22 13:26:46 -0400506 bio->bi_size = 0;
Chris Mason7e383262008-04-09 16:28:12 -0400507 bio_add_page(bio, page, failrec->len, start - page_offset(page));
508 btrfs_submit_bio_hook(inode, READ, bio, failrec->last_mirror);
509 return 0;
510}
511
Chris Mason70dec802008-01-29 09:59:12 -0500512int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
513 struct extent_state *state)
Chris Mason07157aa2007-08-30 08:50:51 -0400514{
Chris Mason35ebb932007-10-30 16:56:53 -0400515 size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT);
Chris Mason07157aa2007-08-30 08:50:51 -0400516 struct inode *inode = page->mapping->host;
Chris Masond1310b22008-01-24 16:13:08 -0500517 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
Chris Mason07157aa2007-08-30 08:50:51 -0400518 char *kaddr;
Chris Masonaadfeb62008-01-29 09:10:27 -0500519 u64 private = ~(u32)0;
Chris Mason07157aa2007-08-30 08:50:51 -0400520 int ret;
Chris Masonff79f812007-10-15 16:22:25 -0400521 struct btrfs_root *root = BTRFS_I(inode)->root;
522 u32 csum = ~(u32)0;
Jens Axboebbf0d002007-10-19 09:23:07 -0400523 unsigned long flags;
Chris Masond1310b22008-01-24 16:13:08 -0500524
Yanb98b6762008-01-08 15:54:37 -0500525 if (btrfs_test_opt(root, NODATASUM) ||
526 btrfs_test_flag(inode, NODATASUM))
Chris Masonb6cda9b2007-12-14 15:30:32 -0500527 return 0;
Yanc2e639f2008-02-04 08:57:25 -0500528 if (state && state->start == start) {
Chris Mason70dec802008-01-29 09:59:12 -0500529 private = state->private;
530 ret = 0;
531 } else {
532 ret = get_state_private(io_tree, start, &private);
533 }
Jens Axboebbf0d002007-10-19 09:23:07 -0400534 local_irq_save(flags);
Chris Mason07157aa2007-08-30 08:50:51 -0400535 kaddr = kmap_atomic(page, KM_IRQ0);
536 if (ret) {
537 goto zeroit;
538 }
Chris Masonff79f812007-10-15 16:22:25 -0400539 csum = btrfs_csum_data(root, kaddr + offset, csum, end - start + 1);
540 btrfs_csum_final(csum, (char *)&csum);
541 if (csum != private) {
Chris Mason07157aa2007-08-30 08:50:51 -0400542 goto zeroit;
543 }
544 kunmap_atomic(kaddr, KM_IRQ0);
Jens Axboebbf0d002007-10-19 09:23:07 -0400545 local_irq_restore(flags);
Chris Mason7e383262008-04-09 16:28:12 -0400546
547 /* if the io failure tree for this inode is non-empty,
548 * check to see if we've recovered from a failed IO
549 */
550 private = 0;
551 if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private,
552 (u64)-1, 1, EXTENT_DIRTY)) {
553 u64 private_failure;
554 struct io_failure_record *failure;
555 ret = get_state_private(&BTRFS_I(inode)->io_failure_tree,
556 start, &private_failure);
557 if (ret == 0) {
Chris Mason587f7702008-04-11 12:16:46 -0400558 failure = (struct io_failure_record *)(unsigned long)
559 private_failure;
Chris Mason7e383262008-04-09 16:28:12 -0400560 set_state_private(&BTRFS_I(inode)->io_failure_tree,
561 failure->start, 0);
562 clear_extent_bits(&BTRFS_I(inode)->io_failure_tree,
563 failure->start,
564 failure->start + failure->len - 1,
565 EXTENT_DIRTY | EXTENT_LOCKED,
566 GFP_NOFS);
567 kfree(failure);
568 }
569 }
Chris Mason07157aa2007-08-30 08:50:51 -0400570 return 0;
571
572zeroit:
Chris Masonaadfeb62008-01-29 09:10:27 -0500573 printk("btrfs csum failed ino %lu off %llu csum %u private %Lu\n",
574 page->mapping->host->i_ino, (unsigned long long)start, csum,
575 private);
Chris Masondb945352007-10-15 16:15:53 -0400576 memset(kaddr + offset, 1, end - start + 1);
577 flush_dcache_page(page);
Chris Mason07157aa2007-08-30 08:50:51 -0400578 kunmap_atomic(kaddr, KM_IRQ0);
Jens Axboebbf0d002007-10-19 09:23:07 -0400579 local_irq_restore(flags);
Chris Mason3b951512008-04-17 11:29:12 -0400580 if (private == 0)
581 return 0;
Chris Mason7e383262008-04-09 16:28:12 -0400582 return -EIO;
Chris Mason07157aa2007-08-30 08:50:51 -0400583}
Chris Masonb888db22007-08-27 16:49:44 -0400584
Chris Mason39279cc2007-06-12 06:35:45 -0400585void btrfs_read_locked_inode(struct inode *inode)
586{
587 struct btrfs_path *path;
Chris Mason5f39d392007-10-15 16:14:19 -0400588 struct extent_buffer *leaf;
Chris Mason39279cc2007-06-12 06:35:45 -0400589 struct btrfs_inode_item *inode_item;
Chris Mason0b86a832008-03-24 15:01:56 -0400590 struct btrfs_timespec *tspec;
Chris Mason39279cc2007-06-12 06:35:45 -0400591 struct btrfs_root *root = BTRFS_I(inode)->root;
592 struct btrfs_key location;
593 u64 alloc_group_block;
Josef Bacik618e21d2007-07-11 10:18:17 -0400594 u32 rdev;
Chris Mason39279cc2007-06-12 06:35:45 -0400595 int ret;
596
597 path = btrfs_alloc_path();
598 BUG_ON(!path);
Chris Mason39279cc2007-06-12 06:35:45 -0400599 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason39279cc2007-06-12 06:35:45 -0400600 memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
Chris Masondc17ff82008-01-08 15:46:30 -0500601
Chris Mason39279cc2007-06-12 06:35:45 -0400602 ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
Chris Mason5f39d392007-10-15 16:14:19 -0400603 if (ret)
Chris Mason39279cc2007-06-12 06:35:45 -0400604 goto make_bad;
Chris Mason39279cc2007-06-12 06:35:45 -0400605
Chris Mason5f39d392007-10-15 16:14:19 -0400606 leaf = path->nodes[0];
607 inode_item = btrfs_item_ptr(leaf, path->slots[0],
608 struct btrfs_inode_item);
609
610 inode->i_mode = btrfs_inode_mode(leaf, inode_item);
611 inode->i_nlink = btrfs_inode_nlink(leaf, inode_item);
612 inode->i_uid = btrfs_inode_uid(leaf, inode_item);
613 inode->i_gid = btrfs_inode_gid(leaf, inode_item);
614 inode->i_size = btrfs_inode_size(leaf, inode_item);
615
616 tspec = btrfs_inode_atime(inode_item);
617 inode->i_atime.tv_sec = btrfs_timespec_sec(leaf, tspec);
618 inode->i_atime.tv_nsec = btrfs_timespec_nsec(leaf, tspec);
619
620 tspec = btrfs_inode_mtime(inode_item);
621 inode->i_mtime.tv_sec = btrfs_timespec_sec(leaf, tspec);
622 inode->i_mtime.tv_nsec = btrfs_timespec_nsec(leaf, tspec);
623
624 tspec = btrfs_inode_ctime(inode_item);
625 inode->i_ctime.tv_sec = btrfs_timespec_sec(leaf, tspec);
626 inode->i_ctime.tv_nsec = btrfs_timespec_nsec(leaf, tspec);
627
628 inode->i_blocks = btrfs_inode_nblocks(leaf, inode_item);
629 inode->i_generation = btrfs_inode_generation(leaf, inode_item);
Josef Bacik618e21d2007-07-11 10:18:17 -0400630 inode->i_rdev = 0;
Chris Mason5f39d392007-10-15 16:14:19 -0400631 rdev = btrfs_inode_rdev(leaf, inode_item);
632
633 alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
Chris Mason39279cc2007-06-12 06:35:45 -0400634 BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info,
635 alloc_group_block);
Yanb98b6762008-01-08 15:54:37 -0500636 BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
Chris Masone52ec0e2007-12-21 16:36:24 -0500637 if (!BTRFS_I(inode)->block_group) {
638 BTRFS_I(inode)->block_group = btrfs_find_block_group(root,
Chris Mason0b86a832008-03-24 15:01:56 -0400639 NULL, 0,
640 BTRFS_BLOCK_GROUP_METADATA, 0);
Chris Masone52ec0e2007-12-21 16:36:24 -0500641 }
Chris Mason39279cc2007-06-12 06:35:45 -0400642 btrfs_free_path(path);
643 inode_item = NULL;
644
645 mutex_unlock(&root->fs_info->fs_mutex);
646
647 switch (inode->i_mode & S_IFMT) {
Chris Mason39279cc2007-06-12 06:35:45 -0400648 case S_IFREG:
649 inode->i_mapping->a_ops = &btrfs_aops;
Chris Mason04160082008-03-26 10:28:07 -0400650 inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
Chris Masond1310b22008-01-24 16:13:08 -0500651 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
Chris Mason39279cc2007-06-12 06:35:45 -0400652 inode->i_fop = &btrfs_file_operations;
653 inode->i_op = &btrfs_file_inode_operations;
654 break;
655 case S_IFDIR:
656 inode->i_fop = &btrfs_dir_file_operations;
657 if (root == root->fs_info->tree_root)
658 inode->i_op = &btrfs_dir_ro_inode_operations;
659 else
660 inode->i_op = &btrfs_dir_inode_operations;
661 break;
662 case S_IFLNK:
663 inode->i_op = &btrfs_symlink_inode_operations;
664 inode->i_mapping->a_ops = &btrfs_symlink_aops;
Chris Mason04160082008-03-26 10:28:07 -0400665 inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
Chris Mason39279cc2007-06-12 06:35:45 -0400666 break;
Josef Bacik618e21d2007-07-11 10:18:17 -0400667 default:
668 init_special_inode(inode, inode->i_mode, rdev);
669 break;
Chris Mason39279cc2007-06-12 06:35:45 -0400670 }
671 return;
672
673make_bad:
674 btrfs_release_path(root, path);
675 btrfs_free_path(path);
676 mutex_unlock(&root->fs_info->fs_mutex);
677 make_bad_inode(inode);
678}
679
Chris Mason5f39d392007-10-15 16:14:19 -0400680static void fill_inode_item(struct extent_buffer *leaf,
681 struct btrfs_inode_item *item,
Chris Mason39279cc2007-06-12 06:35:45 -0400682 struct inode *inode)
683{
Chris Mason5f39d392007-10-15 16:14:19 -0400684 btrfs_set_inode_uid(leaf, item, inode->i_uid);
685 btrfs_set_inode_gid(leaf, item, inode->i_gid);
686 btrfs_set_inode_size(leaf, item, inode->i_size);
687 btrfs_set_inode_mode(leaf, item, inode->i_mode);
688 btrfs_set_inode_nlink(leaf, item, inode->i_nlink);
689
690 btrfs_set_timespec_sec(leaf, btrfs_inode_atime(item),
691 inode->i_atime.tv_sec);
692 btrfs_set_timespec_nsec(leaf, btrfs_inode_atime(item),
693 inode->i_atime.tv_nsec);
694
695 btrfs_set_timespec_sec(leaf, btrfs_inode_mtime(item),
696 inode->i_mtime.tv_sec);
697 btrfs_set_timespec_nsec(leaf, btrfs_inode_mtime(item),
698 inode->i_mtime.tv_nsec);
699
700 btrfs_set_timespec_sec(leaf, btrfs_inode_ctime(item),
701 inode->i_ctime.tv_sec);
702 btrfs_set_timespec_nsec(leaf, btrfs_inode_ctime(item),
703 inode->i_ctime.tv_nsec);
704
705 btrfs_set_inode_nblocks(leaf, item, inode->i_blocks);
706 btrfs_set_inode_generation(leaf, item, inode->i_generation);
707 btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
Yanb98b6762008-01-08 15:54:37 -0500708 btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
Chris Mason5f39d392007-10-15 16:14:19 -0400709 btrfs_set_inode_block_group(leaf, item,
Chris Mason39279cc2007-06-12 06:35:45 -0400710 BTRFS_I(inode)->block_group->key.objectid);
711}
712
Chris Masona52d9a82007-08-27 16:49:44 -0400713int btrfs_update_inode(struct btrfs_trans_handle *trans,
Chris Mason39279cc2007-06-12 06:35:45 -0400714 struct btrfs_root *root,
715 struct inode *inode)
716{
717 struct btrfs_inode_item *inode_item;
718 struct btrfs_path *path;
Chris Mason5f39d392007-10-15 16:14:19 -0400719 struct extent_buffer *leaf;
Chris Mason39279cc2007-06-12 06:35:45 -0400720 int ret;
721
722 path = btrfs_alloc_path();
723 BUG_ON(!path);
Chris Mason39279cc2007-06-12 06:35:45 -0400724 ret = btrfs_lookup_inode(trans, root, path,
725 &BTRFS_I(inode)->location, 1);
726 if (ret) {
727 if (ret > 0)
728 ret = -ENOENT;
729 goto failed;
730 }
731
Chris Mason5f39d392007-10-15 16:14:19 -0400732 leaf = path->nodes[0];
733 inode_item = btrfs_item_ptr(leaf, path->slots[0],
Chris Mason39279cc2007-06-12 06:35:45 -0400734 struct btrfs_inode_item);
735
Chris Mason5f39d392007-10-15 16:14:19 -0400736 fill_inode_item(leaf, inode_item, inode);
737 btrfs_mark_buffer_dirty(leaf);
Josef Bacik15ee9bc2007-08-10 16:22:09 -0400738 btrfs_set_inode_last_trans(trans, inode);
Chris Mason39279cc2007-06-12 06:35:45 -0400739 ret = 0;
740failed:
741 btrfs_release_path(root, path);
742 btrfs_free_path(path);
743 return ret;
744}
745
746
747static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
748 struct btrfs_root *root,
749 struct inode *dir,
750 struct dentry *dentry)
751{
752 struct btrfs_path *path;
753 const char *name = dentry->d_name.name;
754 int name_len = dentry->d_name.len;
755 int ret = 0;
Chris Mason5f39d392007-10-15 16:14:19 -0400756 struct extent_buffer *leaf;
Chris Mason39279cc2007-06-12 06:35:45 -0400757 struct btrfs_dir_item *di;
Chris Mason5f39d392007-10-15 16:14:19 -0400758 struct btrfs_key key;
Chris Mason39279cc2007-06-12 06:35:45 -0400759
760 path = btrfs_alloc_path();
Chris Mason54aa1f42007-06-22 14:16:25 -0400761 if (!path) {
762 ret = -ENOMEM;
763 goto err;
764 }
765
Chris Mason39279cc2007-06-12 06:35:45 -0400766 di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino,
767 name, name_len, -1);
768 if (IS_ERR(di)) {
769 ret = PTR_ERR(di);
770 goto err;
771 }
772 if (!di) {
773 ret = -ENOENT;
774 goto err;
775 }
Chris Mason5f39d392007-10-15 16:14:19 -0400776 leaf = path->nodes[0];
777 btrfs_dir_item_key_to_cpu(leaf, di, &key);
Chris Mason39279cc2007-06-12 06:35:45 -0400778 ret = btrfs_delete_one_dir_name(trans, root, path, di);
Chris Mason54aa1f42007-06-22 14:16:25 -0400779 if (ret)
780 goto err;
Chris Mason39279cc2007-06-12 06:35:45 -0400781 btrfs_release_path(root, path);
782
783 di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
Chris Mason5f39d392007-10-15 16:14:19 -0400784 key.objectid, name, name_len, -1);
Chris Mason39279cc2007-06-12 06:35:45 -0400785 if (IS_ERR(di)) {
786 ret = PTR_ERR(di);
787 goto err;
788 }
789 if (!di) {
790 ret = -ENOENT;
791 goto err;
792 }
793 ret = btrfs_delete_one_dir_name(trans, root, path, di);
Chris Mason39279cc2007-06-12 06:35:45 -0400794
795 dentry->d_inode->i_ctime = dir->i_ctime;
Chris Mason76fea002007-12-13 09:06:01 -0500796 ret = btrfs_del_inode_ref(trans, root, name, name_len,
797 dentry->d_inode->i_ino,
798 dentry->d_parent->d_inode->i_ino);
799 if (ret) {
800 printk("failed to delete reference to %.*s, "
801 "inode %lu parent %lu\n", name_len, name,
802 dentry->d_inode->i_ino,
803 dentry->d_parent->d_inode->i_ino);
Chris Mason39544012007-12-12 14:38:19 -0500804 }
Chris Mason39279cc2007-06-12 06:35:45 -0400805err:
806 btrfs_free_path(path);
807 if (!ret) {
808 dir->i_size -= name_len * 2;
Chris Mason79c44582007-06-25 10:09:33 -0400809 dir->i_mtime = dir->i_ctime = CURRENT_TIME;
Chris Mason39279cc2007-06-12 06:35:45 -0400810 btrfs_update_inode(trans, root, dir);
Chris Mason6da6aba2007-12-18 16:15:09 -0500811#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
812 dentry->d_inode->i_nlink--;
813#else
Chris Mason39279cc2007-06-12 06:35:45 -0400814 drop_nlink(dentry->d_inode);
Chris Mason6da6aba2007-12-18 16:15:09 -0500815#endif
Chris Mason54aa1f42007-06-22 14:16:25 -0400816 ret = btrfs_update_inode(trans, root, dentry->d_inode);
Chris Mason39279cc2007-06-12 06:35:45 -0400817 dir->i_sb->s_dirt = 1;
818 }
819 return ret;
820}
821
822static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
823{
824 struct btrfs_root *root;
825 struct btrfs_trans_handle *trans;
Chris Mason2da98f02008-01-16 11:44:43 -0500826 struct inode *inode = dentry->d_inode;
Chris Mason39279cc2007-06-12 06:35:45 -0400827 int ret;
Chris Mason1832a6d2007-12-21 16:27:21 -0500828 unsigned long nr = 0;
Chris Mason39279cc2007-06-12 06:35:45 -0400829
830 root = BTRFS_I(dir)->root;
831 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -0500832
833 ret = btrfs_check_free_space(root, 1, 1);
834 if (ret)
835 goto fail;
836
Chris Mason39279cc2007-06-12 06:35:45 -0400837 trans = btrfs_start_transaction(root, 1);
Chris Mason5f39d392007-10-15 16:14:19 -0400838
Chris Mason39279cc2007-06-12 06:35:45 -0400839 btrfs_set_trans_block_group(trans, dir);
840 ret = btrfs_unlink_trans(trans, root, dir, dentry);
Chris Masond3c2fdcf2007-09-17 10:58:06 -0400841 nr = trans->blocks_used;
Chris Mason5f39d392007-10-15 16:14:19 -0400842
Chris Mason2da98f02008-01-16 11:44:43 -0500843 if (inode->i_nlink == 0) {
844 int found;
845 /* if the inode isn't linked anywhere,
846 * we don't need to worry about
847 * data=ordered
848 */
849 found = btrfs_del_ordered_inode(inode);
850 if (found == 1) {
851 atomic_dec(&inode->i_count);
852 }
853 }
854
Chris Mason39279cc2007-06-12 06:35:45 -0400855 btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -0500856fail:
Chris Mason39279cc2007-06-12 06:35:45 -0400857 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -0400858 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -0500859 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -0400860 return ret;
861}
862
863static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
864{
865 struct inode *inode = dentry->d_inode;
Chris Mason1832a6d2007-12-21 16:27:21 -0500866 int err = 0;
Chris Mason39279cc2007-06-12 06:35:45 -0400867 int ret;
868 struct btrfs_root *root = BTRFS_I(dir)->root;
Chris Mason39279cc2007-06-12 06:35:45 -0400869 struct btrfs_trans_handle *trans;
Chris Mason1832a6d2007-12-21 16:27:21 -0500870 unsigned long nr = 0;
Chris Mason39279cc2007-06-12 06:35:45 -0400871
Yan134d4512007-10-25 15:49:25 -0400872 if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
873 return -ENOTEMPTY;
874
Chris Mason39279cc2007-06-12 06:35:45 -0400875 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -0500876 ret = btrfs_check_free_space(root, 1, 1);
877 if (ret)
878 goto fail;
879
Chris Mason39279cc2007-06-12 06:35:45 -0400880 trans = btrfs_start_transaction(root, 1);
881 btrfs_set_trans_block_group(trans, dir);
Chris Mason39279cc2007-06-12 06:35:45 -0400882
883 /* now the directory is empty */
884 err = btrfs_unlink_trans(trans, root, dir, dentry);
885 if (!err) {
886 inode->i_size = 0;
887 }
Chris Mason39544012007-12-12 14:38:19 -0500888
Chris Masond3c2fdcf2007-09-17 10:58:06 -0400889 nr = trans->blocks_used;
Chris Mason39279cc2007-06-12 06:35:45 -0400890 ret = btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -0500891fail:
Yan134d4512007-10-25 15:49:25 -0400892 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -0400893 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -0500894 btrfs_throttle(root);
Chris Mason39544012007-12-12 14:38:19 -0500895
Chris Mason39279cc2007-06-12 06:35:45 -0400896 if (ret && !err)
897 err = ret;
898 return err;
899}
900
Chris Mason39279cc2007-06-12 06:35:45 -0400901/*
Chris Mason39279cc2007-06-12 06:35:45 -0400902 * this can truncate away extent items, csum items and directory items.
903 * It starts at a high offset and removes keys until it can't find
904 * any higher than i_size.
905 *
906 * csum items that cross the new i_size are truncated to the new size
907 * as well.
908 */
909static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
910 struct btrfs_root *root,
Chris Mason85e21ba2008-01-29 15:11:36 -0500911 struct inode *inode,
912 u32 min_type)
Chris Mason39279cc2007-06-12 06:35:45 -0400913{
914 int ret;
915 struct btrfs_path *path;
916 struct btrfs_key key;
Chris Mason5f39d392007-10-15 16:14:19 -0400917 struct btrfs_key found_key;
Chris Mason39279cc2007-06-12 06:35:45 -0400918 u32 found_type;
Chris Mason5f39d392007-10-15 16:14:19 -0400919 struct extent_buffer *leaf;
Chris Mason39279cc2007-06-12 06:35:45 -0400920 struct btrfs_file_extent_item *fi;
921 u64 extent_start = 0;
Chris Masondb945352007-10-15 16:15:53 -0400922 u64 extent_num_bytes = 0;
Chris Mason39279cc2007-06-12 06:35:45 -0400923 u64 item_end = 0;
Chris Mason7bb86312007-12-11 09:25:06 -0500924 u64 root_gen = 0;
Chris Masond8d5f3e2007-12-11 12:42:00 -0500925 u64 root_owner = 0;
Chris Mason39279cc2007-06-12 06:35:45 -0400926 int found_extent;
927 int del_item;
Chris Mason85e21ba2008-01-29 15:11:36 -0500928 int pending_del_nr = 0;
929 int pending_del_slot = 0;
Chris Mason179e29e2007-11-01 11:28:41 -0400930 int extent_type = -1;
Chris Mason3b951512008-04-17 11:29:12 -0400931 u64 mask = root->sectorsize - 1;
Chris Mason39279cc2007-06-12 06:35:45 -0400932
Chris Mason3b951512008-04-17 11:29:12 -0400933 btrfs_drop_extent_cache(inode, inode->i_size & (~mask), (u64)-1);
Chris Mason39279cc2007-06-12 06:35:45 -0400934 path = btrfs_alloc_path();
Chris Mason3c69fae2007-08-07 15:52:22 -0400935 path->reada = -1;
Chris Mason39279cc2007-06-12 06:35:45 -0400936 BUG_ON(!path);
Chris Mason5f39d392007-10-15 16:14:19 -0400937
Chris Mason39279cc2007-06-12 06:35:45 -0400938 /* FIXME, add redo link to tree so we don't leak on crash */
939 key.objectid = inode->i_ino;
940 key.offset = (u64)-1;
Chris Mason5f39d392007-10-15 16:14:19 -0400941 key.type = (u8)-1;
942
Chris Mason85e21ba2008-01-29 15:11:36 -0500943 btrfs_init_path(path);
944search_again:
945 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
946 if (ret < 0) {
947 goto error;
948 }
949 if (ret > 0) {
950 BUG_ON(path->slots[0] == 0);
951 path->slots[0]--;
952 }
953
Chris Mason39279cc2007-06-12 06:35:45 -0400954 while(1) {
Chris Mason39279cc2007-06-12 06:35:45 -0400955 fi = NULL;
Chris Mason5f39d392007-10-15 16:14:19 -0400956 leaf = path->nodes[0];
957 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
958 found_type = btrfs_key_type(&found_key);
Chris Mason39279cc2007-06-12 06:35:45 -0400959
Chris Mason5f39d392007-10-15 16:14:19 -0400960 if (found_key.objectid != inode->i_ino)
Chris Mason39279cc2007-06-12 06:35:45 -0400961 break;
Chris Mason5f39d392007-10-15 16:14:19 -0400962
Chris Mason85e21ba2008-01-29 15:11:36 -0500963 if (found_type < min_type)
Chris Mason39279cc2007-06-12 06:35:45 -0400964 break;
965
Chris Mason5f39d392007-10-15 16:14:19 -0400966 item_end = found_key.offset;
Chris Mason39279cc2007-06-12 06:35:45 -0400967 if (found_type == BTRFS_EXTENT_DATA_KEY) {
Chris Mason5f39d392007-10-15 16:14:19 -0400968 fi = btrfs_item_ptr(leaf, path->slots[0],
Chris Mason39279cc2007-06-12 06:35:45 -0400969 struct btrfs_file_extent_item);
Chris Mason179e29e2007-11-01 11:28:41 -0400970 extent_type = btrfs_file_extent_type(leaf, fi);
971 if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
Chris Mason5f39d392007-10-15 16:14:19 -0400972 item_end +=
Chris Masondb945352007-10-15 16:15:53 -0400973 btrfs_file_extent_num_bytes(leaf, fi);
Chris Mason179e29e2007-11-01 11:28:41 -0400974 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
975 struct btrfs_item *item = btrfs_item_nr(leaf,
976 path->slots[0]);
977 item_end += btrfs_file_extent_inline_len(leaf,
978 item);
Chris Mason39279cc2007-06-12 06:35:45 -0400979 }
Yan008630c2007-11-07 13:31:09 -0500980 item_end--;
Chris Mason39279cc2007-06-12 06:35:45 -0400981 }
982 if (found_type == BTRFS_CSUM_ITEM_KEY) {
983 ret = btrfs_csum_truncate(trans, root, path,
984 inode->i_size);
985 BUG_ON(ret);
986 }
Yan008630c2007-11-07 13:31:09 -0500987 if (item_end < inode->i_size) {
Chris Masonb888db22007-08-27 16:49:44 -0400988 if (found_type == BTRFS_DIR_ITEM_KEY) {
989 found_type = BTRFS_INODE_ITEM_KEY;
990 } else if (found_type == BTRFS_EXTENT_ITEM_KEY) {
991 found_type = BTRFS_CSUM_ITEM_KEY;
Chris Mason85e21ba2008-01-29 15:11:36 -0500992 } else if (found_type == BTRFS_EXTENT_DATA_KEY) {
993 found_type = BTRFS_XATTR_ITEM_KEY;
994 } else if (found_type == BTRFS_XATTR_ITEM_KEY) {
995 found_type = BTRFS_INODE_REF_KEY;
Chris Masonb888db22007-08-27 16:49:44 -0400996 } else if (found_type) {
997 found_type--;
998 } else {
999 break;
Chris Mason39279cc2007-06-12 06:35:45 -04001000 }
Yana61721d2007-09-17 11:08:38 -04001001 btrfs_set_key_type(&key, found_type);
Chris Mason85e21ba2008-01-29 15:11:36 -05001002 goto next;
Chris Mason39279cc2007-06-12 06:35:45 -04001003 }
Chris Mason5f39d392007-10-15 16:14:19 -04001004 if (found_key.offset >= inode->i_size)
Chris Mason39279cc2007-06-12 06:35:45 -04001005 del_item = 1;
1006 else
1007 del_item = 0;
1008 found_extent = 0;
1009
1010 /* FIXME, shrink the extent if the ref count is only 1 */
Chris Mason179e29e2007-11-01 11:28:41 -04001011 if (found_type != BTRFS_EXTENT_DATA_KEY)
1012 goto delete;
1013
1014 if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
Chris Mason39279cc2007-06-12 06:35:45 -04001015 u64 num_dec;
Chris Masondb945352007-10-15 16:15:53 -04001016 extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
Chris Mason39279cc2007-06-12 06:35:45 -04001017 if (!del_item) {
Chris Masondb945352007-10-15 16:15:53 -04001018 u64 orig_num_bytes =
1019 btrfs_file_extent_num_bytes(leaf, fi);
1020 extent_num_bytes = inode->i_size -
Chris Mason5f39d392007-10-15 16:14:19 -04001021 found_key.offset + root->sectorsize - 1;
Yanb1632b12008-01-30 11:54:04 -05001022 extent_num_bytes = extent_num_bytes &
1023 ~((u64)root->sectorsize - 1);
Chris Masondb945352007-10-15 16:15:53 -04001024 btrfs_set_file_extent_num_bytes(leaf, fi,
1025 extent_num_bytes);
1026 num_dec = (orig_num_bytes -
Chris Mason90692182008-02-08 13:49:28 -05001027 extent_num_bytes);
1028 if (extent_start != 0)
1029 dec_i_blocks(inode, num_dec);
Chris Mason5f39d392007-10-15 16:14:19 -04001030 btrfs_mark_buffer_dirty(leaf);
Chris Mason39279cc2007-06-12 06:35:45 -04001031 } else {
Chris Masondb945352007-10-15 16:15:53 -04001032 extent_num_bytes =
1033 btrfs_file_extent_disk_num_bytes(leaf,
1034 fi);
Chris Mason39279cc2007-06-12 06:35:45 -04001035 /* FIXME blocksize != 4096 */
Chris Mason90692182008-02-08 13:49:28 -05001036 num_dec = btrfs_file_extent_num_bytes(leaf, fi);
Chris Mason39279cc2007-06-12 06:35:45 -04001037 if (extent_start != 0) {
1038 found_extent = 1;
Chris Mason90692182008-02-08 13:49:28 -05001039 dec_i_blocks(inode, num_dec);
Chris Mason39279cc2007-06-12 06:35:45 -04001040 }
Chris Masond8d5f3e2007-12-11 12:42:00 -05001041 root_gen = btrfs_header_generation(leaf);
1042 root_owner = btrfs_header_owner(leaf);
Chris Mason39279cc2007-06-12 06:35:45 -04001043 }
Chris Mason90692182008-02-08 13:49:28 -05001044 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
1045 if (!del_item) {
1046 u32 newsize = inode->i_size - found_key.offset;
1047 dec_i_blocks(inode, item_end + 1 -
1048 found_key.offset - newsize);
1049 newsize =
1050 btrfs_file_extent_calc_inline_size(newsize);
1051 ret = btrfs_truncate_item(trans, root, path,
1052 newsize, 1);
1053 BUG_ON(ret);
1054 } else {
1055 dec_i_blocks(inode, item_end + 1 -
1056 found_key.offset);
1057 }
Chris Mason39279cc2007-06-12 06:35:45 -04001058 }
Chris Mason179e29e2007-11-01 11:28:41 -04001059delete:
Chris Mason39279cc2007-06-12 06:35:45 -04001060 if (del_item) {
Chris Mason85e21ba2008-01-29 15:11:36 -05001061 if (!pending_del_nr) {
1062 /* no pending yet, add ourselves */
1063 pending_del_slot = path->slots[0];
1064 pending_del_nr = 1;
1065 } else if (pending_del_nr &&
1066 path->slots[0] + 1 == pending_del_slot) {
1067 /* hop on the pending chunk */
1068 pending_del_nr++;
1069 pending_del_slot = path->slots[0];
1070 } else {
1071 printk("bad pending slot %d pending_del_nr %d pending_del_slot %d\n", path->slots[0], pending_del_nr, pending_del_slot);
1072 }
Chris Mason39279cc2007-06-12 06:35:45 -04001073 } else {
1074 break;
1075 }
Chris Mason39279cc2007-06-12 06:35:45 -04001076 if (found_extent) {
1077 ret = btrfs_free_extent(trans, root, extent_start,
Chris Mason7bb86312007-12-11 09:25:06 -05001078 extent_num_bytes,
Chris Masond8d5f3e2007-12-11 12:42:00 -05001079 root_owner,
Chris Mason7bb86312007-12-11 09:25:06 -05001080 root_gen, inode->i_ino,
1081 found_key.offset, 0);
Chris Mason39279cc2007-06-12 06:35:45 -04001082 BUG_ON(ret);
1083 }
Chris Mason85e21ba2008-01-29 15:11:36 -05001084next:
1085 if (path->slots[0] == 0) {
1086 if (pending_del_nr)
1087 goto del_pending;
1088 btrfs_release_path(root, path);
1089 goto search_again;
1090 }
1091
1092 path->slots[0]--;
1093 if (pending_del_nr &&
1094 path->slots[0] + 1 != pending_del_slot) {
1095 struct btrfs_key debug;
1096del_pending:
1097 btrfs_item_key_to_cpu(path->nodes[0], &debug,
1098 pending_del_slot);
1099 ret = btrfs_del_items(trans, root, path,
1100 pending_del_slot,
1101 pending_del_nr);
1102 BUG_ON(ret);
1103 pending_del_nr = 0;
1104 btrfs_release_path(root, path);
1105 goto search_again;
1106 }
Chris Mason39279cc2007-06-12 06:35:45 -04001107 }
1108 ret = 0;
1109error:
Chris Mason85e21ba2008-01-29 15:11:36 -05001110 if (pending_del_nr) {
1111 ret = btrfs_del_items(trans, root, path, pending_del_slot,
1112 pending_del_nr);
1113 }
Chris Mason39279cc2007-06-12 06:35:45 -04001114 btrfs_release_path(root, path);
1115 btrfs_free_path(path);
1116 inode->i_sb->s_dirt = 1;
1117 return ret;
1118}
1119
Chris Masonb888db22007-08-27 16:49:44 -04001120static int btrfs_cow_one_page(struct inode *inode, struct page *page,
Chris Masona52d9a82007-08-27 16:49:44 -04001121 size_t zero_start)
Chris Mason39279cc2007-06-12 06:35:45 -04001122{
Chris Mason39279cc2007-06-12 06:35:45 -04001123 char *kaddr;
Chris Masond1310b22008-01-24 16:13:08 -05001124 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
Chris Mason35ebb932007-10-30 16:56:53 -04001125 u64 page_start = (u64)page->index << PAGE_CACHE_SHIFT;
Chris Masonb888db22007-08-27 16:49:44 -04001126 u64 page_end = page_start + PAGE_CACHE_SIZE - 1;
Chris Mason1832a6d2007-12-21 16:27:21 -05001127 int ret = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001128
Chris Mason190662b2007-12-18 16:25:45 -05001129 WARN_ON(!PageLocked(page));
Christoph Hellwigb3cfa352007-09-17 11:25:58 -04001130 set_page_extent_mapped(page);
Chris Masona52d9a82007-08-27 16:49:44 -04001131
Chris Masond1310b22008-01-24 16:13:08 -05001132 lock_extent(io_tree, page_start, page_end, GFP_NOFS);
Chris Masond1310b22008-01-24 16:13:08 -05001133 set_extent_delalloc(&BTRFS_I(inode)->io_tree, page_start,
Chris Masonb888db22007-08-27 16:49:44 -04001134 page_end, GFP_NOFS);
Chris Mason1832a6d2007-12-21 16:27:21 -05001135
Chris Masona52d9a82007-08-27 16:49:44 -04001136 if (zero_start != PAGE_CACHE_SIZE) {
Chris Masonb888db22007-08-27 16:49:44 -04001137 kaddr = kmap(page);
Chris Masona52d9a82007-08-27 16:49:44 -04001138 memset(kaddr + zero_start, 0, PAGE_CACHE_SIZE - zero_start);
1139 flush_dcache_page(page);
Chris Masonb888db22007-08-27 16:49:44 -04001140 kunmap(page);
Chris Masona52d9a82007-08-27 16:49:44 -04001141 }
Chris Masonb888db22007-08-27 16:49:44 -04001142 set_page_dirty(page);
Chris Masond1310b22008-01-24 16:13:08 -05001143 unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
Chris Masona52d9a82007-08-27 16:49:44 -04001144
Chris Masona52d9a82007-08-27 16:49:44 -04001145 return ret;
1146}
1147
1148/*
1149 * taken from block_truncate_page, but does cow as it zeros out
1150 * any bytes left in the last page in the file.
1151 */
1152static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
1153{
1154 struct inode *inode = mapping->host;
Chris Masondb945352007-10-15 16:15:53 -04001155 struct btrfs_root *root = BTRFS_I(inode)->root;
1156 u32 blocksize = root->sectorsize;
Chris Masona52d9a82007-08-27 16:49:44 -04001157 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1158 unsigned offset = from & (PAGE_CACHE_SIZE-1);
1159 struct page *page;
1160 int ret = 0;
1161 u64 page_start;
1162
1163 if ((offset & (blocksize - 1)) == 0)
1164 goto out;
1165
1166 ret = -ENOMEM;
1167 page = grab_cache_page(mapping, index);
1168 if (!page)
1169 goto out;
1170 if (!PageUptodate(page)) {
1171 ret = btrfs_readpage(NULL, page);
1172 lock_page(page);
1173 if (!PageUptodate(page)) {
1174 ret = -EIO;
1175 goto out;
1176 }
1177 }
Chris Mason35ebb932007-10-30 16:56:53 -04001178 page_start = (u64)page->index << PAGE_CACHE_SHIFT;
Chris Masona52d9a82007-08-27 16:49:44 -04001179
Chris Masonb888db22007-08-27 16:49:44 -04001180 ret = btrfs_cow_one_page(inode, page, offset);
Chris Mason39279cc2007-06-12 06:35:45 -04001181
Chris Mason39279cc2007-06-12 06:35:45 -04001182 unlock_page(page);
1183 page_cache_release(page);
1184out:
1185 return ret;
1186}
1187
1188static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
1189{
1190 struct inode *inode = dentry->d_inode;
1191 int err;
1192
1193 err = inode_change_ok(inode, attr);
1194 if (err)
1195 return err;
1196
1197 if (S_ISREG(inode->i_mode) &&
1198 attr->ia_valid & ATTR_SIZE && attr->ia_size > inode->i_size) {
1199 struct btrfs_trans_handle *trans;
1200 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masond1310b22008-01-24 16:13:08 -05001201 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
Chris Mason2bf5a722007-08-30 11:54:02 -04001202
Chris Mason5f39d392007-10-15 16:14:19 -04001203 u64 mask = root->sectorsize - 1;
Chris Mason1b0f7c22008-01-30 14:33:02 -05001204 u64 hole_start = (inode->i_size + mask) & ~mask;
Chris Masonf392a932008-01-30 11:54:05 -05001205 u64 block_end = (attr->ia_size + mask) & ~mask;
Chris Mason39279cc2007-06-12 06:35:45 -04001206 u64 hole_size;
Chris Mason179e29e2007-11-01 11:28:41 -04001207 u64 alloc_hint = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001208
Chris Mason1b0f7c22008-01-30 14:33:02 -05001209 if (attr->ia_size <= hole_start)
Chris Mason39279cc2007-06-12 06:35:45 -04001210 goto out;
1211
Chris Mason1832a6d2007-12-21 16:27:21 -05001212 mutex_lock(&root->fs_info->fs_mutex);
1213 err = btrfs_check_free_space(root, 1, 0);
1214 mutex_unlock(&root->fs_info->fs_mutex);
1215 if (err)
1216 goto fail;
1217
Chris Mason39279cc2007-06-12 06:35:45 -04001218 btrfs_truncate_page(inode->i_mapping, inode->i_size);
1219
Chris Mason1b0f7c22008-01-30 14:33:02 -05001220 lock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
Chris Mason5f564062008-01-22 16:47:59 -05001221 hole_size = block_end - hole_start;
Chris Mason39279cc2007-06-12 06:35:45 -04001222
1223 mutex_lock(&root->fs_info->fs_mutex);
1224 trans = btrfs_start_transaction(root, 1);
1225 btrfs_set_trans_block_group(trans, inode);
Chris Mason2bf5a722007-08-30 11:54:02 -04001226 err = btrfs_drop_extents(trans, root, inode,
Chris Mason1b0f7c22008-01-30 14:33:02 -05001227 hole_start, block_end, hole_start,
Chris Mason3326d1b2007-10-15 16:18:25 -04001228 &alloc_hint);
Chris Mason2bf5a722007-08-30 11:54:02 -04001229
Chris Mason179e29e2007-11-01 11:28:41 -04001230 if (alloc_hint != EXTENT_MAP_INLINE) {
1231 err = btrfs_insert_file_extent(trans, root,
1232 inode->i_ino,
Chris Mason5f564062008-01-22 16:47:59 -05001233 hole_start, 0, 0,
Sage Weilf2eb0a22008-05-02 14:43:14 -04001234 hole_size, 0);
Chris Masond1310b22008-01-24 16:13:08 -05001235 btrfs_drop_extent_cache(inode, hole_start,
Chris Mason3b951512008-04-17 11:29:12 -04001236 (u64)-1);
Chris Mason5f564062008-01-22 16:47:59 -05001237 btrfs_check_file(root, inode);
Chris Mason179e29e2007-11-01 11:28:41 -04001238 }
Chris Mason39279cc2007-06-12 06:35:45 -04001239 btrfs_end_transaction(trans, root);
1240 mutex_unlock(&root->fs_info->fs_mutex);
Chris Mason1b0f7c22008-01-30 14:33:02 -05001241 unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
Chris Mason54aa1f42007-06-22 14:16:25 -04001242 if (err)
1243 return err;
Chris Mason39279cc2007-06-12 06:35:45 -04001244 }
1245out:
1246 err = inode_setattr(inode, attr);
Chris Mason1832a6d2007-12-21 16:27:21 -05001247fail:
Chris Mason39279cc2007-06-12 06:35:45 -04001248 return err;
1249}
Chris Mason61295eb2008-01-14 16:24:38 -05001250
Chris Mason2da98f02008-01-16 11:44:43 -05001251void btrfs_put_inode(struct inode *inode)
Chris Mason61295eb2008-01-14 16:24:38 -05001252{
Chris Mason2da98f02008-01-16 11:44:43 -05001253 int ret;
1254
1255 if (!BTRFS_I(inode)->ordered_trans) {
Chris Mason61295eb2008-01-14 16:24:38 -05001256 return;
1257 }
Chris Mason2da98f02008-01-16 11:44:43 -05001258
1259 if (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY) ||
1260 mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))
1261 return;
1262
1263 ret = btrfs_del_ordered_inode(inode);
1264 if (ret == 1) {
1265 atomic_dec(&inode->i_count);
1266 }
Chris Mason61295eb2008-01-14 16:24:38 -05001267}
1268
Chris Mason39279cc2007-06-12 06:35:45 -04001269void btrfs_delete_inode(struct inode *inode)
1270{
1271 struct btrfs_trans_handle *trans;
1272 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001273 unsigned long nr;
Chris Mason39279cc2007-06-12 06:35:45 -04001274 int ret;
1275
1276 truncate_inode_pages(&inode->i_data, 0);
1277 if (is_bad_inode(inode)) {
1278 goto no_delete;
1279 }
Chris Mason5f39d392007-10-15 16:14:19 -04001280
Chris Mason39279cc2007-06-12 06:35:45 -04001281 inode->i_size = 0;
1282 mutex_lock(&root->fs_info->fs_mutex);
1283 trans = btrfs_start_transaction(root, 1);
Chris Mason5f39d392007-10-15 16:14:19 -04001284
Chris Mason39279cc2007-06-12 06:35:45 -04001285 btrfs_set_trans_block_group(trans, inode);
Chris Mason85e21ba2008-01-29 15:11:36 -05001286 ret = btrfs_truncate_in_trans(trans, root, inode, 0);
Chris Mason54aa1f42007-06-22 14:16:25 -04001287 if (ret)
1288 goto no_delete_lock;
Chris Mason85e21ba2008-01-29 15:11:36 -05001289
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001290 nr = trans->blocks_used;
Chris Mason85e21ba2008-01-29 15:11:36 -05001291 clear_inode(inode);
Chris Mason5f39d392007-10-15 16:14:19 -04001292
Chris Mason39279cc2007-06-12 06:35:45 -04001293 btrfs_end_transaction(trans, root);
1294 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001295 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05001296 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04001297 return;
Chris Mason54aa1f42007-06-22 14:16:25 -04001298
1299no_delete_lock:
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001300 nr = trans->blocks_used;
Chris Mason54aa1f42007-06-22 14:16:25 -04001301 btrfs_end_transaction(trans, root);
1302 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001303 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05001304 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04001305no_delete:
1306 clear_inode(inode);
1307}
1308
1309/*
1310 * this returns the key found in the dir entry in the location pointer.
1311 * If no dir entries were found, location->objectid is 0.
1312 */
1313static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
1314 struct btrfs_key *location)
1315{
1316 const char *name = dentry->d_name.name;
1317 int namelen = dentry->d_name.len;
1318 struct btrfs_dir_item *di;
1319 struct btrfs_path *path;
1320 struct btrfs_root *root = BTRFS_I(dir)->root;
Yan0d9f7f32007-10-25 15:48:28 -04001321 int ret = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001322
Chris Mason39544012007-12-12 14:38:19 -05001323 if (namelen == 1 && strcmp(name, ".") == 0) {
1324 location->objectid = dir->i_ino;
1325 location->type = BTRFS_INODE_ITEM_KEY;
1326 location->offset = 0;
1327 return 0;
1328 }
Chris Mason39279cc2007-06-12 06:35:45 -04001329 path = btrfs_alloc_path();
1330 BUG_ON(!path);
Chris Mason39544012007-12-12 14:38:19 -05001331
Chris Mason7a720532007-12-13 09:06:59 -05001332 if (namelen == 2 && strcmp(name, "..") == 0) {
Chris Mason39544012007-12-12 14:38:19 -05001333 struct btrfs_key key;
1334 struct extent_buffer *leaf;
1335 u32 nritems;
1336 int slot;
1337
1338 key.objectid = dir->i_ino;
1339 btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY);
1340 key.offset = 0;
1341 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1342 BUG_ON(ret == 0);
1343 ret = 0;
1344
1345 leaf = path->nodes[0];
1346 slot = path->slots[0];
1347 nritems = btrfs_header_nritems(leaf);
1348 if (slot >= nritems)
1349 goto out_err;
1350
1351 btrfs_item_key_to_cpu(leaf, &key, slot);
1352 if (key.objectid != dir->i_ino ||
1353 key.type != BTRFS_INODE_REF_KEY) {
1354 goto out_err;
1355 }
1356 location->objectid = key.offset;
1357 location->type = BTRFS_INODE_ITEM_KEY;
1358 location->offset = 0;
1359 goto out;
1360 }
1361
Chris Mason39279cc2007-06-12 06:35:45 -04001362 di = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name,
1363 namelen, 0);
Yan0d9f7f32007-10-25 15:48:28 -04001364 if (IS_ERR(di))
1365 ret = PTR_ERR(di);
Chris Mason39279cc2007-06-12 06:35:45 -04001366 if (!di || IS_ERR(di)) {
Chris Mason39544012007-12-12 14:38:19 -05001367 goto out_err;
Chris Mason39279cc2007-06-12 06:35:45 -04001368 }
Chris Mason5f39d392007-10-15 16:14:19 -04001369 btrfs_dir_item_key_to_cpu(path->nodes[0], di, location);
Chris Mason39279cc2007-06-12 06:35:45 -04001370out:
Chris Mason39279cc2007-06-12 06:35:45 -04001371 btrfs_free_path(path);
1372 return ret;
Chris Mason39544012007-12-12 14:38:19 -05001373out_err:
1374 location->objectid = 0;
1375 goto out;
Chris Mason39279cc2007-06-12 06:35:45 -04001376}
1377
1378/*
1379 * when we hit a tree root in a directory, the btrfs part of the inode
1380 * needs to be changed to reflect the root directory of the tree root. This
1381 * is kind of like crossing a mount point.
1382 */
1383static int fixup_tree_root_location(struct btrfs_root *root,
1384 struct btrfs_key *location,
Josef Bacik58176a92007-08-29 15:47:34 -04001385 struct btrfs_root **sub_root,
1386 struct dentry *dentry)
Chris Mason39279cc2007-06-12 06:35:45 -04001387{
1388 struct btrfs_path *path;
1389 struct btrfs_root_item *ri;
1390
1391 if (btrfs_key_type(location) != BTRFS_ROOT_ITEM_KEY)
1392 return 0;
1393 if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
1394 return 0;
1395
1396 path = btrfs_alloc_path();
1397 BUG_ON(!path);
1398 mutex_lock(&root->fs_info->fs_mutex);
1399
Josef Bacik58176a92007-08-29 15:47:34 -04001400 *sub_root = btrfs_read_fs_root(root->fs_info, location,
1401 dentry->d_name.name,
1402 dentry->d_name.len);
Chris Mason39279cc2007-06-12 06:35:45 -04001403 if (IS_ERR(*sub_root))
1404 return PTR_ERR(*sub_root);
1405
1406 ri = &(*sub_root)->root_item;
1407 location->objectid = btrfs_root_dirid(ri);
Chris Mason39279cc2007-06-12 06:35:45 -04001408 btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
1409 location->offset = 0;
1410
1411 btrfs_free_path(path);
1412 mutex_unlock(&root->fs_info->fs_mutex);
1413 return 0;
1414}
1415
1416static int btrfs_init_locked_inode(struct inode *inode, void *p)
1417{
1418 struct btrfs_iget_args *args = p;
1419 inode->i_ino = args->ino;
1420 BTRFS_I(inode)->root = args->root;
Chris Mason90692182008-02-08 13:49:28 -05001421 BTRFS_I(inode)->delalloc_bytes = 0;
Chris Masond1310b22008-01-24 16:13:08 -05001422 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1423 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
Chris Masonb888db22007-08-27 16:49:44 -04001424 inode->i_mapping, GFP_NOFS);
Chris Mason7e383262008-04-09 16:28:12 -04001425 extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
1426 inode->i_mapping, GFP_NOFS);
Chris Mason81d7ed22008-04-25 08:51:48 -04001427 atomic_set(&BTRFS_I(inode)->ordered_writeback, 0);
Chris Mason39279cc2007-06-12 06:35:45 -04001428 return 0;
1429}
1430
1431static int btrfs_find_actor(struct inode *inode, void *opaque)
1432{
1433 struct btrfs_iget_args *args = opaque;
1434 return (args->ino == inode->i_ino &&
1435 args->root == BTRFS_I(inode)->root);
1436}
1437
Chris Masondc17ff82008-01-08 15:46:30 -05001438struct inode *btrfs_ilookup(struct super_block *s, u64 objectid,
1439 u64 root_objectid)
1440{
1441 struct btrfs_iget_args args;
1442 args.ino = objectid;
1443 args.root = btrfs_lookup_fs_root(btrfs_sb(s)->fs_info, root_objectid);
1444
1445 if (!args.root)
1446 return NULL;
1447
1448 return ilookup5(s, objectid, btrfs_find_actor, (void *)&args);
1449}
1450
Chris Mason39279cc2007-06-12 06:35:45 -04001451struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid,
1452 struct btrfs_root *root)
1453{
1454 struct inode *inode;
1455 struct btrfs_iget_args args;
1456 args.ino = objectid;
1457 args.root = root;
1458
1459 inode = iget5_locked(s, objectid, btrfs_find_actor,
1460 btrfs_init_locked_inode,
1461 (void *)&args);
1462 return inode;
1463}
1464
1465static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
1466 struct nameidata *nd)
1467{
1468 struct inode * inode;
1469 struct btrfs_inode *bi = BTRFS_I(dir);
1470 struct btrfs_root *root = bi->root;
1471 struct btrfs_root *sub_root = root;
1472 struct btrfs_key location;
1473 int ret;
1474
1475 if (dentry->d_name.len > BTRFS_NAME_LEN)
1476 return ERR_PTR(-ENAMETOOLONG);
Chris Mason5f39d392007-10-15 16:14:19 -04001477
Chris Mason39279cc2007-06-12 06:35:45 -04001478 mutex_lock(&root->fs_info->fs_mutex);
1479 ret = btrfs_inode_by_name(dir, dentry, &location);
1480 mutex_unlock(&root->fs_info->fs_mutex);
Chris Mason5f39d392007-10-15 16:14:19 -04001481
Chris Mason39279cc2007-06-12 06:35:45 -04001482 if (ret < 0)
1483 return ERR_PTR(ret);
Chris Mason5f39d392007-10-15 16:14:19 -04001484
Chris Mason39279cc2007-06-12 06:35:45 -04001485 inode = NULL;
1486 if (location.objectid) {
Josef Bacik58176a92007-08-29 15:47:34 -04001487 ret = fixup_tree_root_location(root, &location, &sub_root,
1488 dentry);
Chris Mason39279cc2007-06-12 06:35:45 -04001489 if (ret < 0)
1490 return ERR_PTR(ret);
1491 if (ret > 0)
1492 return ERR_PTR(-ENOENT);
1493 inode = btrfs_iget_locked(dir->i_sb, location.objectid,
1494 sub_root);
1495 if (!inode)
1496 return ERR_PTR(-EACCES);
1497 if (inode->i_state & I_NEW) {
1498 /* the inode and parent dir are two different roots */
1499 if (sub_root != root) {
1500 igrab(inode);
1501 sub_root->inode = inode;
1502 }
1503 BTRFS_I(inode)->root = sub_root;
1504 memcpy(&BTRFS_I(inode)->location, &location,
1505 sizeof(location));
1506 btrfs_read_locked_inode(inode);
1507 unlock_new_inode(inode);
1508 }
1509 }
1510 return d_splice_alias(inode, dentry);
1511}
1512
Chris Mason39279cc2007-06-12 06:35:45 -04001513static unsigned char btrfs_filetype_table[] = {
1514 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
1515};
1516
1517static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
1518{
Chris Mason6da6aba2007-12-18 16:15:09 -05001519 struct inode *inode = filp->f_dentry->d_inode;
Chris Mason39279cc2007-06-12 06:35:45 -04001520 struct btrfs_root *root = BTRFS_I(inode)->root;
1521 struct btrfs_item *item;
1522 struct btrfs_dir_item *di;
1523 struct btrfs_key key;
Chris Mason5f39d392007-10-15 16:14:19 -04001524 struct btrfs_key found_key;
Chris Mason39279cc2007-06-12 06:35:45 -04001525 struct btrfs_path *path;
1526 int ret;
1527 u32 nritems;
Chris Mason5f39d392007-10-15 16:14:19 -04001528 struct extent_buffer *leaf;
Chris Mason39279cc2007-06-12 06:35:45 -04001529 int slot;
1530 int advance;
1531 unsigned char d_type;
1532 int over = 0;
1533 u32 di_cur;
1534 u32 di_total;
1535 u32 di_len;
1536 int key_type = BTRFS_DIR_INDEX_KEY;
Chris Mason5f39d392007-10-15 16:14:19 -04001537 char tmp_name[32];
1538 char *name_ptr;
1539 int name_len;
Chris Mason39279cc2007-06-12 06:35:45 -04001540
1541 /* FIXME, use a real flag for deciding about the key type */
1542 if (root->fs_info->tree_root == root)
1543 key_type = BTRFS_DIR_ITEM_KEY;
Chris Mason5f39d392007-10-15 16:14:19 -04001544
Chris Mason39544012007-12-12 14:38:19 -05001545 /* special case for "." */
1546 if (filp->f_pos == 0) {
1547 over = filldir(dirent, ".", 1,
1548 1, inode->i_ino,
1549 DT_DIR);
1550 if (over)
1551 return 0;
1552 filp->f_pos = 1;
1553 }
1554
Chris Mason39279cc2007-06-12 06:35:45 -04001555 mutex_lock(&root->fs_info->fs_mutex);
1556 key.objectid = inode->i_ino;
Chris Mason39544012007-12-12 14:38:19 -05001557 path = btrfs_alloc_path();
1558 path->reada = 2;
1559
1560 /* special case for .., just use the back ref */
1561 if (filp->f_pos == 1) {
1562 btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY);
1563 key.offset = 0;
1564 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1565 BUG_ON(ret == 0);
1566 leaf = path->nodes[0];
1567 slot = path->slots[0];
1568 nritems = btrfs_header_nritems(leaf);
1569 if (slot >= nritems) {
1570 btrfs_release_path(root, path);
1571 goto read_dir_items;
1572 }
1573 btrfs_item_key_to_cpu(leaf, &found_key, slot);
1574 btrfs_release_path(root, path);
1575 if (found_key.objectid != key.objectid ||
1576 found_key.type != BTRFS_INODE_REF_KEY)
1577 goto read_dir_items;
1578 over = filldir(dirent, "..", 2,
1579 2, found_key.offset, DT_DIR);
1580 if (over)
1581 goto nopos;
1582 filp->f_pos = 2;
1583 }
1584
1585read_dir_items:
Chris Mason39279cc2007-06-12 06:35:45 -04001586 btrfs_set_key_type(&key, key_type);
1587 key.offset = filp->f_pos;
Chris Mason5f39d392007-10-15 16:14:19 -04001588
Chris Mason39279cc2007-06-12 06:35:45 -04001589 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1590 if (ret < 0)
1591 goto err;
1592 advance = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001593 while(1) {
Chris Mason5f39d392007-10-15 16:14:19 -04001594 leaf = path->nodes[0];
1595 nritems = btrfs_header_nritems(leaf);
Chris Mason39279cc2007-06-12 06:35:45 -04001596 slot = path->slots[0];
1597 if (advance || slot >= nritems) {
1598 if (slot >= nritems -1) {
Chris Mason39279cc2007-06-12 06:35:45 -04001599 ret = btrfs_next_leaf(root, path);
1600 if (ret)
1601 break;
Chris Mason5f39d392007-10-15 16:14:19 -04001602 leaf = path->nodes[0];
1603 nritems = btrfs_header_nritems(leaf);
Chris Mason39279cc2007-06-12 06:35:45 -04001604 slot = path->slots[0];
1605 } else {
1606 slot++;
1607 path->slots[0]++;
1608 }
1609 }
1610 advance = 1;
Chris Mason5f39d392007-10-15 16:14:19 -04001611 item = btrfs_item_nr(leaf, slot);
1612 btrfs_item_key_to_cpu(leaf, &found_key, slot);
1613
1614 if (found_key.objectid != key.objectid)
Chris Mason39279cc2007-06-12 06:35:45 -04001615 break;
Chris Mason5f39d392007-10-15 16:14:19 -04001616 if (btrfs_key_type(&found_key) != key_type)
Chris Mason39279cc2007-06-12 06:35:45 -04001617 break;
Chris Mason5f39d392007-10-15 16:14:19 -04001618 if (found_key.offset < filp->f_pos)
Chris Mason39279cc2007-06-12 06:35:45 -04001619 continue;
Chris Mason5f39d392007-10-15 16:14:19 -04001620
1621 filp->f_pos = found_key.offset;
Chris Mason39279cc2007-06-12 06:35:45 -04001622 advance = 1;
1623 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
1624 di_cur = 0;
Chris Mason5f39d392007-10-15 16:14:19 -04001625 di_total = btrfs_item_size(leaf, item);
Chris Mason39279cc2007-06-12 06:35:45 -04001626 while(di_cur < di_total) {
Chris Mason5f39d392007-10-15 16:14:19 -04001627 struct btrfs_key location;
1628
1629 name_len = btrfs_dir_name_len(leaf, di);
1630 if (name_len < 32) {
1631 name_ptr = tmp_name;
1632 } else {
1633 name_ptr = kmalloc(name_len, GFP_NOFS);
1634 BUG_ON(!name_ptr);
1635 }
1636 read_extent_buffer(leaf, name_ptr,
1637 (unsigned long)(di + 1), name_len);
1638
1639 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
1640 btrfs_dir_item_key_to_cpu(leaf, di, &location);
Chris Mason5f39d392007-10-15 16:14:19 -04001641 over = filldir(dirent, name_ptr, name_len,
1642 found_key.offset,
1643 location.objectid,
Chris Mason39279cc2007-06-12 06:35:45 -04001644 d_type);
Chris Mason5f39d392007-10-15 16:14:19 -04001645
1646 if (name_ptr != tmp_name)
1647 kfree(name_ptr);
1648
Chris Mason39279cc2007-06-12 06:35:45 -04001649 if (over)
1650 goto nopos;
Josef Bacik5103e942007-11-16 11:45:54 -05001651 di_len = btrfs_dir_name_len(leaf, di) +
1652 btrfs_dir_data_len(leaf, di) +sizeof(*di);
Chris Mason39279cc2007-06-12 06:35:45 -04001653 di_cur += di_len;
1654 di = (struct btrfs_dir_item *)((char *)di + di_len);
1655 }
1656 }
Yan Zheng5e591a02008-02-19 11:41:02 -05001657 if (key_type == BTRFS_DIR_INDEX_KEY)
1658 filp->f_pos = INT_LIMIT(typeof(filp->f_pos));
1659 else
1660 filp->f_pos++;
Chris Mason39279cc2007-06-12 06:35:45 -04001661nopos:
1662 ret = 0;
1663err:
1664 btrfs_release_path(root, path);
1665 btrfs_free_path(path);
1666 mutex_unlock(&root->fs_info->fs_mutex);
1667 return ret;
1668}
1669
1670int btrfs_write_inode(struct inode *inode, int wait)
1671{
1672 struct btrfs_root *root = BTRFS_I(inode)->root;
1673 struct btrfs_trans_handle *trans;
1674 int ret = 0;
1675
1676 if (wait) {
1677 mutex_lock(&root->fs_info->fs_mutex);
1678 trans = btrfs_start_transaction(root, 1);
1679 btrfs_set_trans_block_group(trans, inode);
1680 ret = btrfs_commit_transaction(trans, root);
1681 mutex_unlock(&root->fs_info->fs_mutex);
1682 }
1683 return ret;
1684}
1685
1686/*
Chris Mason54aa1f42007-06-22 14:16:25 -04001687 * This is somewhat expensive, updating the tree every time the
Chris Mason39279cc2007-06-12 06:35:45 -04001688 * inode changes. But, it is most likely to find the inode in cache.
1689 * FIXME, needs more benchmarking...there are no reasons other than performance
1690 * to keep or drop this code.
1691 */
1692void btrfs_dirty_inode(struct inode *inode)
1693{
1694 struct btrfs_root *root = BTRFS_I(inode)->root;
1695 struct btrfs_trans_handle *trans;
1696
1697 mutex_lock(&root->fs_info->fs_mutex);
1698 trans = btrfs_start_transaction(root, 1);
1699 btrfs_set_trans_block_group(trans, inode);
1700 btrfs_update_inode(trans, root, inode);
1701 btrfs_end_transaction(trans, root);
1702 mutex_unlock(&root->fs_info->fs_mutex);
Chris Mason39279cc2007-06-12 06:35:45 -04001703}
1704
1705static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1706 struct btrfs_root *root,
Chris Mason9c583092008-01-29 15:15:18 -05001707 const char *name, int name_len,
1708 u64 ref_objectid,
Chris Mason39279cc2007-06-12 06:35:45 -04001709 u64 objectid,
1710 struct btrfs_block_group_cache *group,
1711 int mode)
1712{
1713 struct inode *inode;
Chris Mason5f39d392007-10-15 16:14:19 -04001714 struct btrfs_inode_item *inode_item;
Chris Mason6324fbf2008-03-24 15:01:59 -04001715 struct btrfs_block_group_cache *new_inode_group;
Chris Mason39279cc2007-06-12 06:35:45 -04001716 struct btrfs_key *location;
Chris Mason5f39d392007-10-15 16:14:19 -04001717 struct btrfs_path *path;
Chris Mason9c583092008-01-29 15:15:18 -05001718 struct btrfs_inode_ref *ref;
1719 struct btrfs_key key[2];
1720 u32 sizes[2];
1721 unsigned long ptr;
Chris Mason39279cc2007-06-12 06:35:45 -04001722 int ret;
1723 int owner;
1724
Chris Mason5f39d392007-10-15 16:14:19 -04001725 path = btrfs_alloc_path();
1726 BUG_ON(!path);
1727
Chris Mason39279cc2007-06-12 06:35:45 -04001728 inode = new_inode(root->fs_info->sb);
1729 if (!inode)
1730 return ERR_PTR(-ENOMEM);
1731
Chris Masond1310b22008-01-24 16:13:08 -05001732 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1733 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
Chris Masonb888db22007-08-27 16:49:44 -04001734 inode->i_mapping, GFP_NOFS);
Chris Mason7e383262008-04-09 16:28:12 -04001735 extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
1736 inode->i_mapping, GFP_NOFS);
Chris Mason81d7ed22008-04-25 08:51:48 -04001737 atomic_set(&BTRFS_I(inode)->ordered_writeback, 0);
Chris Mason90692182008-02-08 13:49:28 -05001738 BTRFS_I(inode)->delalloc_bytes = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001739 BTRFS_I(inode)->root = root;
Chris Masonb888db22007-08-27 16:49:44 -04001740
Chris Mason39279cc2007-06-12 06:35:45 -04001741 if (mode & S_IFDIR)
1742 owner = 0;
1743 else
1744 owner = 1;
Chris Mason6324fbf2008-03-24 15:01:59 -04001745 new_inode_group = btrfs_find_block_group(root, group, 0,
Chris Mason0b86a832008-03-24 15:01:56 -04001746 BTRFS_BLOCK_GROUP_METADATA, owner);
Chris Mason6324fbf2008-03-24 15:01:59 -04001747 if (!new_inode_group) {
1748 printk("find_block group failed\n");
1749 new_inode_group = group;
1750 }
1751 BTRFS_I(inode)->block_group = new_inode_group;
Yanb98b6762008-01-08 15:54:37 -05001752 BTRFS_I(inode)->flags = 0;
Chris Mason9c583092008-01-29 15:15:18 -05001753
1754 key[0].objectid = objectid;
1755 btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
1756 key[0].offset = 0;
1757
1758 key[1].objectid = objectid;
1759 btrfs_set_key_type(&key[1], BTRFS_INODE_REF_KEY);
1760 key[1].offset = ref_objectid;
1761
1762 sizes[0] = sizeof(struct btrfs_inode_item);
1763 sizes[1] = name_len + sizeof(*ref);
1764
1765 ret = btrfs_insert_empty_items(trans, root, path, key, sizes, 2);
1766 if (ret != 0)
Chris Mason5f39d392007-10-15 16:14:19 -04001767 goto fail;
1768
Chris Mason9c583092008-01-29 15:15:18 -05001769 if (objectid > root->highest_inode)
1770 root->highest_inode = objectid;
1771
Chris Mason39279cc2007-06-12 06:35:45 -04001772 inode->i_uid = current->fsuid;
1773 inode->i_gid = current->fsgid;
1774 inode->i_mode = mode;
1775 inode->i_ino = objectid;
1776 inode->i_blocks = 0;
1777 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
Chris Mason5f39d392007-10-15 16:14:19 -04001778 inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
1779 struct btrfs_inode_item);
1780 fill_inode_item(path->nodes[0], inode_item, inode);
Chris Mason9c583092008-01-29 15:15:18 -05001781
1782 ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1,
1783 struct btrfs_inode_ref);
1784 btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
1785 ptr = (unsigned long)(ref + 1);
1786 write_extent_buffer(path->nodes[0], name, ptr, name_len);
1787
Chris Mason5f39d392007-10-15 16:14:19 -04001788 btrfs_mark_buffer_dirty(path->nodes[0]);
1789 btrfs_free_path(path);
1790
Chris Mason39279cc2007-06-12 06:35:45 -04001791 location = &BTRFS_I(inode)->location;
1792 location->objectid = objectid;
Chris Mason39279cc2007-06-12 06:35:45 -04001793 location->offset = 0;
1794 btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
1795
Chris Mason39279cc2007-06-12 06:35:45 -04001796 insert_inode_hash(inode);
1797 return inode;
Chris Mason5f39d392007-10-15 16:14:19 -04001798fail:
1799 btrfs_free_path(path);
1800 return ERR_PTR(ret);
Chris Mason39279cc2007-06-12 06:35:45 -04001801}
1802
1803static inline u8 btrfs_inode_type(struct inode *inode)
1804{
1805 return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT];
1806}
1807
1808static int btrfs_add_link(struct btrfs_trans_handle *trans,
Chris Mason9c583092008-01-29 15:15:18 -05001809 struct dentry *dentry, struct inode *inode,
1810 int add_backref)
Chris Mason39279cc2007-06-12 06:35:45 -04001811{
1812 int ret;
1813 struct btrfs_key key;
1814 struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root;
Chris Mason79c44582007-06-25 10:09:33 -04001815 struct inode *parent_inode;
Chris Mason5f39d392007-10-15 16:14:19 -04001816
Chris Mason39279cc2007-06-12 06:35:45 -04001817 key.objectid = inode->i_ino;
Chris Mason39279cc2007-06-12 06:35:45 -04001818 btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
1819 key.offset = 0;
1820
1821 ret = btrfs_insert_dir_item(trans, root,
1822 dentry->d_name.name, dentry->d_name.len,
1823 dentry->d_parent->d_inode->i_ino,
1824 &key, btrfs_inode_type(inode));
1825 if (ret == 0) {
Chris Mason9c583092008-01-29 15:15:18 -05001826 if (add_backref) {
1827 ret = btrfs_insert_inode_ref(trans, root,
1828 dentry->d_name.name,
1829 dentry->d_name.len,
1830 inode->i_ino,
1831 dentry->d_parent->d_inode->i_ino);
1832 }
Chris Mason79c44582007-06-25 10:09:33 -04001833 parent_inode = dentry->d_parent->d_inode;
1834 parent_inode->i_size += dentry->d_name.len * 2;
1835 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
Chris Mason39279cc2007-06-12 06:35:45 -04001836 ret = btrfs_update_inode(trans, root,
1837 dentry->d_parent->d_inode);
1838 }
1839 return ret;
1840}
1841
1842static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
Chris Mason9c583092008-01-29 15:15:18 -05001843 struct dentry *dentry, struct inode *inode,
1844 int backref)
Chris Mason39279cc2007-06-12 06:35:45 -04001845{
Chris Mason9c583092008-01-29 15:15:18 -05001846 int err = btrfs_add_link(trans, dentry, inode, backref);
Chris Mason39279cc2007-06-12 06:35:45 -04001847 if (!err) {
1848 d_instantiate(dentry, inode);
1849 return 0;
1850 }
1851 if (err > 0)
1852 err = -EEXIST;
1853 return err;
1854}
1855
Josef Bacik618e21d2007-07-11 10:18:17 -04001856static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
1857 int mode, dev_t rdev)
1858{
1859 struct btrfs_trans_handle *trans;
1860 struct btrfs_root *root = BTRFS_I(dir)->root;
Chris Mason1832a6d2007-12-21 16:27:21 -05001861 struct inode *inode = NULL;
Josef Bacik618e21d2007-07-11 10:18:17 -04001862 int err;
1863 int drop_inode = 0;
1864 u64 objectid;
Chris Mason1832a6d2007-12-21 16:27:21 -05001865 unsigned long nr = 0;
Josef Bacik618e21d2007-07-11 10:18:17 -04001866
1867 if (!new_valid_dev(rdev))
1868 return -EINVAL;
1869
1870 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05001871 err = btrfs_check_free_space(root, 1, 0);
1872 if (err)
1873 goto fail;
1874
Josef Bacik618e21d2007-07-11 10:18:17 -04001875 trans = btrfs_start_transaction(root, 1);
1876 btrfs_set_trans_block_group(trans, dir);
1877
1878 err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
1879 if (err) {
1880 err = -ENOSPC;
1881 goto out_unlock;
1882 }
1883
Chris Mason9c583092008-01-29 15:15:18 -05001884 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
1885 dentry->d_name.len,
1886 dentry->d_parent->d_inode->i_ino, objectid,
Josef Bacik618e21d2007-07-11 10:18:17 -04001887 BTRFS_I(dir)->block_group, mode);
1888 err = PTR_ERR(inode);
1889 if (IS_ERR(inode))
1890 goto out_unlock;
1891
1892 btrfs_set_trans_block_group(trans, inode);
Chris Mason9c583092008-01-29 15:15:18 -05001893 err = btrfs_add_nondir(trans, dentry, inode, 0);
Josef Bacik618e21d2007-07-11 10:18:17 -04001894 if (err)
1895 drop_inode = 1;
1896 else {
1897 inode->i_op = &btrfs_special_inode_operations;
1898 init_special_inode(inode, inode->i_mode, rdev);
Yan1b4ab1b2007-08-29 09:11:44 -04001899 btrfs_update_inode(trans, root, inode);
Josef Bacik618e21d2007-07-11 10:18:17 -04001900 }
1901 dir->i_sb->s_dirt = 1;
1902 btrfs_update_inode_block_group(trans, inode);
1903 btrfs_update_inode_block_group(trans, dir);
1904out_unlock:
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001905 nr = trans->blocks_used;
Josef Bacik618e21d2007-07-11 10:18:17 -04001906 btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -05001907fail:
Josef Bacik618e21d2007-07-11 10:18:17 -04001908 mutex_unlock(&root->fs_info->fs_mutex);
1909
1910 if (drop_inode) {
1911 inode_dec_link_count(inode);
1912 iput(inode);
1913 }
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001914 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05001915 btrfs_throttle(root);
Josef Bacik618e21d2007-07-11 10:18:17 -04001916 return err;
1917}
1918
Chris Mason39279cc2007-06-12 06:35:45 -04001919static int btrfs_create(struct inode *dir, struct dentry *dentry,
1920 int mode, struct nameidata *nd)
1921{
1922 struct btrfs_trans_handle *trans;
1923 struct btrfs_root *root = BTRFS_I(dir)->root;
Chris Mason1832a6d2007-12-21 16:27:21 -05001924 struct inode *inode = NULL;
Chris Mason39279cc2007-06-12 06:35:45 -04001925 int err;
1926 int drop_inode = 0;
Chris Mason1832a6d2007-12-21 16:27:21 -05001927 unsigned long nr = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001928 u64 objectid;
1929
1930 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05001931 err = btrfs_check_free_space(root, 1, 0);
1932 if (err)
1933 goto fail;
Chris Mason39279cc2007-06-12 06:35:45 -04001934 trans = btrfs_start_transaction(root, 1);
1935 btrfs_set_trans_block_group(trans, dir);
1936
1937 err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
1938 if (err) {
1939 err = -ENOSPC;
1940 goto out_unlock;
1941 }
1942
Chris Mason9c583092008-01-29 15:15:18 -05001943 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
1944 dentry->d_name.len,
1945 dentry->d_parent->d_inode->i_ino,
1946 objectid, BTRFS_I(dir)->block_group, mode);
Chris Mason39279cc2007-06-12 06:35:45 -04001947 err = PTR_ERR(inode);
1948 if (IS_ERR(inode))
1949 goto out_unlock;
1950
1951 btrfs_set_trans_block_group(trans, inode);
Chris Mason9c583092008-01-29 15:15:18 -05001952 err = btrfs_add_nondir(trans, dentry, inode, 0);
Chris Mason39279cc2007-06-12 06:35:45 -04001953 if (err)
1954 drop_inode = 1;
1955 else {
1956 inode->i_mapping->a_ops = &btrfs_aops;
Chris Mason04160082008-03-26 10:28:07 -04001957 inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
Chris Mason39279cc2007-06-12 06:35:45 -04001958 inode->i_fop = &btrfs_file_operations;
1959 inode->i_op = &btrfs_file_inode_operations;
Chris Masond1310b22008-01-24 16:13:08 -05001960 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1961 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
Chris Masona52d9a82007-08-27 16:49:44 -04001962 inode->i_mapping, GFP_NOFS);
Chris Mason7e383262008-04-09 16:28:12 -04001963 extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
1964 inode->i_mapping, GFP_NOFS);
Chris Mason90692182008-02-08 13:49:28 -05001965 BTRFS_I(inode)->delalloc_bytes = 0;
Chris Mason81d7ed22008-04-25 08:51:48 -04001966 atomic_set(&BTRFS_I(inode)->ordered_writeback, 0);
Chris Masond1310b22008-01-24 16:13:08 -05001967 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
Chris Mason39279cc2007-06-12 06:35:45 -04001968 }
1969 dir->i_sb->s_dirt = 1;
1970 btrfs_update_inode_block_group(trans, inode);
1971 btrfs_update_inode_block_group(trans, dir);
1972out_unlock:
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001973 nr = trans->blocks_used;
Chris Mason39279cc2007-06-12 06:35:45 -04001974 btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -05001975fail:
Chris Mason39279cc2007-06-12 06:35:45 -04001976 mutex_unlock(&root->fs_info->fs_mutex);
1977
1978 if (drop_inode) {
1979 inode_dec_link_count(inode);
1980 iput(inode);
1981 }
Chris Masond3c2fdcf2007-09-17 10:58:06 -04001982 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05001983 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04001984 return err;
1985}
1986
1987static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
1988 struct dentry *dentry)
1989{
1990 struct btrfs_trans_handle *trans;
1991 struct btrfs_root *root = BTRFS_I(dir)->root;
1992 struct inode *inode = old_dentry->d_inode;
Chris Mason1832a6d2007-12-21 16:27:21 -05001993 unsigned long nr = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04001994 int err;
1995 int drop_inode = 0;
1996
1997 if (inode->i_nlink == 0)
1998 return -ENOENT;
1999
Chris Mason6da6aba2007-12-18 16:15:09 -05002000#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
2001 inode->i_nlink++;
2002#else
Chris Mason39279cc2007-06-12 06:35:45 -04002003 inc_nlink(inode);
Chris Mason6da6aba2007-12-18 16:15:09 -05002004#endif
Chris Mason39279cc2007-06-12 06:35:45 -04002005 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05002006 err = btrfs_check_free_space(root, 1, 0);
2007 if (err)
2008 goto fail;
Chris Mason39279cc2007-06-12 06:35:45 -04002009 trans = btrfs_start_transaction(root, 1);
Chris Mason5f39d392007-10-15 16:14:19 -04002010
Chris Mason39279cc2007-06-12 06:35:45 -04002011 btrfs_set_trans_block_group(trans, dir);
2012 atomic_inc(&inode->i_count);
Chris Mason9c583092008-01-29 15:15:18 -05002013 err = btrfs_add_nondir(trans, dentry, inode, 1);
Chris Mason5f39d392007-10-15 16:14:19 -04002014
Chris Mason39279cc2007-06-12 06:35:45 -04002015 if (err)
2016 drop_inode = 1;
Chris Mason5f39d392007-10-15 16:14:19 -04002017
Chris Mason39279cc2007-06-12 06:35:45 -04002018 dir->i_sb->s_dirt = 1;
2019 btrfs_update_inode_block_group(trans, dir);
Chris Mason54aa1f42007-06-22 14:16:25 -04002020 err = btrfs_update_inode(trans, root, inode);
Chris Mason5f39d392007-10-15 16:14:19 -04002021
Chris Mason54aa1f42007-06-22 14:16:25 -04002022 if (err)
2023 drop_inode = 1;
Chris Mason39279cc2007-06-12 06:35:45 -04002024
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002025 nr = trans->blocks_used;
Chris Mason39279cc2007-06-12 06:35:45 -04002026 btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -05002027fail:
Chris Mason39279cc2007-06-12 06:35:45 -04002028 mutex_unlock(&root->fs_info->fs_mutex);
2029
2030 if (drop_inode) {
2031 inode_dec_link_count(inode);
2032 iput(inode);
2033 }
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002034 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05002035 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04002036 return err;
2037}
2038
Chris Mason39279cc2007-06-12 06:35:45 -04002039static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2040{
Chris Masonb9d86662008-05-02 16:13:49 -04002041 struct inode *inode = NULL;
Chris Mason39279cc2007-06-12 06:35:45 -04002042 struct btrfs_trans_handle *trans;
2043 struct btrfs_root *root = BTRFS_I(dir)->root;
2044 int err = 0;
2045 int drop_on_err = 0;
Chris Masonb9d86662008-05-02 16:13:49 -04002046 u64 objectid = 0;
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002047 unsigned long nr = 1;
Chris Mason39279cc2007-06-12 06:35:45 -04002048
2049 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05002050 err = btrfs_check_free_space(root, 1, 0);
2051 if (err)
2052 goto out_unlock;
2053
Chris Mason39279cc2007-06-12 06:35:45 -04002054 trans = btrfs_start_transaction(root, 1);
2055 btrfs_set_trans_block_group(trans, dir);
Chris Mason5f39d392007-10-15 16:14:19 -04002056
Chris Mason39279cc2007-06-12 06:35:45 -04002057 if (IS_ERR(trans)) {
2058 err = PTR_ERR(trans);
2059 goto out_unlock;
2060 }
2061
2062 err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
2063 if (err) {
2064 err = -ENOSPC;
2065 goto out_unlock;
2066 }
2067
Chris Mason9c583092008-01-29 15:15:18 -05002068 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
2069 dentry->d_name.len,
2070 dentry->d_parent->d_inode->i_ino, objectid,
Chris Mason39279cc2007-06-12 06:35:45 -04002071 BTRFS_I(dir)->block_group, S_IFDIR | mode);
2072 if (IS_ERR(inode)) {
2073 err = PTR_ERR(inode);
2074 goto out_fail;
2075 }
Chris Mason5f39d392007-10-15 16:14:19 -04002076
Chris Mason39279cc2007-06-12 06:35:45 -04002077 drop_on_err = 1;
2078 inode->i_op = &btrfs_dir_inode_operations;
2079 inode->i_fop = &btrfs_dir_file_operations;
2080 btrfs_set_trans_block_group(trans, inode);
2081
Chris Mason39544012007-12-12 14:38:19 -05002082 inode->i_size = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04002083 err = btrfs_update_inode(trans, root, inode);
2084 if (err)
2085 goto out_fail;
Chris Mason5f39d392007-10-15 16:14:19 -04002086
Chris Mason9c583092008-01-29 15:15:18 -05002087 err = btrfs_add_link(trans, dentry, inode, 0);
Chris Mason39279cc2007-06-12 06:35:45 -04002088 if (err)
2089 goto out_fail;
Chris Mason5f39d392007-10-15 16:14:19 -04002090
Chris Mason39279cc2007-06-12 06:35:45 -04002091 d_instantiate(dentry, inode);
2092 drop_on_err = 0;
2093 dir->i_sb->s_dirt = 1;
2094 btrfs_update_inode_block_group(trans, inode);
2095 btrfs_update_inode_block_group(trans, dir);
2096
2097out_fail:
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002098 nr = trans->blocks_used;
Chris Mason39279cc2007-06-12 06:35:45 -04002099 btrfs_end_transaction(trans, root);
Chris Mason5f39d392007-10-15 16:14:19 -04002100
Chris Mason39279cc2007-06-12 06:35:45 -04002101out_unlock:
2102 mutex_unlock(&root->fs_info->fs_mutex);
2103 if (drop_on_err)
2104 iput(inode);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002105 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05002106 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04002107 return err;
2108}
2109
Chris Mason3b951512008-04-17 11:29:12 -04002110static int merge_extent_mapping(struct extent_map_tree *em_tree,
2111 struct extent_map *existing,
2112 struct extent_map *em)
2113{
2114 u64 start_diff;
2115 u64 new_end;
2116 int ret = 0;
2117 int real_blocks = existing->block_start < EXTENT_MAP_LAST_BYTE;
2118
2119 if (real_blocks && em->block_start >= EXTENT_MAP_LAST_BYTE)
2120 goto invalid;
2121
2122 if (!real_blocks && em->block_start != existing->block_start)
2123 goto invalid;
2124
2125 new_end = max(existing->start + existing->len, em->start + em->len);
2126
2127 if (existing->start >= em->start) {
2128 if (em->start + em->len < existing->start)
2129 goto invalid;
2130
2131 start_diff = existing->start - em->start;
2132 if (real_blocks && em->block_start + start_diff !=
2133 existing->block_start)
2134 goto invalid;
2135
2136 em->len = new_end - em->start;
2137
2138 remove_extent_mapping(em_tree, existing);
2139 /* free for the tree */
2140 free_extent_map(existing);
2141 ret = add_extent_mapping(em_tree, em);
2142
2143 } else if (em->start > existing->start) {
2144
2145 if (existing->start + existing->len < em->start)
2146 goto invalid;
2147
2148 start_diff = em->start - existing->start;
2149 if (real_blocks && existing->block_start + start_diff !=
2150 em->block_start)
2151 goto invalid;
2152
2153 remove_extent_mapping(em_tree, existing);
2154 em->block_start = existing->block_start;
2155 em->start = existing->start;
2156 em->len = new_end - existing->start;
2157 free_extent_map(existing);
2158
2159 ret = add_extent_mapping(em_tree, em);
2160 } else {
2161 goto invalid;
2162 }
2163 return ret;
2164
2165invalid:
2166 printk("invalid extent map merge [%Lu %Lu %Lu] [%Lu %Lu %Lu]\n",
2167 existing->start, existing->len, existing->block_start,
2168 em->start, em->len, em->block_start);
2169 return -EIO;
2170}
2171
Chris Masona52d9a82007-08-27 16:49:44 -04002172struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
Chris Mason70dec802008-01-29 09:59:12 -05002173 size_t pg_offset, u64 start, u64 len,
Chris Masona52d9a82007-08-27 16:49:44 -04002174 int create)
2175{
2176 int ret;
2177 int err = 0;
Chris Masondb945352007-10-15 16:15:53 -04002178 u64 bytenr;
Chris Masona52d9a82007-08-27 16:49:44 -04002179 u64 extent_start = 0;
2180 u64 extent_end = 0;
2181 u64 objectid = inode->i_ino;
2182 u32 found_type;
Chris Masona52d9a82007-08-27 16:49:44 -04002183 struct btrfs_path *path;
2184 struct btrfs_root *root = BTRFS_I(inode)->root;
2185 struct btrfs_file_extent_item *item;
Chris Mason5f39d392007-10-15 16:14:19 -04002186 struct extent_buffer *leaf;
2187 struct btrfs_key found_key;
Chris Masona52d9a82007-08-27 16:49:44 -04002188 struct extent_map *em = NULL;
2189 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
Chris Masond1310b22008-01-24 16:13:08 -05002190 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
Chris Masona52d9a82007-08-27 16:49:44 -04002191 struct btrfs_trans_handle *trans = NULL;
2192
2193 path = btrfs_alloc_path();
2194 BUG_ON(!path);
2195 mutex_lock(&root->fs_info->fs_mutex);
2196
2197again:
Chris Masond1310b22008-01-24 16:13:08 -05002198 spin_lock(&em_tree->lock);
2199 em = lookup_extent_mapping(em_tree, start, len);
Chris Masona061fc82008-05-07 11:43:44 -04002200 if (em)
2201 em->bdev = root->fs_info->fs_devices->latest_bdev;
Chris Masond1310b22008-01-24 16:13:08 -05002202 spin_unlock(&em_tree->lock);
2203
Chris Masona52d9a82007-08-27 16:49:44 -04002204 if (em) {
Chris Masone1c4b742008-04-22 13:26:46 -04002205 if (em->start > start || em->start + em->len <= start)
2206 free_extent_map(em);
2207 else if (em->block_start == EXTENT_MAP_INLINE && page)
Chris Mason70dec802008-01-29 09:59:12 -05002208 free_extent_map(em);
2209 else
2210 goto out;
Chris Masona52d9a82007-08-27 16:49:44 -04002211 }
Chris Masond1310b22008-01-24 16:13:08 -05002212 em = alloc_extent_map(GFP_NOFS);
Chris Masona52d9a82007-08-27 16:49:44 -04002213 if (!em) {
Chris Masond1310b22008-01-24 16:13:08 -05002214 err = -ENOMEM;
2215 goto out;
Chris Masona52d9a82007-08-27 16:49:44 -04002216 }
Chris Masond1310b22008-01-24 16:13:08 -05002217
2218 em->start = EXTENT_MAP_HOLE;
2219 em->len = (u64)-1;
Chris Masona061fc82008-05-07 11:43:44 -04002220 em->bdev = root->fs_info->fs_devices->latest_bdev;
Chris Mason179e29e2007-11-01 11:28:41 -04002221 ret = btrfs_lookup_file_extent(trans, root, path,
2222 objectid, start, trans != NULL);
Chris Masona52d9a82007-08-27 16:49:44 -04002223 if (ret < 0) {
2224 err = ret;
2225 goto out;
2226 }
2227
2228 if (ret != 0) {
2229 if (path->slots[0] == 0)
2230 goto not_found;
2231 path->slots[0]--;
2232 }
2233
Chris Mason5f39d392007-10-15 16:14:19 -04002234 leaf = path->nodes[0];
2235 item = btrfs_item_ptr(leaf, path->slots[0],
Chris Masona52d9a82007-08-27 16:49:44 -04002236 struct btrfs_file_extent_item);
Chris Masona52d9a82007-08-27 16:49:44 -04002237 /* are we inside the extent that was found? */
Chris Mason5f39d392007-10-15 16:14:19 -04002238 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
2239 found_type = btrfs_key_type(&found_key);
2240 if (found_key.objectid != objectid ||
Chris Masona52d9a82007-08-27 16:49:44 -04002241 found_type != BTRFS_EXTENT_DATA_KEY) {
2242 goto not_found;
2243 }
2244
Chris Mason5f39d392007-10-15 16:14:19 -04002245 found_type = btrfs_file_extent_type(leaf, item);
2246 extent_start = found_key.offset;
Chris Masona52d9a82007-08-27 16:49:44 -04002247 if (found_type == BTRFS_FILE_EXTENT_REG) {
2248 extent_end = extent_start +
Chris Masondb945352007-10-15 16:15:53 -04002249 btrfs_file_extent_num_bytes(leaf, item);
Chris Masona52d9a82007-08-27 16:49:44 -04002250 err = 0;
Chris Masonb888db22007-08-27 16:49:44 -04002251 if (start < extent_start || start >= extent_end) {
Chris Masona52d9a82007-08-27 16:49:44 -04002252 em->start = start;
2253 if (start < extent_start) {
Chris Masond1310b22008-01-24 16:13:08 -05002254 if (start + len <= extent_start)
Chris Masonb888db22007-08-27 16:49:44 -04002255 goto not_found;
Chris Masond1310b22008-01-24 16:13:08 -05002256 em->len = extent_end - extent_start;
Chris Masona52d9a82007-08-27 16:49:44 -04002257 } else {
Chris Masond1310b22008-01-24 16:13:08 -05002258 em->len = len;
Chris Masona52d9a82007-08-27 16:49:44 -04002259 }
2260 goto not_found_em;
2261 }
Chris Masondb945352007-10-15 16:15:53 -04002262 bytenr = btrfs_file_extent_disk_bytenr(leaf, item);
2263 if (bytenr == 0) {
Chris Masona52d9a82007-08-27 16:49:44 -04002264 em->start = extent_start;
Chris Masond1310b22008-01-24 16:13:08 -05002265 em->len = extent_end - extent_start;
Chris Mason5f39d392007-10-15 16:14:19 -04002266 em->block_start = EXTENT_MAP_HOLE;
Chris Masona52d9a82007-08-27 16:49:44 -04002267 goto insert;
2268 }
Chris Masondb945352007-10-15 16:15:53 -04002269 bytenr += btrfs_file_extent_offset(leaf, item);
2270 em->block_start = bytenr;
Chris Masona52d9a82007-08-27 16:49:44 -04002271 em->start = extent_start;
Chris Masond1310b22008-01-24 16:13:08 -05002272 em->len = extent_end - extent_start;
Chris Masona52d9a82007-08-27 16:49:44 -04002273 goto insert;
2274 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
Chris Mason70dec802008-01-29 09:59:12 -05002275 u64 page_start;
Chris Mason5f39d392007-10-15 16:14:19 -04002276 unsigned long ptr;
Chris Masona52d9a82007-08-27 16:49:44 -04002277 char *map;
Chris Mason3326d1b2007-10-15 16:18:25 -04002278 size_t size;
2279 size_t extent_offset;
2280 size_t copy_size;
Chris Masona52d9a82007-08-27 16:49:44 -04002281
Chris Mason5f39d392007-10-15 16:14:19 -04002282 size = btrfs_file_extent_inline_len(leaf, btrfs_item_nr(leaf,
2283 path->slots[0]));
Chris Masond1310b22008-01-24 16:13:08 -05002284 extent_end = (extent_start + size + root->sectorsize - 1) &
2285 ~((u64)root->sectorsize - 1);
Chris Masonb888db22007-08-27 16:49:44 -04002286 if (start < extent_start || start >= extent_end) {
Chris Masona52d9a82007-08-27 16:49:44 -04002287 em->start = start;
2288 if (start < extent_start) {
Chris Masond1310b22008-01-24 16:13:08 -05002289 if (start + len <= extent_start)
Chris Masonb888db22007-08-27 16:49:44 -04002290 goto not_found;
Chris Masond1310b22008-01-24 16:13:08 -05002291 em->len = extent_end - extent_start;
Chris Masona52d9a82007-08-27 16:49:44 -04002292 } else {
Chris Masond1310b22008-01-24 16:13:08 -05002293 em->len = len;
Chris Masona52d9a82007-08-27 16:49:44 -04002294 }
2295 goto not_found_em;
2296 }
2297 em->block_start = EXTENT_MAP_INLINE;
Yan689f9342007-10-29 11:41:07 -04002298
2299 if (!page) {
2300 em->start = extent_start;
Chris Masond1310b22008-01-24 16:13:08 -05002301 em->len = size;
Yan689f9342007-10-29 11:41:07 -04002302 goto out;
2303 }
2304
Chris Mason70dec802008-01-29 09:59:12 -05002305 page_start = page_offset(page) + pg_offset;
2306 extent_offset = page_start - extent_start;
2307 copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset,
Yan689f9342007-10-29 11:41:07 -04002308 size - extent_offset);
Chris Mason3326d1b2007-10-15 16:18:25 -04002309 em->start = extent_start + extent_offset;
Chris Mason70dec802008-01-29 09:59:12 -05002310 em->len = (copy_size + root->sectorsize - 1) &
2311 ~((u64)root->sectorsize - 1);
Yan689f9342007-10-29 11:41:07 -04002312 map = kmap(page);
2313 ptr = btrfs_file_extent_inline_start(item) + extent_offset;
Chris Mason179e29e2007-11-01 11:28:41 -04002314 if (create == 0 && !PageUptodate(page)) {
Chris Mason70dec802008-01-29 09:59:12 -05002315 read_extent_buffer(leaf, map + pg_offset, ptr,
Chris Mason179e29e2007-11-01 11:28:41 -04002316 copy_size);
2317 flush_dcache_page(page);
2318 } else if (create && PageUptodate(page)) {
2319 if (!trans) {
2320 kunmap(page);
2321 free_extent_map(em);
2322 em = NULL;
2323 btrfs_release_path(root, path);
2324 trans = btrfs_start_transaction(root, 1);
2325 goto again;
2326 }
Chris Mason70dec802008-01-29 09:59:12 -05002327 write_extent_buffer(leaf, map + pg_offset, ptr,
Chris Mason179e29e2007-11-01 11:28:41 -04002328 copy_size);
2329 btrfs_mark_buffer_dirty(leaf);
Chris Masona52d9a82007-08-27 16:49:44 -04002330 }
Chris Masona52d9a82007-08-27 16:49:44 -04002331 kunmap(page);
Chris Masond1310b22008-01-24 16:13:08 -05002332 set_extent_uptodate(io_tree, em->start,
2333 extent_map_end(em) - 1, GFP_NOFS);
Chris Masona52d9a82007-08-27 16:49:44 -04002334 goto insert;
2335 } else {
2336 printk("unkknown found_type %d\n", found_type);
2337 WARN_ON(1);
2338 }
2339not_found:
2340 em->start = start;
Chris Masond1310b22008-01-24 16:13:08 -05002341 em->len = len;
Chris Masona52d9a82007-08-27 16:49:44 -04002342not_found_em:
Chris Mason5f39d392007-10-15 16:14:19 -04002343 em->block_start = EXTENT_MAP_HOLE;
Chris Masona52d9a82007-08-27 16:49:44 -04002344insert:
2345 btrfs_release_path(root, path);
Chris Masond1310b22008-01-24 16:13:08 -05002346 if (em->start > start || extent_map_end(em) <= start) {
2347 printk("bad extent! em: [%Lu %Lu] passed [%Lu %Lu]\n", em->start, em->len, start, len);
Chris Masona52d9a82007-08-27 16:49:44 -04002348 err = -EIO;
2349 goto out;
2350 }
Chris Masond1310b22008-01-24 16:13:08 -05002351
2352 err = 0;
2353 spin_lock(&em_tree->lock);
Chris Masona52d9a82007-08-27 16:49:44 -04002354 ret = add_extent_mapping(em_tree, em);
Chris Mason3b951512008-04-17 11:29:12 -04002355 /* it is possible that someone inserted the extent into the tree
2356 * while we had the lock dropped. It is also possible that
2357 * an overlapping map exists in the tree
2358 */
Chris Masona52d9a82007-08-27 16:49:44 -04002359 if (ret == -EEXIST) {
Chris Mason3b951512008-04-17 11:29:12 -04002360 struct extent_map *existing;
2361 existing = lookup_extent_mapping(em_tree, start, len);
Chris Masone1c4b742008-04-22 13:26:46 -04002362 if (existing && (existing->start > start ||
2363 existing->start + existing->len <= start)) {
2364 free_extent_map(existing);
2365 existing = NULL;
2366 }
Chris Mason3b951512008-04-17 11:29:12 -04002367 if (!existing) {
2368 existing = lookup_extent_mapping(em_tree, em->start,
2369 em->len);
2370 if (existing) {
2371 err = merge_extent_mapping(em_tree, existing,
2372 em);
2373 free_extent_map(existing);
2374 if (err) {
2375 free_extent_map(em);
2376 em = NULL;
2377 }
2378 } else {
2379 err = -EIO;
2380 printk("failing to insert %Lu %Lu\n",
2381 start, len);
2382 free_extent_map(em);
2383 em = NULL;
2384 }
2385 } else {
2386 free_extent_map(em);
2387 em = existing;
Chris Masona52d9a82007-08-27 16:49:44 -04002388 }
Chris Masona52d9a82007-08-27 16:49:44 -04002389 }
Chris Masond1310b22008-01-24 16:13:08 -05002390 spin_unlock(&em_tree->lock);
Chris Masona52d9a82007-08-27 16:49:44 -04002391out:
2392 btrfs_free_path(path);
2393 if (trans) {
2394 ret = btrfs_end_transaction(trans, root);
2395 if (!err)
2396 err = ret;
2397 }
2398 mutex_unlock(&root->fs_info->fs_mutex);
2399 if (err) {
2400 free_extent_map(em);
2401 WARN_ON(1);
2402 return ERR_PTR(err);
2403 }
2404 return em;
2405}
2406
Chris Masone1c4b742008-04-22 13:26:46 -04002407#if 0 /* waiting for O_DIRECT reads */
Chris Mason16432982008-04-10 10:23:21 -04002408static int btrfs_get_block(struct inode *inode, sector_t iblock,
2409 struct buffer_head *bh_result, int create)
2410{
2411 struct extent_map *em;
2412 u64 start = (u64)iblock << inode->i_blkbits;
2413 struct btrfs_multi_bio *multi = NULL;
2414 struct btrfs_root *root = BTRFS_I(inode)->root;
2415 u64 len;
2416 u64 logical;
2417 u64 map_length;
2418 int ret = 0;
2419
2420 em = btrfs_get_extent(inode, NULL, 0, start, bh_result->b_size, 0);
2421
2422 if (!em || IS_ERR(em))
2423 goto out;
2424
Chris Masone1c4b742008-04-22 13:26:46 -04002425 if (em->start > start || em->start + em->len <= start) {
Chris Mason16432982008-04-10 10:23:21 -04002426 goto out;
Chris Masone1c4b742008-04-22 13:26:46 -04002427 }
Chris Mason16432982008-04-10 10:23:21 -04002428
2429 if (em->block_start == EXTENT_MAP_INLINE) {
2430 ret = -EINVAL;
2431 goto out;
2432 }
2433
Chris Mason16432982008-04-10 10:23:21 -04002434 len = em->start + em->len - start;
2435 len = min_t(u64, len, INT_LIMIT(typeof(bh_result->b_size)));
2436
Chris Masone1c4b742008-04-22 13:26:46 -04002437 if (em->block_start == EXTENT_MAP_HOLE ||
2438 em->block_start == EXTENT_MAP_DELALLOC) {
2439 bh_result->b_size = len;
2440 goto out;
2441 }
2442
Chris Mason16432982008-04-10 10:23:21 -04002443 logical = start - em->start;
2444 logical = em->block_start + logical;
2445
2446 map_length = len;
2447 ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
2448 logical, &map_length, &multi, 0);
2449 BUG_ON(ret);
2450 bh_result->b_blocknr = multi->stripes[0].physical >> inode->i_blkbits;
2451 bh_result->b_size = min(map_length, len);
Chris Masone1c4b742008-04-22 13:26:46 -04002452
Chris Mason16432982008-04-10 10:23:21 -04002453 bh_result->b_bdev = multi->stripes[0].dev->bdev;
2454 set_buffer_mapped(bh_result);
2455 kfree(multi);
2456out:
2457 free_extent_map(em);
2458 return ret;
2459}
Chris Masone1c4b742008-04-22 13:26:46 -04002460#endif
Chris Mason16432982008-04-10 10:23:21 -04002461
2462static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
2463 const struct iovec *iov, loff_t offset,
2464 unsigned long nr_segs)
2465{
Chris Masone1c4b742008-04-22 13:26:46 -04002466 return -EINVAL;
2467#if 0
Chris Mason16432982008-04-10 10:23:21 -04002468 struct file *file = iocb->ki_filp;
2469 struct inode *inode = file->f_mapping->host;
2470
2471 if (rw == WRITE)
2472 return -EINVAL;
2473
2474 return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
2475 offset, nr_segs, btrfs_get_block, NULL);
Chris Masone1c4b742008-04-22 13:26:46 -04002476#endif
Chris Mason16432982008-04-10 10:23:21 -04002477}
2478
Christoph Hellwigd396c6f2007-09-10 20:02:30 -04002479static sector_t btrfs_bmap(struct address_space *mapping, sector_t iblock)
Chris Mason39279cc2007-06-12 06:35:45 -04002480{
Christoph Hellwigd396c6f2007-09-10 20:02:30 -04002481 return extent_bmap(mapping, iblock, btrfs_get_extent);
Chris Mason39279cc2007-06-12 06:35:45 -04002482}
2483
Chris Mason9ebefb182007-06-15 13:50:00 -04002484int btrfs_readpage(struct file *file, struct page *page)
2485{
Chris Masond1310b22008-01-24 16:13:08 -05002486 struct extent_io_tree *tree;
2487 tree = &BTRFS_I(page->mapping->host)->io_tree;
Chris Masona52d9a82007-08-27 16:49:44 -04002488 return extent_read_full_page(tree, page, btrfs_get_extent);
Chris Mason39279cc2007-06-12 06:35:45 -04002489}
Chris Mason1832a6d2007-12-21 16:27:21 -05002490
Chris Mason39279cc2007-06-12 06:35:45 -04002491static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
2492{
Chris Masond1310b22008-01-24 16:13:08 -05002493 struct extent_io_tree *tree;
Chris Masonb888db22007-08-27 16:49:44 -04002494
2495
2496 if (current->flags & PF_MEMALLOC) {
2497 redirty_page_for_writepage(wbc, page);
2498 unlock_page(page);
2499 return 0;
2500 }
Chris Masond1310b22008-01-24 16:13:08 -05002501 tree = &BTRFS_I(page->mapping->host)->io_tree;
Chris Masona52d9a82007-08-27 16:49:44 -04002502 return extent_write_full_page(tree, page, btrfs_get_extent, wbc);
2503}
Chris Mason39279cc2007-06-12 06:35:45 -04002504
Chris Masonb293f02e2007-11-01 19:45:34 -04002505static int btrfs_writepages(struct address_space *mapping,
2506 struct writeback_control *wbc)
2507{
Chris Masond1310b22008-01-24 16:13:08 -05002508 struct extent_io_tree *tree;
2509 tree = &BTRFS_I(mapping->host)->io_tree;
Chris Masonb293f02e2007-11-01 19:45:34 -04002510 return extent_writepages(tree, mapping, btrfs_get_extent, wbc);
2511}
2512
Chris Mason3ab2fb52007-11-08 10:59:22 -05002513static int
2514btrfs_readpages(struct file *file, struct address_space *mapping,
2515 struct list_head *pages, unsigned nr_pages)
2516{
Chris Masond1310b22008-01-24 16:13:08 -05002517 struct extent_io_tree *tree;
2518 tree = &BTRFS_I(mapping->host)->io_tree;
Chris Mason3ab2fb52007-11-08 10:59:22 -05002519 return extent_readpages(tree, mapping, pages, nr_pages,
2520 btrfs_get_extent);
2521}
2522
Chris Mason70dec802008-01-29 09:59:12 -05002523static int btrfs_releasepage(struct page *page, gfp_t gfp_flags)
Chris Masona52d9a82007-08-27 16:49:44 -04002524{
Chris Masond1310b22008-01-24 16:13:08 -05002525 struct extent_io_tree *tree;
2526 struct extent_map_tree *map;
Chris Masona52d9a82007-08-27 16:49:44 -04002527 int ret;
Chris Mason39279cc2007-06-12 06:35:45 -04002528
Chris Masond1310b22008-01-24 16:13:08 -05002529 tree = &BTRFS_I(page->mapping->host)->io_tree;
2530 map = &BTRFS_I(page->mapping->host)->extent_tree;
Chris Mason70dec802008-01-29 09:59:12 -05002531 ret = try_release_extent_mapping(map, tree, page, gfp_flags);
Chris Masona52d9a82007-08-27 16:49:44 -04002532 if (ret == 1) {
Chris Mason4ef64ea2008-04-21 08:52:50 -04002533 invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
Chris Masona52d9a82007-08-27 16:49:44 -04002534 ClearPagePrivate(page);
2535 set_page_private(page, 0);
2536 page_cache_release(page);
2537 }
2538 return ret;
2539}
Chris Mason39279cc2007-06-12 06:35:45 -04002540
Chris Masona52d9a82007-08-27 16:49:44 -04002541static void btrfs_invalidatepage(struct page *page, unsigned long offset)
2542{
Chris Masond1310b22008-01-24 16:13:08 -05002543 struct extent_io_tree *tree;
Chris Masona52d9a82007-08-27 16:49:44 -04002544
Chris Masond1310b22008-01-24 16:13:08 -05002545 tree = &BTRFS_I(page->mapping->host)->io_tree;
Chris Masona52d9a82007-08-27 16:49:44 -04002546 extent_invalidatepage(tree, page, offset);
2547 btrfs_releasepage(page, GFP_NOFS);
Chris Mason9ad6b7bc2008-04-18 16:11:30 -04002548 if (PagePrivate(page)) {
Chris Mason4ef64ea2008-04-21 08:52:50 -04002549 invalidate_extent_lru(tree, page_offset(page), PAGE_CACHE_SIZE);
Chris Mason9ad6b7bc2008-04-18 16:11:30 -04002550 ClearPagePrivate(page);
2551 set_page_private(page, 0);
2552 page_cache_release(page);
2553 }
Chris Mason39279cc2007-06-12 06:35:45 -04002554}
2555
Chris Mason9ebefb182007-06-15 13:50:00 -04002556/*
2557 * btrfs_page_mkwrite() is not allowed to change the file size as it gets
2558 * called from a page fault handler when a page is first dirtied. Hence we must
2559 * be careful to check for EOF conditions here. We set the page up correctly
2560 * for a written page which means we get ENOSPC checking when writing into
2561 * holes and correct delalloc and unwritten extent mapping on filesystems that
2562 * support these features.
2563 *
2564 * We are not allowed to take the i_mutex here so we have to play games to
2565 * protect against truncate races as the page could now be beyond EOF. Because
2566 * vmtruncate() writes the inode size before removing pages, once we have the
2567 * page lock we can determine safely if the page is beyond EOF. If it is not
2568 * beyond EOF, then the page is guaranteed safe against truncation until we
2569 * unlock the page.
2570 */
2571int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
2572{
Chris Mason6da6aba2007-12-18 16:15:09 -05002573 struct inode *inode = fdentry(vma->vm_file)->d_inode;
Chris Mason1832a6d2007-12-21 16:27:21 -05002574 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Mason9ebefb182007-06-15 13:50:00 -04002575 unsigned long end;
2576 loff_t size;
Chris Mason1832a6d2007-12-21 16:27:21 -05002577 int ret;
Chris Masona52d9a82007-08-27 16:49:44 -04002578 u64 page_start;
Chris Mason9ebefb182007-06-15 13:50:00 -04002579
Chris Mason1832a6d2007-12-21 16:27:21 -05002580 mutex_lock(&root->fs_info->fs_mutex);
2581 ret = btrfs_check_free_space(root, PAGE_CACHE_SIZE, 0);
Chris Mason8f662a72008-01-02 10:01:11 -05002582 mutex_unlock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05002583 if (ret)
2584 goto out;
2585
2586 ret = -EINVAL;
2587
Chris Mason9ebefb182007-06-15 13:50:00 -04002588 lock_page(page);
2589 wait_on_page_writeback(page);
Chris Mason9ebefb182007-06-15 13:50:00 -04002590 size = i_size_read(inode);
Chris Mason35ebb932007-10-30 16:56:53 -04002591 page_start = (u64)page->index << PAGE_CACHE_SHIFT;
Chris Masona52d9a82007-08-27 16:49:44 -04002592
Chris Mason9ebefb182007-06-15 13:50:00 -04002593 if ((page->mapping != inode->i_mapping) ||
Chris Masona52d9a82007-08-27 16:49:44 -04002594 (page_start > size)) {
Chris Mason9ebefb182007-06-15 13:50:00 -04002595 /* page got truncated out from underneath us */
2596 goto out_unlock;
2597 }
2598
2599 /* page is wholly or partially inside EOF */
Chris Masona52d9a82007-08-27 16:49:44 -04002600 if (page_start + PAGE_CACHE_SIZE > size)
Chris Mason9ebefb182007-06-15 13:50:00 -04002601 end = size & ~PAGE_CACHE_MASK;
2602 else
2603 end = PAGE_CACHE_SIZE;
2604
Chris Masonb888db22007-08-27 16:49:44 -04002605 ret = btrfs_cow_one_page(inode, page, end);
Chris Mason9ebefb182007-06-15 13:50:00 -04002606
2607out_unlock:
2608 unlock_page(page);
Chris Mason1832a6d2007-12-21 16:27:21 -05002609out:
Chris Mason9ebefb182007-06-15 13:50:00 -04002610 return ret;
2611}
2612
Chris Mason39279cc2007-06-12 06:35:45 -04002613static void btrfs_truncate(struct inode *inode)
2614{
2615 struct btrfs_root *root = BTRFS_I(inode)->root;
2616 int ret;
2617 struct btrfs_trans_handle *trans;
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002618 unsigned long nr;
Chris Mason39279cc2007-06-12 06:35:45 -04002619
2620 if (!S_ISREG(inode->i_mode))
2621 return;
2622 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2623 return;
2624
2625 btrfs_truncate_page(inode->i_mapping, inode->i_size);
2626
2627 mutex_lock(&root->fs_info->fs_mutex);
2628 trans = btrfs_start_transaction(root, 1);
2629 btrfs_set_trans_block_group(trans, inode);
2630
2631 /* FIXME, add redo link to tree so we don't leak on crash */
Chris Mason85e21ba2008-01-29 15:11:36 -05002632 ret = btrfs_truncate_in_trans(trans, root, inode,
2633 BTRFS_EXTENT_DATA_KEY);
Chris Mason39279cc2007-06-12 06:35:45 -04002634 btrfs_update_inode(trans, root, inode);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002635 nr = trans->blocks_used;
Chris Mason5f39d392007-10-15 16:14:19 -04002636
Chris Mason39279cc2007-06-12 06:35:45 -04002637 ret = btrfs_end_transaction(trans, root);
2638 BUG_ON(ret);
2639 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002640 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05002641 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04002642}
2643
Chris Mason4313b392008-01-03 09:08:48 -05002644static int noinline create_subvol(struct btrfs_root *root, char *name,
2645 int namelen)
Chris Mason39279cc2007-06-12 06:35:45 -04002646{
2647 struct btrfs_trans_handle *trans;
2648 struct btrfs_key key;
2649 struct btrfs_root_item root_item;
2650 struct btrfs_inode_item *inode_item;
Chris Mason5f39d392007-10-15 16:14:19 -04002651 struct extent_buffer *leaf;
Chris Masondc17ff82008-01-08 15:46:30 -05002652 struct btrfs_root *new_root = root;
Chris Mason39279cc2007-06-12 06:35:45 -04002653 struct inode *inode;
2654 struct inode *dir;
2655 int ret;
Chris Mason54aa1f42007-06-22 14:16:25 -04002656 int err;
Chris Mason39279cc2007-06-12 06:35:45 -04002657 u64 objectid;
2658 u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002659 unsigned long nr = 1;
Chris Mason39279cc2007-06-12 06:35:45 -04002660
2661 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05002662 ret = btrfs_check_free_space(root, 1, 0);
2663 if (ret)
2664 goto fail_commit;
2665
Chris Mason39279cc2007-06-12 06:35:45 -04002666 trans = btrfs_start_transaction(root, 1);
2667 BUG_ON(!trans);
2668
Chris Mason7bb86312007-12-11 09:25:06 -05002669 ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root,
2670 0, &objectid);
2671 if (ret)
2672 goto fail;
2673
2674 leaf = __btrfs_alloc_free_block(trans, root, root->leafsize,
2675 objectid, trans->transid, 0, 0,
2676 0, 0);
Chris Mason5f39d392007-10-15 16:14:19 -04002677 if (IS_ERR(leaf))
2678 return PTR_ERR(leaf);
2679
2680 btrfs_set_header_nritems(leaf, 0);
2681 btrfs_set_header_level(leaf, 0);
Chris Masondb945352007-10-15 16:15:53 -04002682 btrfs_set_header_bytenr(leaf, leaf->start);
Chris Mason5f39d392007-10-15 16:14:19 -04002683 btrfs_set_header_generation(leaf, trans->transid);
Chris Mason7bb86312007-12-11 09:25:06 -05002684 btrfs_set_header_owner(leaf, objectid);
2685
Chris Mason5f39d392007-10-15 16:14:19 -04002686 write_extent_buffer(leaf, root->fs_info->fsid,
2687 (unsigned long)btrfs_header_fsid(leaf),
2688 BTRFS_FSID_SIZE);
2689 btrfs_mark_buffer_dirty(leaf);
Chris Mason39279cc2007-06-12 06:35:45 -04002690
2691 inode_item = &root_item.inode;
2692 memset(inode_item, 0, sizeof(*inode_item));
Chris Mason5f39d392007-10-15 16:14:19 -04002693 inode_item->generation = cpu_to_le64(1);
2694 inode_item->size = cpu_to_le64(3);
2695 inode_item->nlink = cpu_to_le32(1);
2696 inode_item->nblocks = cpu_to_le64(1);
2697 inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
Chris Mason39279cc2007-06-12 06:35:45 -04002698
Chris Masondb945352007-10-15 16:15:53 -04002699 btrfs_set_root_bytenr(&root_item, leaf->start);
2700 btrfs_set_root_level(&root_item, 0);
Chris Mason39279cc2007-06-12 06:35:45 -04002701 btrfs_set_root_refs(&root_item, 1);
Chris Mason5f39d392007-10-15 16:14:19 -04002702 btrfs_set_root_used(&root_item, 0);
2703
Chris Mason5eda7b52007-06-22 14:16:25 -04002704 memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
2705 root_item.drop_level = 0;
Chris Mason5f39d392007-10-15 16:14:19 -04002706
2707 free_extent_buffer(leaf);
2708 leaf = NULL;
Chris Mason39279cc2007-06-12 06:35:45 -04002709
Chris Mason39279cc2007-06-12 06:35:45 -04002710 btrfs_set_root_dirid(&root_item, new_dirid);
2711
2712 key.objectid = objectid;
2713 key.offset = 1;
Chris Mason39279cc2007-06-12 06:35:45 -04002714 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
2715 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
2716 &root_item);
Chris Mason54aa1f42007-06-22 14:16:25 -04002717 if (ret)
2718 goto fail;
Chris Mason39279cc2007-06-12 06:35:45 -04002719
2720 /*
2721 * insert the directory item
2722 */
2723 key.offset = (u64)-1;
2724 dir = root->fs_info->sb->s_root->d_inode;
2725 ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
2726 name, namelen, dir->i_ino, &key,
2727 BTRFS_FT_DIR);
Chris Mason54aa1f42007-06-22 14:16:25 -04002728 if (ret)
2729 goto fail;
Chris Mason39279cc2007-06-12 06:35:45 -04002730
Chris Mason39544012007-12-12 14:38:19 -05002731 ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
2732 name, namelen, objectid,
2733 root->fs_info->sb->s_root->d_inode->i_ino);
2734 if (ret)
2735 goto fail;
2736
Chris Mason39279cc2007-06-12 06:35:45 -04002737 ret = btrfs_commit_transaction(trans, root);
Chris Mason54aa1f42007-06-22 14:16:25 -04002738 if (ret)
2739 goto fail_commit;
Chris Mason39279cc2007-06-12 06:35:45 -04002740
Josef Bacik58176a92007-08-29 15:47:34 -04002741 new_root = btrfs_read_fs_root(root->fs_info, &key, name, namelen);
Chris Mason39279cc2007-06-12 06:35:45 -04002742 BUG_ON(!new_root);
2743
2744 trans = btrfs_start_transaction(new_root, 1);
2745 BUG_ON(!trans);
2746
Chris Mason9c583092008-01-29 15:15:18 -05002747 inode = btrfs_new_inode(trans, new_root, "..", 2, new_dirid,
2748 new_dirid,
Chris Mason39279cc2007-06-12 06:35:45 -04002749 BTRFS_I(dir)->block_group, S_IFDIR | 0700);
Chris Mason54aa1f42007-06-22 14:16:25 -04002750 if (IS_ERR(inode))
2751 goto fail;
Chris Mason39279cc2007-06-12 06:35:45 -04002752 inode->i_op = &btrfs_dir_inode_operations;
2753 inode->i_fop = &btrfs_dir_file_operations;
Chris Mason34088782007-06-12 11:36:58 -04002754 new_root->inode = inode;
Chris Mason39279cc2007-06-12 06:35:45 -04002755
Chris Mason39544012007-12-12 14:38:19 -05002756 ret = btrfs_insert_inode_ref(trans, new_root, "..", 2, new_dirid,
2757 new_dirid);
Chris Mason39279cc2007-06-12 06:35:45 -04002758 inode->i_nlink = 1;
Chris Mason39544012007-12-12 14:38:19 -05002759 inode->i_size = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04002760 ret = btrfs_update_inode(trans, new_root, inode);
Chris Mason54aa1f42007-06-22 14:16:25 -04002761 if (ret)
2762 goto fail;
2763fail:
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002764 nr = trans->blocks_used;
Chris Masondc17ff82008-01-08 15:46:30 -05002765 err = btrfs_commit_transaction(trans, new_root);
Chris Mason54aa1f42007-06-22 14:16:25 -04002766 if (err && !ret)
2767 ret = err;
2768fail_commit:
Chris Mason39279cc2007-06-12 06:35:45 -04002769 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002770 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05002771 btrfs_throttle(root);
Chris Mason54aa1f42007-06-22 14:16:25 -04002772 return ret;
Chris Mason39279cc2007-06-12 06:35:45 -04002773}
2774
2775static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
2776{
Chris Mason3063d292008-01-08 15:46:30 -05002777 struct btrfs_pending_snapshot *pending_snapshot;
Chris Mason39279cc2007-06-12 06:35:45 -04002778 struct btrfs_trans_handle *trans;
Chris Mason39279cc2007-06-12 06:35:45 -04002779 int ret;
Chris Mason54aa1f42007-06-22 14:16:25 -04002780 int err;
Chris Mason1832a6d2007-12-21 16:27:21 -05002781 unsigned long nr = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04002782
2783 if (!root->ref_cows)
2784 return -EINVAL;
2785
2786 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05002787 ret = btrfs_check_free_space(root, 1, 0);
2788 if (ret)
2789 goto fail_unlock;
2790
Chris Mason3063d292008-01-08 15:46:30 -05002791 pending_snapshot = kmalloc(sizeof(*pending_snapshot), GFP_NOFS);
2792 if (!pending_snapshot) {
2793 ret = -ENOMEM;
2794 goto fail_unlock;
2795 }
Yanfb4bc1e2008-01-17 11:59:51 -05002796 pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS);
Chris Mason3063d292008-01-08 15:46:30 -05002797 if (!pending_snapshot->name) {
2798 ret = -ENOMEM;
2799 kfree(pending_snapshot);
2800 goto fail_unlock;
2801 }
Yanfb4bc1e2008-01-17 11:59:51 -05002802 memcpy(pending_snapshot->name, name, namelen);
2803 pending_snapshot->name[namelen] = '\0';
Chris Mason39279cc2007-06-12 06:35:45 -04002804 trans = btrfs_start_transaction(root, 1);
2805 BUG_ON(!trans);
Chris Mason3063d292008-01-08 15:46:30 -05002806 pending_snapshot->root = root;
2807 list_add(&pending_snapshot->list,
2808 &trans->transaction->pending_snapshots);
Chris Mason39279cc2007-06-12 06:35:45 -04002809 ret = btrfs_update_inode(trans, root, root->inode);
Chris Mason54aa1f42007-06-22 14:16:25 -04002810 err = btrfs_commit_transaction(trans, root);
Chris Mason5f39d392007-10-15 16:14:19 -04002811
Chris Mason1832a6d2007-12-21 16:27:21 -05002812fail_unlock:
Chris Mason39279cc2007-06-12 06:35:45 -04002813 mutex_unlock(&root->fs_info->fs_mutex);
Chris Masond3c2fdcf2007-09-17 10:58:06 -04002814 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05002815 btrfs_throttle(root);
Chris Mason54aa1f42007-06-22 14:16:25 -04002816 return ret;
Chris Mason39279cc2007-06-12 06:35:45 -04002817}
2818
Chris Masonedbd8d42007-12-21 16:27:24 -05002819unsigned long btrfs_force_ra(struct address_space *mapping,
Chris Mason86479a02007-09-10 19:58:16 -04002820 struct file_ra_state *ra, struct file *file,
2821 pgoff_t offset, pgoff_t last_index)
2822{
Chris Mason8e7bf942008-04-28 09:02:36 -04002823 pgoff_t req_size = last_index - offset + 1;
Chris Mason86479a02007-09-10 19:58:16 -04002824
2825#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
Chris Mason86479a02007-09-10 19:58:16 -04002826 offset = page_cache_readahead(mapping, ra, file, offset, req_size);
2827 return offset;
2828#else
Chris Mason86479a02007-09-10 19:58:16 -04002829 page_cache_sync_readahead(mapping, ra, file, offset, req_size);
2830 return offset + req_size;
2831#endif
2832}
2833
2834int btrfs_defrag_file(struct file *file) {
Chris Mason6da6aba2007-12-18 16:15:09 -05002835 struct inode *inode = fdentry(file)->d_inode;
Chris Mason1832a6d2007-12-21 16:27:21 -05002836 struct btrfs_root *root = BTRFS_I(inode)->root;
Chris Masond1310b22008-01-24 16:13:08 -05002837 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
Chris Mason86479a02007-09-10 19:58:16 -04002838 struct page *page;
2839 unsigned long last_index;
Chris Mason8e7bf942008-04-28 09:02:36 -04002840 unsigned long ra_pages = root->fs_info->bdi.ra_pages;
2841 unsigned long total_read = 0;
Chris Mason86479a02007-09-10 19:58:16 -04002842 u64 page_start;
2843 u64 page_end;
2844 unsigned long i;
Chris Mason1832a6d2007-12-21 16:27:21 -05002845 int ret;
2846
2847 mutex_lock(&root->fs_info->fs_mutex);
2848 ret = btrfs_check_free_space(root, inode->i_size, 0);
2849 mutex_unlock(&root->fs_info->fs_mutex);
2850 if (ret)
2851 return -ENOSPC;
Chris Mason86479a02007-09-10 19:58:16 -04002852
2853 mutex_lock(&inode->i_mutex);
2854 last_index = inode->i_size >> PAGE_CACHE_SHIFT;
2855 for (i = 0; i <= last_index; i++) {
Chris Mason8e7bf942008-04-28 09:02:36 -04002856 if (total_read % ra_pages == 0) {
2857 btrfs_force_ra(inode->i_mapping, &file->f_ra, file, i,
2858 min(last_index, i + ra_pages - 1));
Chris Mason86479a02007-09-10 19:58:16 -04002859 }
Chris Mason8e7bf942008-04-28 09:02:36 -04002860 total_read++;
Chris Mason86479a02007-09-10 19:58:16 -04002861 page = grab_cache_page(inode->i_mapping, i);
2862 if (!page)
2863 goto out_unlock;
2864 if (!PageUptodate(page)) {
2865 btrfs_readpage(NULL, page);
2866 lock_page(page);
2867 if (!PageUptodate(page)) {
2868 unlock_page(page);
2869 page_cache_release(page);
2870 goto out_unlock;
2871 }
2872 }
Chris Masonec44a352008-04-28 15:29:52 -04002873
2874#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
2875 ClearPageDirty(page);
2876#else
2877 cancel_dirty_page(page, PAGE_CACHE_SIZE);
2878#endif
2879 wait_on_page_writeback(page);
2880 set_page_extent_mapped(page);
2881
Chris Mason35ebb932007-10-30 16:56:53 -04002882 page_start = (u64)page->index << PAGE_CACHE_SHIFT;
Chris Mason86479a02007-09-10 19:58:16 -04002883 page_end = page_start + PAGE_CACHE_SIZE - 1;
2884
Chris Masond1310b22008-01-24 16:13:08 -05002885 lock_extent(io_tree, page_start, page_end, GFP_NOFS);
Chris Masond1310b22008-01-24 16:13:08 -05002886 set_extent_delalloc(io_tree, page_start,
Chris Mason86479a02007-09-10 19:58:16 -04002887 page_end, GFP_NOFS);
Chris Masonedbd8d42007-12-21 16:27:24 -05002888
Chris Masond1310b22008-01-24 16:13:08 -05002889 unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
Chris Mason86479a02007-09-10 19:58:16 -04002890 set_page_dirty(page);
2891 unlock_page(page);
2892 page_cache_release(page);
2893 balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1);
2894 }
2895
2896out_unlock:
2897 mutex_unlock(&inode->i_mutex);
2898 return 0;
2899}
2900
Chris Masonedbd8d42007-12-21 16:27:24 -05002901static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
2902{
2903 u64 new_size;
2904 u64 old_size;
Chris Mason8f18cf12008-04-25 16:53:30 -04002905 u64 devid = 1;
Chris Masonedbd8d42007-12-21 16:27:24 -05002906 struct btrfs_ioctl_vol_args *vol_args;
2907 struct btrfs_trans_handle *trans;
Chris Mason8f18cf12008-04-25 16:53:30 -04002908 struct btrfs_device *device = NULL;
Chris Masonedbd8d42007-12-21 16:27:24 -05002909 char *sizestr;
Chris Mason8f18cf12008-04-25 16:53:30 -04002910 char *devstr = NULL;
Chris Masonedbd8d42007-12-21 16:27:24 -05002911 int ret = 0;
2912 int namelen;
2913 int mod = 0;
2914
2915 vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
2916
2917 if (!vol_args)
2918 return -ENOMEM;
2919
2920 if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
2921 ret = -EFAULT;
2922 goto out;
2923 }
2924 namelen = strlen(vol_args->name);
2925 if (namelen > BTRFS_VOL_NAME_MAX) {
2926 ret = -EINVAL;
2927 goto out;
2928 }
2929
Chris Mason8f18cf12008-04-25 16:53:30 -04002930 mutex_lock(&root->fs_info->fs_mutex);
Chris Masonedbd8d42007-12-21 16:27:24 -05002931 sizestr = vol_args->name;
Chris Mason8f18cf12008-04-25 16:53:30 -04002932 devstr = strchr(sizestr, ':');
2933 if (devstr) {
2934 char *end;
2935 sizestr = devstr + 1;
2936 *devstr = '\0';
2937 devstr = vol_args->name;
2938 devid = simple_strtoull(devstr, &end, 10);
2939printk("resizing devid %Lu\n", devid);
2940 }
2941 device = btrfs_find_device(root, devid, NULL);
2942 if (!device) {
2943 printk("resizer unable to find device %Lu\n", devid);
2944 ret = -EINVAL;
2945 goto out_unlock;
2946 }
Chris Masonedbd8d42007-12-21 16:27:24 -05002947 if (!strcmp(sizestr, "max"))
Chris Mason8f18cf12008-04-25 16:53:30 -04002948 new_size = device->bdev->bd_inode->i_size;
Chris Masonedbd8d42007-12-21 16:27:24 -05002949 else {
2950 if (sizestr[0] == '-') {
2951 mod = -1;
2952 sizestr++;
2953 } else if (sizestr[0] == '+') {
2954 mod = 1;
2955 sizestr++;
2956 }
2957 new_size = btrfs_parse_size(sizestr);
2958 if (new_size == 0) {
2959 ret = -EINVAL;
Chris Mason8f18cf12008-04-25 16:53:30 -04002960 goto out_unlock;
Chris Masonedbd8d42007-12-21 16:27:24 -05002961 }
2962 }
2963
Chris Mason8f18cf12008-04-25 16:53:30 -04002964 old_size = device->total_bytes;
Chris Masonedbd8d42007-12-21 16:27:24 -05002965
2966 if (mod < 0) {
2967 if (new_size > old_size) {
2968 ret = -EINVAL;
2969 goto out_unlock;
2970 }
2971 new_size = old_size - new_size;
2972 } else if (mod > 0) {
2973 new_size = old_size + new_size;
2974 }
2975
2976 if (new_size < 256 * 1024 * 1024) {
2977 ret = -EINVAL;
2978 goto out_unlock;
2979 }
Chris Mason8f18cf12008-04-25 16:53:30 -04002980 if (new_size > device->bdev->bd_inode->i_size) {
Chris Masonedbd8d42007-12-21 16:27:24 -05002981 ret = -EFBIG;
2982 goto out_unlock;
2983 }
Chris Masonf9ef6602008-01-03 09:22:38 -05002984
2985 do_div(new_size, root->sectorsize);
2986 new_size *= root->sectorsize;
Chris Masonedbd8d42007-12-21 16:27:24 -05002987
Chris Mason8f18cf12008-04-25 16:53:30 -04002988printk("new size for %s is %llu\n", device->name, (unsigned long long)new_size);
2989
Chris Masonedbd8d42007-12-21 16:27:24 -05002990 if (new_size > old_size) {
2991 trans = btrfs_start_transaction(root, 1);
Chris Mason8f18cf12008-04-25 16:53:30 -04002992 ret = btrfs_grow_device(trans, device, new_size);
Chris Masonedbd8d42007-12-21 16:27:24 -05002993 btrfs_commit_transaction(trans, root);
2994 } else {
Chris Mason8f18cf12008-04-25 16:53:30 -04002995 ret = btrfs_shrink_device(device, new_size);
Chris Masonedbd8d42007-12-21 16:27:24 -05002996 }
2997
2998out_unlock:
2999 mutex_unlock(&root->fs_info->fs_mutex);
3000out:
3001 kfree(vol_args);
3002 return ret;
3003}
3004
Chris Mason4313b392008-01-03 09:08:48 -05003005static int noinline btrfs_ioctl_snap_create(struct btrfs_root *root,
3006 void __user *arg)
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003007{
Chris Mason4aec2b52007-12-18 16:25:45 -05003008 struct btrfs_ioctl_vol_args *vol_args;
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003009 struct btrfs_dir_item *di;
3010 struct btrfs_path *path;
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003011 u64 root_dirid;
Chris Mason4aec2b52007-12-18 16:25:45 -05003012 int namelen;
3013 int ret;
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003014
Chris Mason4aec2b52007-12-18 16:25:45 -05003015 vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
Chris Mason5f39d392007-10-15 16:14:19 -04003016
Chris Mason4aec2b52007-12-18 16:25:45 -05003017 if (!vol_args)
3018 return -ENOMEM;
3019
3020 if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
3021 ret = -EFAULT;
3022 goto out;
3023 }
3024
3025 namelen = strlen(vol_args->name);
3026 if (namelen > BTRFS_VOL_NAME_MAX) {
3027 ret = -EINVAL;
3028 goto out;
3029 }
3030 if (strchr(vol_args->name, '/')) {
3031 ret = -EINVAL;
3032 goto out;
3033 }
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003034
3035 path = btrfs_alloc_path();
Chris Mason4aec2b52007-12-18 16:25:45 -05003036 if (!path) {
3037 ret = -ENOMEM;
3038 goto out;
3039 }
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003040
3041 root_dirid = root->fs_info->sb->s_root->d_inode->i_ino,
3042 mutex_lock(&root->fs_info->fs_mutex);
3043 di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root,
3044 path, root_dirid,
Chris Mason4aec2b52007-12-18 16:25:45 -05003045 vol_args->name, namelen, 0);
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003046 mutex_unlock(&root->fs_info->fs_mutex);
3047 btrfs_free_path(path);
Chris Mason4aec2b52007-12-18 16:25:45 -05003048
3049 if (di && !IS_ERR(di)) {
3050 ret = -EEXIST;
3051 goto out;
3052 }
3053
3054 if (IS_ERR(di)) {
3055 ret = PTR_ERR(di);
3056 goto out;
3057 }
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003058
3059 if (root == root->fs_info->tree_root)
Chris Mason4aec2b52007-12-18 16:25:45 -05003060 ret = create_subvol(root, vol_args->name, namelen);
3061 else
3062 ret = create_snapshot(root, vol_args->name, namelen);
3063out:
3064 kfree(vol_args);
3065 return ret;
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003066}
3067
3068static int btrfs_ioctl_defrag(struct file *file)
Chris Mason39279cc2007-06-12 06:35:45 -04003069{
Chris Mason6da6aba2007-12-18 16:15:09 -05003070 struct inode *inode = fdentry(file)->d_inode;
Chris Mason39279cc2007-06-12 06:35:45 -04003071 struct btrfs_root *root = BTRFS_I(inode)->root;
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003072
3073 switch (inode->i_mode & S_IFMT) {
3074 case S_IFDIR:
3075 mutex_lock(&root->fs_info->fs_mutex);
3076 btrfs_defrag_root(root, 0);
3077 btrfs_defrag_root(root->fs_info->extent_root, 0);
3078 mutex_unlock(&root->fs_info->fs_mutex);
3079 break;
3080 case S_IFREG:
3081 btrfs_defrag_file(file);
3082 break;
3083 }
3084
3085 return 0;
3086}
3087
Chris Mason788f20e2008-04-28 15:29:42 -04003088long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
3089{
3090 struct btrfs_ioctl_vol_args *vol_args;
3091 int ret;
3092
3093 vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
3094
3095 if (!vol_args)
3096 return -ENOMEM;
3097
3098 if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
3099 ret = -EFAULT;
3100 goto out;
3101 }
3102 ret = btrfs_init_new_device(root, vol_args->name);
3103
3104out:
3105 kfree(vol_args);
3106 return ret;
3107}
3108
Chris Masona061fc82008-05-07 11:43:44 -04003109long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
3110{
3111 struct btrfs_ioctl_vol_args *vol_args;
3112 int ret;
3113
3114 vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
3115
3116 if (!vol_args)
3117 return -ENOMEM;
3118
3119 if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
3120 ret = -EFAULT;
3121 goto out;
3122 }
3123 ret = btrfs_rm_device(root, vol_args->name);
3124
3125out:
3126 kfree(vol_args);
3127 return ret;
3128}
3129
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003130int dup_item_to_inode(struct btrfs_trans_handle *trans,
Sage Weilf2eb0a22008-05-02 14:43:14 -04003131 struct btrfs_root *root,
3132 struct btrfs_path *path,
3133 struct extent_buffer *leaf,
3134 int slot,
3135 struct btrfs_key *key,
3136 u64 destino)
3137{
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003138 char *dup;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003139 int len = btrfs_item_size_nr(leaf, slot);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003140 struct btrfs_key ckey = *key;
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003141 int ret = 0;
3142
3143 dup = kmalloc(len, GFP_NOFS);
3144 if (!dup)
3145 return -ENOMEM;
3146
3147 read_extent_buffer(leaf, dup, btrfs_item_ptr_offset(leaf, slot), len);
3148 btrfs_release_path(root, path);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003149
3150 ckey.objectid = destino;
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003151 ret = btrfs_insert_item(trans, root, &ckey, dup, len);
3152 kfree(dup);
3153 return ret;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003154}
3155
3156long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
3157{
3158 struct inode *inode = fdentry(file)->d_inode;
3159 struct btrfs_root *root = BTRFS_I(inode)->root;
3160 struct file *src_file;
3161 struct inode *src;
3162 struct btrfs_trans_handle *trans;
3163 int ret;
3164 u64 pos;
3165 struct btrfs_path *path;
3166 struct btrfs_key key;
3167 struct extent_buffer *leaf;
3168 u32 nritems;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003169 int slot;
3170
3171 src_file = fget(src_fd);
3172 if (!src_file)
3173 return -EBADF;
3174 src = src_file->f_dentry->d_inode;
3175
3176 ret = -EXDEV;
3177 if (src->i_sb != inode->i_sb)
3178 goto out_fput;
3179
3180 if (inode < src) {
3181 mutex_lock(&inode->i_mutex);
3182 mutex_lock(&src->i_mutex);
3183 } else {
3184 mutex_lock(&src->i_mutex);
3185 mutex_lock(&inode->i_mutex);
3186 }
3187
3188 ret = -ENOTEMPTY;
3189 if (inode->i_size)
3190 goto out_unlock;
3191
3192 /* do any pending delalloc/csum calc on src, one way or
3193 another, and lock file content */
3194 while (1) {
3195 filemap_write_and_wait(src->i_mapping);
3196 lock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
3197 if (BTRFS_I(src)->delalloc_bytes == 0)
3198 break;
3199 unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
3200 }
3201
3202 mutex_lock(&root->fs_info->fs_mutex);
3203 trans = btrfs_start_transaction(root, 0);
3204 path = btrfs_alloc_path();
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003205 if (!path) {
3206 ret = -ENOMEM;
3207 goto out;
3208 }
3209 key.offset = 0;
3210 key.type = BTRFS_EXTENT_DATA_KEY;
3211 key.objectid = src->i_ino;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003212 pos = 0;
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003213 path->reada = 2;
3214
Sage Weilf2eb0a22008-05-02 14:43:14 -04003215 while (1) {
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003216 /*
3217 * note the key will change type as we walk through the
3218 * tree.
3219 */
3220 ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003221 if (ret < 0)
3222 goto out;
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003223
3224 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
3225 ret = btrfs_next_leaf(root, path);
3226 if (ret < 0)
Sage Weilf2eb0a22008-05-02 14:43:14 -04003227 goto out;
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003228 if (ret > 0)
3229 break;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003230 }
Sage Weilf2eb0a22008-05-02 14:43:14 -04003231 leaf = path->nodes[0];
3232 slot = path->slots[0];
3233 btrfs_item_key_to_cpu(leaf, &key, slot);
3234 nritems = btrfs_header_nritems(leaf);
3235
3236 if (btrfs_key_type(&key) > BTRFS_CSUM_ITEM_KEY ||
3237 key.objectid != src->i_ino)
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003238 break;
3239
Sage Weilf2eb0a22008-05-02 14:43:14 -04003240 if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
3241 struct btrfs_file_extent_item *extent;
3242 int found_type;
3243 pos = key.offset;
3244 extent = btrfs_item_ptr(leaf, slot,
3245 struct btrfs_file_extent_item);
3246 found_type = btrfs_file_extent_type(leaf, extent);
3247 if (found_type == BTRFS_FILE_EXTENT_REG) {
3248 u64 len = btrfs_file_extent_num_bytes(leaf,
3249 extent);
3250 u64 ds = btrfs_file_extent_disk_bytenr(leaf,
3251 extent);
3252 u64 dl = btrfs_file_extent_disk_num_bytes(leaf,
3253 extent);
3254 u64 off = btrfs_file_extent_offset(leaf,
3255 extent);
3256 btrfs_insert_file_extent(trans, root,
3257 inode->i_ino, pos,
3258 ds, dl, len, off);
3259 /* ds == 0 means there's a hole */
3260 if (ds != 0) {
3261 btrfs_inc_extent_ref(trans, root,
3262 ds, dl,
3263 root->root_key.objectid,
3264 trans->transid,
3265 inode->i_ino, pos);
3266 }
3267 pos = key.offset + len;
3268 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003269 ret = dup_item_to_inode(trans, root, path,
3270 leaf, slot, &key,
3271 inode->i_ino);
3272 if (ret)
3273 goto out;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003274 pos = key.offset + btrfs_item_size_nr(leaf,
3275 slot);
3276 }
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003277 } else if (btrfs_key_type(&key) == BTRFS_CSUM_ITEM_KEY) {
3278 ret = dup_item_to_inode(trans, root, path, leaf,
3279 slot, &key, inode->i_ino);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003280
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003281 if (ret)
Sage Weilf2eb0a22008-05-02 14:43:14 -04003282 goto out;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003283 }
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003284 key.offset++;
3285 btrfs_release_path(root, path);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003286 }
3287
Chris Mason5d9cd9e2008-05-05 06:26:21 -04003288 ret = 0;
Sage Weilf2eb0a22008-05-02 14:43:14 -04003289out:
3290 btrfs_free_path(path);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003291
3292 inode->i_blocks = src->i_blocks;
3293 i_size_write(inode, src->i_size);
3294 btrfs_update_inode(trans, root, inode);
3295
3296 unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
3297
3298 btrfs_end_transaction(trans, root);
3299 mutex_unlock(&root->fs_info->fs_mutex);
3300
3301out_unlock:
3302 mutex_unlock(&src->i_mutex);
3303 mutex_unlock(&inode->i_mutex);
3304out_fput:
3305 fput(src_file);
3306 return ret;
3307}
3308
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003309long btrfs_ioctl(struct file *file, unsigned int
3310 cmd, unsigned long arg)
3311{
Chris Mason6da6aba2007-12-18 16:15:09 -05003312 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
Chris Mason39279cc2007-06-12 06:35:45 -04003313
3314 switch (cmd) {
3315 case BTRFS_IOC_SNAP_CREATE:
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003316 return btrfs_ioctl_snap_create(root, (void __user *)arg);
Chris Mason6702ed42007-08-07 16:15:09 -04003317 case BTRFS_IOC_DEFRAG:
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003318 return btrfs_ioctl_defrag(file);
Chris Masonedbd8d42007-12-21 16:27:24 -05003319 case BTRFS_IOC_RESIZE:
3320 return btrfs_ioctl_resize(root, (void __user *)arg);
Chris Mason788f20e2008-04-28 15:29:42 -04003321 case BTRFS_IOC_ADD_DEV:
3322 return btrfs_ioctl_add_dev(root, (void __user *)arg);
Chris Masona061fc82008-05-07 11:43:44 -04003323 case BTRFS_IOC_RM_DEV:
3324 return btrfs_ioctl_rm_dev(root, (void __user *)arg);
Chris Masonec44a352008-04-28 15:29:52 -04003325 case BTRFS_IOC_BALANCE:
3326 return btrfs_balance(root->fs_info->dev_root);
Sage Weilf2eb0a22008-05-02 14:43:14 -04003327 case BTRFS_IOC_CLONE:
3328 return btrfs_ioctl_clone(file, arg);
Chris Mason39279cc2007-06-12 06:35:45 -04003329 }
Christoph Hellwigd03581f2007-09-14 10:22:57 -04003330
3331 return -ENOTTY;
Chris Mason39279cc2007-06-12 06:35:45 -04003332}
3333
Chris Mason39279cc2007-06-12 06:35:45 -04003334/*
3335 * Called inside transaction, so use GFP_NOFS
3336 */
3337struct inode *btrfs_alloc_inode(struct super_block *sb)
3338{
3339 struct btrfs_inode *ei;
3340
3341 ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_NOFS);
3342 if (!ei)
3343 return NULL;
Josef Bacik15ee9bc2007-08-10 16:22:09 -04003344 ei->last_trans = 0;
Chris Masondc17ff82008-01-08 15:46:30 -05003345 ei->ordered_trans = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04003346 return &ei->vfs_inode;
3347}
3348
3349void btrfs_destroy_inode(struct inode *inode)
3350{
3351 WARN_ON(!list_empty(&inode->i_dentry));
3352 WARN_ON(inode->i_data.nrpages);
3353
Chris Mason8c416c92008-01-14 15:10:26 -05003354 btrfs_drop_extent_cache(inode, 0, (u64)-1);
Chris Mason39279cc2007-06-12 06:35:45 -04003355 kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
3356}
3357
Chris Mason44ec0b72007-10-29 10:55:05 -04003358#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
3359static void init_once(struct kmem_cache * cachep, void *foo)
3360#else
Chris Mason39279cc2007-06-12 06:35:45 -04003361static void init_once(void * foo, struct kmem_cache * cachep,
3362 unsigned long flags)
Chris Mason44ec0b72007-10-29 10:55:05 -04003363#endif
Chris Mason39279cc2007-06-12 06:35:45 -04003364{
3365 struct btrfs_inode *ei = (struct btrfs_inode *) foo;
3366
3367 inode_init_once(&ei->vfs_inode);
3368}
3369
3370void btrfs_destroy_cachep(void)
3371{
3372 if (btrfs_inode_cachep)
3373 kmem_cache_destroy(btrfs_inode_cachep);
3374 if (btrfs_trans_handle_cachep)
3375 kmem_cache_destroy(btrfs_trans_handle_cachep);
3376 if (btrfs_transaction_cachep)
3377 kmem_cache_destroy(btrfs_transaction_cachep);
3378 if (btrfs_bit_radix_cachep)
3379 kmem_cache_destroy(btrfs_bit_radix_cachep);
3380 if (btrfs_path_cachep)
3381 kmem_cache_destroy(btrfs_path_cachep);
3382}
3383
Chris Mason86479a02007-09-10 19:58:16 -04003384struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
Chris Mason92fee662007-07-25 12:31:35 -04003385 unsigned long extra_flags,
Chris Mason44ec0b72007-10-29 10:55:05 -04003386#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
3387 void (*ctor)(struct kmem_cache *, void *)
3388#else
Chris Mason92fee662007-07-25 12:31:35 -04003389 void (*ctor)(void *, struct kmem_cache *,
Chris Mason44ec0b72007-10-29 10:55:05 -04003390 unsigned long)
3391#endif
3392 )
Chris Mason92fee662007-07-25 12:31:35 -04003393{
3394 return kmem_cache_create(name, size, 0, (SLAB_RECLAIM_ACCOUNT |
3395 SLAB_MEM_SPREAD | extra_flags), ctor
3396#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
3397 ,NULL
3398#endif
3399 );
3400}
3401
Chris Mason39279cc2007-06-12 06:35:45 -04003402int btrfs_init_cachep(void)
3403{
Chris Mason86479a02007-09-10 19:58:16 -04003404 btrfs_inode_cachep = btrfs_cache_create("btrfs_inode_cache",
Chris Mason92fee662007-07-25 12:31:35 -04003405 sizeof(struct btrfs_inode),
3406 0, init_once);
Chris Mason39279cc2007-06-12 06:35:45 -04003407 if (!btrfs_inode_cachep)
3408 goto fail;
Chris Mason86479a02007-09-10 19:58:16 -04003409 btrfs_trans_handle_cachep =
3410 btrfs_cache_create("btrfs_trans_handle_cache",
3411 sizeof(struct btrfs_trans_handle),
3412 0, NULL);
Chris Mason39279cc2007-06-12 06:35:45 -04003413 if (!btrfs_trans_handle_cachep)
3414 goto fail;
Chris Mason86479a02007-09-10 19:58:16 -04003415 btrfs_transaction_cachep = btrfs_cache_create("btrfs_transaction_cache",
Chris Mason39279cc2007-06-12 06:35:45 -04003416 sizeof(struct btrfs_transaction),
Chris Mason92fee662007-07-25 12:31:35 -04003417 0, NULL);
Chris Mason39279cc2007-06-12 06:35:45 -04003418 if (!btrfs_transaction_cachep)
3419 goto fail;
Chris Mason86479a02007-09-10 19:58:16 -04003420 btrfs_path_cachep = btrfs_cache_create("btrfs_path_cache",
Yan23223582007-09-17 11:08:52 -04003421 sizeof(struct btrfs_path),
Chris Mason92fee662007-07-25 12:31:35 -04003422 0, NULL);
Chris Mason39279cc2007-06-12 06:35:45 -04003423 if (!btrfs_path_cachep)
3424 goto fail;
Chris Mason86479a02007-09-10 19:58:16 -04003425 btrfs_bit_radix_cachep = btrfs_cache_create("btrfs_radix", 256,
Chris Mason92fee662007-07-25 12:31:35 -04003426 SLAB_DESTROY_BY_RCU, NULL);
Chris Mason39279cc2007-06-12 06:35:45 -04003427 if (!btrfs_bit_radix_cachep)
3428 goto fail;
3429 return 0;
3430fail:
3431 btrfs_destroy_cachep();
3432 return -ENOMEM;
3433}
3434
3435static int btrfs_getattr(struct vfsmount *mnt,
3436 struct dentry *dentry, struct kstat *stat)
3437{
3438 struct inode *inode = dentry->d_inode;
3439 generic_fillattr(inode, stat);
Chris Masond6667462008-01-03 14:51:00 -05003440 stat->blksize = PAGE_CACHE_SIZE;
Chris Mason90692182008-02-08 13:49:28 -05003441 stat->blocks = inode->i_blocks + (BTRFS_I(inode)->delalloc_bytes >> 9);
Chris Mason39279cc2007-06-12 06:35:45 -04003442 return 0;
3443}
3444
3445static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
3446 struct inode * new_dir,struct dentry *new_dentry)
3447{
3448 struct btrfs_trans_handle *trans;
3449 struct btrfs_root *root = BTRFS_I(old_dir)->root;
3450 struct inode *new_inode = new_dentry->d_inode;
3451 struct inode *old_inode = old_dentry->d_inode;
3452 struct timespec ctime = CURRENT_TIME;
3453 struct btrfs_path *path;
Chris Mason39279cc2007-06-12 06:35:45 -04003454 int ret;
3455
3456 if (S_ISDIR(old_inode->i_mode) && new_inode &&
3457 new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) {
3458 return -ENOTEMPTY;
3459 }
Chris Mason5f39d392007-10-15 16:14:19 -04003460
Chris Mason39279cc2007-06-12 06:35:45 -04003461 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05003462 ret = btrfs_check_free_space(root, 1, 0);
3463 if (ret)
3464 goto out_unlock;
3465
Chris Mason39279cc2007-06-12 06:35:45 -04003466 trans = btrfs_start_transaction(root, 1);
Chris Mason5f39d392007-10-15 16:14:19 -04003467
Chris Mason39279cc2007-06-12 06:35:45 -04003468 btrfs_set_trans_block_group(trans, new_dir);
3469 path = btrfs_alloc_path();
3470 if (!path) {
3471 ret = -ENOMEM;
3472 goto out_fail;
3473 }
3474
3475 old_dentry->d_inode->i_nlink++;
3476 old_dir->i_ctime = old_dir->i_mtime = ctime;
3477 new_dir->i_ctime = new_dir->i_mtime = ctime;
3478 old_inode->i_ctime = ctime;
Chris Mason5f39d392007-10-15 16:14:19 -04003479
Chris Mason39279cc2007-06-12 06:35:45 -04003480 ret = btrfs_unlink_trans(trans, root, old_dir, old_dentry);
3481 if (ret)
3482 goto out_fail;
3483
3484 if (new_inode) {
3485 new_inode->i_ctime = CURRENT_TIME;
3486 ret = btrfs_unlink_trans(trans, root, new_dir, new_dentry);
3487 if (ret)
3488 goto out_fail;
Chris Mason39279cc2007-06-12 06:35:45 -04003489 }
Chris Mason9c583092008-01-29 15:15:18 -05003490 ret = btrfs_add_link(trans, new_dentry, old_inode, 1);
Chris Mason39279cc2007-06-12 06:35:45 -04003491 if (ret)
3492 goto out_fail;
3493
3494out_fail:
3495 btrfs_free_path(path);
3496 btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -05003497out_unlock:
Chris Mason39279cc2007-06-12 06:35:45 -04003498 mutex_unlock(&root->fs_info->fs_mutex);
3499 return ret;
3500}
3501
3502static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
3503 const char *symname)
3504{
3505 struct btrfs_trans_handle *trans;
3506 struct btrfs_root *root = BTRFS_I(dir)->root;
3507 struct btrfs_path *path;
3508 struct btrfs_key key;
Chris Mason1832a6d2007-12-21 16:27:21 -05003509 struct inode *inode = NULL;
Chris Mason39279cc2007-06-12 06:35:45 -04003510 int err;
3511 int drop_inode = 0;
3512 u64 objectid;
3513 int name_len;
3514 int datasize;
Chris Mason5f39d392007-10-15 16:14:19 -04003515 unsigned long ptr;
Chris Mason39279cc2007-06-12 06:35:45 -04003516 struct btrfs_file_extent_item *ei;
Chris Mason5f39d392007-10-15 16:14:19 -04003517 struct extent_buffer *leaf;
Chris Mason1832a6d2007-12-21 16:27:21 -05003518 unsigned long nr = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04003519
3520 name_len = strlen(symname) + 1;
3521 if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
3522 return -ENAMETOOLONG;
Chris Mason1832a6d2007-12-21 16:27:21 -05003523
Chris Mason39279cc2007-06-12 06:35:45 -04003524 mutex_lock(&root->fs_info->fs_mutex);
Chris Mason1832a6d2007-12-21 16:27:21 -05003525 err = btrfs_check_free_space(root, 1, 0);
3526 if (err)
3527 goto out_fail;
3528
Chris Mason39279cc2007-06-12 06:35:45 -04003529 trans = btrfs_start_transaction(root, 1);
3530 btrfs_set_trans_block_group(trans, dir);
3531
3532 err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
3533 if (err) {
3534 err = -ENOSPC;
3535 goto out_unlock;
3536 }
3537
Chris Mason9c583092008-01-29 15:15:18 -05003538 inode = btrfs_new_inode(trans, root, dentry->d_name.name,
3539 dentry->d_name.len,
3540 dentry->d_parent->d_inode->i_ino, objectid,
Chris Mason39279cc2007-06-12 06:35:45 -04003541 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO);
3542 err = PTR_ERR(inode);
3543 if (IS_ERR(inode))
3544 goto out_unlock;
3545
3546 btrfs_set_trans_block_group(trans, inode);
Chris Mason9c583092008-01-29 15:15:18 -05003547 err = btrfs_add_nondir(trans, dentry, inode, 0);
Chris Mason39279cc2007-06-12 06:35:45 -04003548 if (err)
3549 drop_inode = 1;
3550 else {
3551 inode->i_mapping->a_ops = &btrfs_aops;
Chris Mason04160082008-03-26 10:28:07 -04003552 inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
Chris Mason39279cc2007-06-12 06:35:45 -04003553 inode->i_fop = &btrfs_file_operations;
3554 inode->i_op = &btrfs_file_inode_operations;
Chris Masond1310b22008-01-24 16:13:08 -05003555 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
3556 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
Chris Masona52d9a82007-08-27 16:49:44 -04003557 inode->i_mapping, GFP_NOFS);
Chris Mason7e383262008-04-09 16:28:12 -04003558 extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree,
3559 inode->i_mapping, GFP_NOFS);
Chris Mason90692182008-02-08 13:49:28 -05003560 BTRFS_I(inode)->delalloc_bytes = 0;
Chris Mason81d7ed22008-04-25 08:51:48 -04003561 atomic_set(&BTRFS_I(inode)->ordered_writeback, 0);
Chris Masond1310b22008-01-24 16:13:08 -05003562 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
Chris Mason39279cc2007-06-12 06:35:45 -04003563 }
3564 dir->i_sb->s_dirt = 1;
3565 btrfs_update_inode_block_group(trans, inode);
3566 btrfs_update_inode_block_group(trans, dir);
3567 if (drop_inode)
3568 goto out_unlock;
3569
3570 path = btrfs_alloc_path();
3571 BUG_ON(!path);
3572 key.objectid = inode->i_ino;
3573 key.offset = 0;
Chris Mason39279cc2007-06-12 06:35:45 -04003574 btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
3575 datasize = btrfs_file_extent_calc_inline_size(name_len);
3576 err = btrfs_insert_empty_item(trans, root, path, &key,
3577 datasize);
Chris Mason54aa1f42007-06-22 14:16:25 -04003578 if (err) {
3579 drop_inode = 1;
3580 goto out_unlock;
3581 }
Chris Mason5f39d392007-10-15 16:14:19 -04003582 leaf = path->nodes[0];
3583 ei = btrfs_item_ptr(leaf, path->slots[0],
3584 struct btrfs_file_extent_item);
3585 btrfs_set_file_extent_generation(leaf, ei, trans->transid);
3586 btrfs_set_file_extent_type(leaf, ei,
Chris Mason39279cc2007-06-12 06:35:45 -04003587 BTRFS_FILE_EXTENT_INLINE);
3588 ptr = btrfs_file_extent_inline_start(ei);
Chris Mason5f39d392007-10-15 16:14:19 -04003589 write_extent_buffer(leaf, symname, ptr, name_len);
3590 btrfs_mark_buffer_dirty(leaf);
Chris Mason39279cc2007-06-12 06:35:45 -04003591 btrfs_free_path(path);
Chris Mason5f39d392007-10-15 16:14:19 -04003592
Chris Mason39279cc2007-06-12 06:35:45 -04003593 inode->i_op = &btrfs_symlink_inode_operations;
3594 inode->i_mapping->a_ops = &btrfs_symlink_aops;
Chris Mason04160082008-03-26 10:28:07 -04003595 inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
Chris Mason39279cc2007-06-12 06:35:45 -04003596 inode->i_size = name_len - 1;
Chris Mason54aa1f42007-06-22 14:16:25 -04003597 err = btrfs_update_inode(trans, root, inode);
3598 if (err)
3599 drop_inode = 1;
Chris Mason39279cc2007-06-12 06:35:45 -04003600
3601out_unlock:
Chris Masond3c2fdcf2007-09-17 10:58:06 -04003602 nr = trans->blocks_used;
Chris Mason39279cc2007-06-12 06:35:45 -04003603 btrfs_end_transaction(trans, root);
Chris Mason1832a6d2007-12-21 16:27:21 -05003604out_fail:
Chris Mason39279cc2007-06-12 06:35:45 -04003605 mutex_unlock(&root->fs_info->fs_mutex);
Chris Mason39279cc2007-06-12 06:35:45 -04003606 if (drop_inode) {
3607 inode_dec_link_count(inode);
3608 iput(inode);
3609 }
Chris Masond3c2fdcf2007-09-17 10:58:06 -04003610 btrfs_btree_balance_dirty(root, nr);
Chris Masone2008b62008-01-08 15:46:30 -05003611 btrfs_throttle(root);
Chris Mason39279cc2007-06-12 06:35:45 -04003612 return err;
3613}
Chris Mason16432982008-04-10 10:23:21 -04003614
Yanfdebe2b2008-01-14 13:26:08 -05003615static int btrfs_permission(struct inode *inode, int mask,
3616 struct nameidata *nd)
3617{
3618 if (btrfs_test_flag(inode, READONLY) && (mask & MAY_WRITE))
3619 return -EACCES;
3620 return generic_permission(inode, mask, NULL);
3621}
Chris Mason39279cc2007-06-12 06:35:45 -04003622
3623static struct inode_operations btrfs_dir_inode_operations = {
3624 .lookup = btrfs_lookup,
3625 .create = btrfs_create,
3626 .unlink = btrfs_unlink,
3627 .link = btrfs_link,
3628 .mkdir = btrfs_mkdir,
3629 .rmdir = btrfs_rmdir,
3630 .rename = btrfs_rename,
3631 .symlink = btrfs_symlink,
3632 .setattr = btrfs_setattr,
Josef Bacik618e21d2007-07-11 10:18:17 -04003633 .mknod = btrfs_mknod,
Josef Bacik5103e942007-11-16 11:45:54 -05003634 .setxattr = generic_setxattr,
3635 .getxattr = generic_getxattr,
3636 .listxattr = btrfs_listxattr,
3637 .removexattr = generic_removexattr,
Yanfdebe2b2008-01-14 13:26:08 -05003638 .permission = btrfs_permission,
Chris Mason39279cc2007-06-12 06:35:45 -04003639};
Chris Mason39279cc2007-06-12 06:35:45 -04003640static struct inode_operations btrfs_dir_ro_inode_operations = {
3641 .lookup = btrfs_lookup,
Yanfdebe2b2008-01-14 13:26:08 -05003642 .permission = btrfs_permission,
Chris Mason39279cc2007-06-12 06:35:45 -04003643};
Chris Mason39279cc2007-06-12 06:35:45 -04003644static struct file_operations btrfs_dir_file_operations = {
3645 .llseek = generic_file_llseek,
3646 .read = generic_read_dir,
3647 .readdir = btrfs_readdir,
Christoph Hellwig34287aa2007-09-14 10:22:47 -04003648 .unlocked_ioctl = btrfs_ioctl,
Chris Mason39279cc2007-06-12 06:35:45 -04003649#ifdef CONFIG_COMPAT
Christoph Hellwig34287aa2007-09-14 10:22:47 -04003650 .compat_ioctl = btrfs_ioctl,
Chris Mason39279cc2007-06-12 06:35:45 -04003651#endif
3652};
3653
Chris Masond1310b22008-01-24 16:13:08 -05003654static struct extent_io_ops btrfs_extent_io_ops = {
Chris Mason07157aa2007-08-30 08:50:51 -04003655 .fill_delalloc = run_delalloc_range,
Chris Mason065631f2008-02-20 12:07:25 -05003656 .submit_bio_hook = btrfs_submit_bio_hook,
Chris Mason239b14b2008-03-24 15:02:07 -04003657 .merge_bio_hook = btrfs_merge_bio_hook,
Chris Mason07157aa2007-08-30 08:50:51 -04003658 .readpage_io_hook = btrfs_readpage_io_hook,
3659 .readpage_end_io_hook = btrfs_readpage_end_io_hook,
Chris Mason7e383262008-04-09 16:28:12 -04003660 .readpage_io_failed_hook = btrfs_readpage_io_failed_hook,
Chris Masonb0c68f82008-01-31 11:05:37 -05003661 .set_bit_hook = btrfs_set_bit_hook,
3662 .clear_bit_hook = btrfs_clear_bit_hook,
Chris Mason07157aa2007-08-30 08:50:51 -04003663};
3664
Chris Mason39279cc2007-06-12 06:35:45 -04003665static struct address_space_operations btrfs_aops = {
3666 .readpage = btrfs_readpage,
3667 .writepage = btrfs_writepage,
Chris Masonb293f02e2007-11-01 19:45:34 -04003668 .writepages = btrfs_writepages,
Chris Mason3ab2fb52007-11-08 10:59:22 -05003669 .readpages = btrfs_readpages,
Chris Mason39279cc2007-06-12 06:35:45 -04003670 .sync_page = block_sync_page,
Chris Mason39279cc2007-06-12 06:35:45 -04003671 .bmap = btrfs_bmap,
Chris Mason16432982008-04-10 10:23:21 -04003672 .direct_IO = btrfs_direct_IO,
Chris Masona52d9a82007-08-27 16:49:44 -04003673 .invalidatepage = btrfs_invalidatepage,
3674 .releasepage = btrfs_releasepage,
3675 .set_page_dirty = __set_page_dirty_nobuffers,
Chris Mason39279cc2007-06-12 06:35:45 -04003676};
3677
3678static struct address_space_operations btrfs_symlink_aops = {
3679 .readpage = btrfs_readpage,
3680 .writepage = btrfs_writepage,
Chris Mason2bf5a722007-08-30 11:54:02 -04003681 .invalidatepage = btrfs_invalidatepage,
3682 .releasepage = btrfs_releasepage,
Chris Mason39279cc2007-06-12 06:35:45 -04003683};
3684
3685static struct inode_operations btrfs_file_inode_operations = {
3686 .truncate = btrfs_truncate,
3687 .getattr = btrfs_getattr,
3688 .setattr = btrfs_setattr,
Josef Bacik5103e942007-11-16 11:45:54 -05003689 .setxattr = generic_setxattr,
3690 .getxattr = generic_getxattr,
3691 .listxattr = btrfs_listxattr,
3692 .removexattr = generic_removexattr,
Yanfdebe2b2008-01-14 13:26:08 -05003693 .permission = btrfs_permission,
Chris Mason39279cc2007-06-12 06:35:45 -04003694};
Josef Bacik618e21d2007-07-11 10:18:17 -04003695static struct inode_operations btrfs_special_inode_operations = {
3696 .getattr = btrfs_getattr,
3697 .setattr = btrfs_setattr,
Yanfdebe2b2008-01-14 13:26:08 -05003698 .permission = btrfs_permission,
Josef Bacik618e21d2007-07-11 10:18:17 -04003699};
Chris Mason39279cc2007-06-12 06:35:45 -04003700static struct inode_operations btrfs_symlink_inode_operations = {
3701 .readlink = generic_readlink,
3702 .follow_link = page_follow_link_light,
3703 .put_link = page_put_link,
Yanfdebe2b2008-01-14 13:26:08 -05003704 .permission = btrfs_permission,
Chris Mason39279cc2007-06-12 06:35:45 -04003705};