diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-08 15:46:30 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | dc17ff8f11d129db9e83ab7244769e4eae05e14d (patch) | |
tree | 622e70100d6082e371a6ca62b02fd57e0c37f8dc /fs/btrfs/inode.c | |
parent | e4204dedbbaa3a614605cb83cc0ac5161af6b4e6 (diff) |
Btrfs: Add data=ordered support
This forces file data extents down the disk along with the metadata that
references them. The current implementation is fairly simple, and just
writes out all of the dirty pages in an inode before the commit.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6d0cd9a7a615..6d6e1ac0a9a0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -135,6 +135,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
135 | alloc_hint = ins.objectid + ins.offset; | 135 | alloc_hint = ins.objectid + ins.offset; |
136 | start += cur_alloc_size; | 136 | start += cur_alloc_size; |
137 | } | 137 | } |
138 | btrfs_add_ordered_inode(inode); | ||
138 | out: | 139 | out: |
139 | btrfs_end_transaction(trans, root); | 140 | btrfs_end_transaction(trans, root); |
140 | return ret; | 141 | return ret; |
@@ -367,8 +368,8 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
367 | path = btrfs_alloc_path(); | 368 | path = btrfs_alloc_path(); |
368 | BUG_ON(!path); | 369 | BUG_ON(!path); |
369 | mutex_lock(&root->fs_info->fs_mutex); | 370 | mutex_lock(&root->fs_info->fs_mutex); |
370 | |||
371 | memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); | 371 | memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); |
372 | |||
372 | ret = btrfs_lookup_inode(NULL, root, path, &location, 0); | 373 | ret = btrfs_lookup_inode(NULL, root, path, &location, 0); |
373 | if (ret) | 374 | if (ret) |
374 | goto make_bad; | 375 | goto make_bad; |
@@ -898,7 +899,6 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
898 | if ((offset & (blocksize - 1)) == 0) | 899 | if ((offset & (blocksize - 1)) == 0) |
899 | goto out; | 900 | goto out; |
900 | 901 | ||
901 | down_read(&root->snap_sem); | ||
902 | ret = -ENOMEM; | 902 | ret = -ENOMEM; |
903 | page = grab_cache_page(mapping, index); | 903 | page = grab_cache_page(mapping, index); |
904 | if (!page) | 904 | if (!page) |
@@ -917,7 +917,6 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
917 | 917 | ||
918 | unlock_page(page); | 918 | unlock_page(page); |
919 | page_cache_release(page); | 919 | page_cache_release(page); |
920 | up_read(&BTRFS_I(inode)->root->snap_sem); | ||
921 | out: | 920 | out: |
922 | return ret; | 921 | return ret; |
923 | } | 922 | } |
@@ -1146,6 +1145,19 @@ static int btrfs_find_actor(struct inode *inode, void *opaque) | |||
1146 | args->root == BTRFS_I(inode)->root); | 1145 | args->root == BTRFS_I(inode)->root); |
1147 | } | 1146 | } |
1148 | 1147 | ||
1148 | struct inode *btrfs_ilookup(struct super_block *s, u64 objectid, | ||
1149 | u64 root_objectid) | ||
1150 | { | ||
1151 | struct btrfs_iget_args args; | ||
1152 | args.ino = objectid; | ||
1153 | args.root = btrfs_lookup_fs_root(btrfs_sb(s)->fs_info, root_objectid); | ||
1154 | |||
1155 | if (!args.root) | ||
1156 | return NULL; | ||
1157 | |||
1158 | return ilookup5(s, objectid, btrfs_find_actor, (void *)&args); | ||
1159 | } | ||
1160 | |||
1149 | struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid, | 1161 | struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid, |
1150 | struct btrfs_root *root) | 1162 | struct btrfs_root *root) |
1151 | { | 1163 | { |
@@ -1336,7 +1348,6 @@ read_dir_items: | |||
1336 | 1348 | ||
1337 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; | 1349 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; |
1338 | btrfs_dir_item_key_to_cpu(leaf, di, &location); | 1350 | btrfs_dir_item_key_to_cpu(leaf, di, &location); |
1339 | |||
1340 | over = filldir(dirent, name_ptr, name_len, | 1351 | over = filldir(dirent, name_ptr, name_len, |
1341 | found_key.offset, | 1352 | found_key.offset, |
1342 | location.objectid, | 1353 | location.objectid, |
@@ -2054,7 +2065,6 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
2054 | 2065 | ||
2055 | ret = -EINVAL; | 2066 | ret = -EINVAL; |
2056 | 2067 | ||
2057 | down_read(&BTRFS_I(inode)->root->snap_sem); | ||
2058 | lock_page(page); | 2068 | lock_page(page); |
2059 | wait_on_page_writeback(page); | 2069 | wait_on_page_writeback(page); |
2060 | size = i_size_read(inode); | 2070 | size = i_size_read(inode); |
@@ -2075,7 +2085,6 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
2075 | ret = btrfs_cow_one_page(inode, page, end); | 2085 | ret = btrfs_cow_one_page(inode, page, end); |
2076 | 2086 | ||
2077 | out_unlock: | 2087 | out_unlock: |
2078 | up_read(&BTRFS_I(inode)->root->snap_sem); | ||
2079 | unlock_page(page); | 2088 | unlock_page(page); |
2080 | out: | 2089 | out: |
2081 | return ret; | 2090 | return ret; |
@@ -2118,7 +2127,7 @@ static int noinline create_subvol(struct btrfs_root *root, char *name, | |||
2118 | struct btrfs_root_item root_item; | 2127 | struct btrfs_root_item root_item; |
2119 | struct btrfs_inode_item *inode_item; | 2128 | struct btrfs_inode_item *inode_item; |
2120 | struct extent_buffer *leaf; | 2129 | struct extent_buffer *leaf; |
2121 | struct btrfs_root *new_root; | 2130 | struct btrfs_root *new_root = root; |
2122 | struct inode *inode; | 2131 | struct inode *inode; |
2123 | struct inode *dir; | 2132 | struct inode *dir; |
2124 | int ret; | 2133 | int ret; |
@@ -2230,7 +2239,7 @@ static int noinline create_subvol(struct btrfs_root *root, char *name, | |||
2230 | goto fail; | 2239 | goto fail; |
2231 | fail: | 2240 | fail: |
2232 | nr = trans->blocks_used; | 2241 | nr = trans->blocks_used; |
2233 | err = btrfs_commit_transaction(trans, root); | 2242 | err = btrfs_commit_transaction(trans, new_root); |
2234 | if (err && !ret) | 2243 | if (err && !ret) |
2235 | ret = err; | 2244 | ret = err; |
2236 | fail_commit: | 2245 | fail_commit: |
@@ -2253,10 +2262,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2253 | if (!root->ref_cows) | 2262 | if (!root->ref_cows) |
2254 | return -EINVAL; | 2263 | return -EINVAL; |
2255 | 2264 | ||
2256 | down_write(&root->snap_sem); | ||
2257 | freeze_bdev(root->fs_info->sb->s_bdev); | ||
2258 | thaw_bdev(root->fs_info->sb->s_bdev, root->fs_info->sb); | ||
2259 | |||
2260 | mutex_lock(&root->fs_info->fs_mutex); | 2265 | mutex_lock(&root->fs_info->fs_mutex); |
2261 | ret = btrfs_check_free_space(root, 1, 0); | 2266 | ret = btrfs_check_free_space(root, 1, 0); |
2262 | if (ret) | 2267 | if (ret) |
@@ -2264,6 +2269,9 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2264 | 2269 | ||
2265 | trans = btrfs_start_transaction(root, 1); | 2270 | trans = btrfs_start_transaction(root, 1); |
2266 | BUG_ON(!trans); | 2271 | BUG_ON(!trans); |
2272 | err = btrfs_commit_transaction(trans, root); | ||
2273 | |||
2274 | trans = btrfs_start_transaction(root, 1); | ||
2267 | 2275 | ||
2268 | ret = btrfs_update_inode(trans, root, root->inode); | 2276 | ret = btrfs_update_inode(trans, root, root->inode); |
2269 | if (ret) | 2277 | if (ret) |
@@ -2272,9 +2280,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2272 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | 2280 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, |
2273 | 0, &objectid); | 2281 | 0, &objectid); |
2274 | if (ret) | 2282 | if (ret) |
2275 | goto fail; | 2283 | goto fail; memcpy(&new_root_item, &root->root_item, |
2276 | |||
2277 | memcpy(&new_root_item, &root->root_item, | ||
2278 | sizeof(new_root_item)); | 2284 | sizeof(new_root_item)); |
2279 | 2285 | ||
2280 | key.objectid = objectid; | 2286 | key.objectid = objectid; |
@@ -2285,12 +2291,20 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2285 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 2291 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); |
2286 | free_extent_buffer(tmp); | 2292 | free_extent_buffer(tmp); |
2287 | 2293 | ||
2294 | /* write the ordered inodes to force all delayed allocations to | ||
2295 | * be filled. Once this is done, we can copy the root | ||
2296 | */ | ||
2297 | mutex_lock(&root->fs_info->trans_mutex); | ||
2298 | btrfs_write_ordered_inodes(trans, root); | ||
2299 | mutex_unlock(&root->fs_info->trans_mutex); | ||
2300 | |||
2288 | btrfs_copy_root(trans, root, root->node, &tmp, objectid); | 2301 | btrfs_copy_root(trans, root, root->node, &tmp, objectid); |
2289 | 2302 | ||
2290 | btrfs_set_root_bytenr(&new_root_item, tmp->start); | 2303 | btrfs_set_root_bytenr(&new_root_item, tmp->start); |
2291 | btrfs_set_root_level(&new_root_item, btrfs_header_level(tmp)); | 2304 | btrfs_set_root_level(&new_root_item, btrfs_header_level(tmp)); |
2292 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 2305 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
2293 | &new_root_item); | 2306 | &new_root_item); |
2307 | printk("new root %Lu node %Lu\n", objectid, tmp->start); | ||
2294 | free_extent_buffer(tmp); | 2308 | free_extent_buffer(tmp); |
2295 | if (ret) | 2309 | if (ret) |
2296 | goto fail; | 2310 | goto fail; |
@@ -2321,7 +2335,6 @@ fail: | |||
2321 | ret = err; | 2335 | ret = err; |
2322 | fail_unlock: | 2336 | fail_unlock: |
2323 | mutex_unlock(&root->fs_info->fs_mutex); | 2337 | mutex_unlock(&root->fs_info->fs_mutex); |
2324 | up_write(&root->snap_sem); | ||
2325 | btrfs_btree_balance_dirty(root, nr); | 2338 | btrfs_btree_balance_dirty(root, nr); |
2326 | return ret; | 2339 | return ret; |
2327 | } | 2340 | } |
@@ -2608,6 +2621,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
2608 | if (!ei) | 2621 | if (!ei) |
2609 | return NULL; | 2622 | return NULL; |
2610 | ei->last_trans = 0; | 2623 | ei->last_trans = 0; |
2624 | ei->ordered_trans = 0; | ||
2611 | return &ei->vfs_inode; | 2625 | return &ei->vfs_inode; |
2612 | } | 2626 | } |
2613 | 2627 | ||