diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 79 |
1 files changed, 15 insertions, 64 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6d6e1ac0a9a0..10cece11dbd8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2250,13 +2250,10 @@ fail_commit: | |||
2250 | 2250 | ||
2251 | static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | 2251 | static int create_snapshot(struct btrfs_root *root, char *name, int namelen) |
2252 | { | 2252 | { |
2253 | struct btrfs_pending_snapshot *pending_snapshot; | ||
2253 | struct btrfs_trans_handle *trans; | 2254 | struct btrfs_trans_handle *trans; |
2254 | struct btrfs_key key; | ||
2255 | struct btrfs_root_item new_root_item; | ||
2256 | struct extent_buffer *tmp; | ||
2257 | int ret; | 2255 | int ret; |
2258 | int err; | 2256 | int err; |
2259 | u64 objectid; | ||
2260 | unsigned long nr = 0; | 2257 | unsigned long nr = 0; |
2261 | 2258 | ||
2262 | if (!root->ref_cows) | 2259 | if (!root->ref_cows) |
@@ -2267,72 +2264,26 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2267 | if (ret) | 2264 | if (ret) |
2268 | goto fail_unlock; | 2265 | goto fail_unlock; |
2269 | 2266 | ||
2267 | pending_snapshot = kmalloc(sizeof(*pending_snapshot), GFP_NOFS); | ||
2268 | if (!pending_snapshot) { | ||
2269 | ret = -ENOMEM; | ||
2270 | goto fail_unlock; | ||
2271 | } | ||
2272 | pending_snapshot->name = kstrndup(name, namelen, GFP_NOFS); | ||
2273 | if (!pending_snapshot->name) { | ||
2274 | ret = -ENOMEM; | ||
2275 | kfree(pending_snapshot); | ||
2276 | goto fail_unlock; | ||
2277 | } | ||
2270 | trans = btrfs_start_transaction(root, 1); | 2278 | trans = btrfs_start_transaction(root, 1); |
2271 | BUG_ON(!trans); | 2279 | BUG_ON(!trans); |
2272 | err = btrfs_commit_transaction(trans, root); | ||
2273 | |||
2274 | trans = btrfs_start_transaction(root, 1); | ||
2275 | 2280 | ||
2281 | pending_snapshot->root = root; | ||
2282 | list_add(&pending_snapshot->list, | ||
2283 | &trans->transaction->pending_snapshots); | ||
2276 | ret = btrfs_update_inode(trans, root, root->inode); | 2284 | ret = btrfs_update_inode(trans, root, root->inode); |
2277 | if (ret) | ||
2278 | goto fail; | ||
2279 | |||
2280 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | ||
2281 | 0, &objectid); | ||
2282 | if (ret) | ||
2283 | goto fail; memcpy(&new_root_item, &root->root_item, | ||
2284 | sizeof(new_root_item)); | ||
2285 | |||
2286 | key.objectid = objectid; | ||
2287 | key.offset = 1; | ||
2288 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | ||
2289 | |||
2290 | extent_buffer_get(root->node); | ||
2291 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | ||
2292 | free_extent_buffer(tmp); | ||
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 | |||
2301 | btrfs_copy_root(trans, root, root->node, &tmp, objectid); | ||
2302 | |||
2303 | btrfs_set_root_bytenr(&new_root_item, tmp->start); | ||
2304 | btrfs_set_root_level(&new_root_item, btrfs_header_level(tmp)); | ||
2305 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | ||
2306 | &new_root_item); | ||
2307 | printk("new root %Lu node %Lu\n", objectid, tmp->start); | ||
2308 | free_extent_buffer(tmp); | ||
2309 | if (ret) | ||
2310 | goto fail; | ||
2311 | |||
2312 | /* | ||
2313 | * insert the directory item | ||
2314 | */ | ||
2315 | key.offset = (u64)-1; | ||
2316 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | ||
2317 | name, namelen, | ||
2318 | root->fs_info->sb->s_root->d_inode->i_ino, | ||
2319 | &key, BTRFS_FT_DIR); | ||
2320 | |||
2321 | if (ret) | ||
2322 | goto fail; | ||
2323 | |||
2324 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, | ||
2325 | name, namelen, objectid, | ||
2326 | root->fs_info->sb->s_root->d_inode->i_ino); | ||
2327 | |||
2328 | if (ret) | ||
2329 | goto fail; | ||
2330 | fail: | ||
2331 | nr = trans->blocks_used; | ||
2332 | err = btrfs_commit_transaction(trans, root); | 2285 | err = btrfs_commit_transaction(trans, root); |
2333 | 2286 | ||
2334 | if (err && !ret) | ||
2335 | ret = err; | ||
2336 | fail_unlock: | 2287 | fail_unlock: |
2337 | mutex_unlock(&root->fs_info->fs_mutex); | 2288 | mutex_unlock(&root->fs_info->fs_mutex); |
2338 | btrfs_btree_balance_dirty(root, nr); | 2289 | btrfs_btree_balance_dirty(root, nr); |