Skip to contentSkip to conversation

add drop snapshot/subvol ioctl

PATCH New Yan, Zheng 1 participant 1 message Aug 25, 2009 Btrfs file system

lore
Share & tools
lore

Yan, Zheng

author
#0 lore raw

PATCH 4/4 add drop snapshot/subvol ioctl

This patch adds drop snapshot/subvol ioctl that allows dropping non-empty snapshot/subvols. The ioctl code is based on Aaron Straus's patch.

Another change in this patch is add code that finds orphan fs trees.

---

fs/btrfs/ctree.h +1 -0
diff -urp 4/fs/btrfs/ctree.h 5/fs/btrfs/ctree.h
@@ -2125,6 +2125,7 @@ int btrfs_find_last_root(struct btrfs_ro
 int btrfs_search_root(struct btrfs_root *root, u64 search_start,
 		      u64 *found_objectid);
 int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
+int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
 int btrfs_set_root_node(struct btrfs_root_item *item,
 			struct extent_buffer *node);
 /* dir-item.c */
fs/btrfs/disk-io.c +26 -12
diff -urp 4/fs/btrfs/disk-io.c 5/fs/btrfs/disk-io.c
@@ -950,13 +950,14 @@ static int find_and_setup_root(struct bt
 	ret = btrfs_find_last_root(tree_root, objectid,
 				   &root->root_item, &root->root_key);
 	BUG_ON(ret);
+	BUG_ON(btrfs_root_refs(&root->root_item) == 0);
 
 	generation = btrfs_root_generation(&root->root_item);
 	blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
 	root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
 				     blocksize, generation);
-	root->commit_root = btrfs_root_node(root);
 	BUG_ON(!root->node);
+	root->commit_root = btrfs_root_node(root);
 	return 0;
 }
 
@@ -1194,12 +1195,13 @@ struct btrfs_root *btrfs_read_fs_root_no
 		kfree(root);
 		return ERR_PTR(ret);
 	}
-	if (!(fs_info->sb->s_flags & MS_RDONLY)) {
-		ret = btrfs_find_dead_roots(fs_info->tree_root,
-					    root->root_key.objectid);
-		BUG_ON(ret);
+	ret = btrfs_find_dead_roots(fs_info->tree_root,
+				    root->root_key.objectid);
+	BUG_ON(ret);
+
+	if (!(fs_info->sb->s_flags & MS_RDONLY))
 		btrfs_orphan_cleanup(root);
-	}
+
 	return root;
 }
 
@@ -1424,9 +1426,12 @@ static int cleaner_kthread(void *arg)
 			break;
 
 		vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
-		mutex_lock(&root->fs_info->cleaner_mutex);
-		btrfs_clean_old_snapshots(root);
-		mutex_unlock(&root->fs_info->cleaner_mutex);
+
+		if (!(root->fs_info->sb->s_flags & MS_RDONLY)) {
+			mutex_lock(&root->fs_info->cleaner_mutex);
+			btrfs_clean_old_snapshots(root);
+			mutex_unlock(&root->fs_info->cleaner_mutex);
+		}
 
 		if (freezing(current)) {
 			refrigerator();
@@ -1889,6 +1894,9 @@ struct btrfs_root *open_ctree(struct sup
 		}
 	}
 
+	ret = btrfs_find_orphan_roots(tree_root);
+	BUG_ON(ret);
+
 	if (!(sb->s_flags & MS_RDONLY)) {
 		ret = btrfs_recover_relocation(tree_root);
 		BUG_ON(ret);
@@ -2229,6 +2237,15 @@ static int del_fs_roots(struct btrfs_fs_
 	struct btrfs_root *gang[8];
 	int i;
 
+	while (!list_empty(&fs_info->dead_roots)) {
+		gang[0] = list_entry(fs_info->dead_roots.next,
+				     struct btrfs_root, root_list);
+		list_del(&gang[0]->root_list);
+		free_extent_buffer(gang[0]->node);
+		free_extent_buffer(gang[0]->commit_root);
+		kfree(gang[0]);
+	}
+
 	while (1) {
 		ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
 					     (void **)gang, 0,
@@ -2258,9 +2275,6 @@ int btrfs_cleanup_fs_roots(struct btrfs_
 		root_objectid = gang[ret - 1]->root_key.objectid + 1;
 		for (i = 0; i < ret; i++) {
 			root_objectid = gang[i]->root_key.objectid;
-			ret = btrfs_find_dead_roots(fs_info->tree_root,
-						    root_objectid);
-			BUG_ON(ret);
 			btrfs_orphan_cleanup(gang[i]);
 		}
 		root_objectid++;
fs/btrfs/extent-tree.c +11 -0
diff -urp 4/fs/btrfs/extent-tree.c 5/fs/btrfs/extent-tree.c
@@ -5356,6 +5356,17 @@ int btrfs_drop_snapshot(struct btrfs_roo
 	ret = btrfs_del_root(trans, tree_root, &root->root_key);
 	BUG_ON(ret);
 
+	if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
+		ret = btrfs_find_last_root(tree_root, root->root_key.objectid,
+					   NULL, NULL);
+		BUG_ON(ret < 0);
+		if (ret > 0) {
+			ret = btrfs_del_orphan_item(trans, tree_root,
+						    root->root_key.objectid);
+			BUG_ON(ret);
+		}
+	}
+
 	free_extent_buffer(root->node);
 	free_extent_buffer(root->commit_root);
 	kfree(root);
fs/btrfs/inode-map.c +2 -2
diff -urp 4/fs/btrfs/inode-map.c 5/fs/btrfs/inode-map.c
@@ -44,9 +44,9 @@ int btrfs_find_highest_inode(struct btrf
 		l = path->nodes[0];
 		btrfs_item_key_to_cpu(l, &found_key, slot);
 		*objectid = max_t(u64, found_key.objectid,
-				  BTRFS_FIRST_FREE_OBJECTID - 1);
+				  BTRFS_FIRST_FREE_OBJECTID);
 	} else {
-		*objectid = BTRFS_FIRST_FREE_OBJECTID - 1;
+		*objectid = BTRFS_FIRST_FREE_OBJECTID;
 	}
 	ret = 0;
 error:
fs/btrfs/ioctl.c +88 -3

115 lines not on this page · raw message

fs/btrfs/ioctl.h +2 -1
diff -urp 4/fs/btrfs/ioctl.h 5/fs/btrfs/ioctl.h
@@ -65,5 +65,6 @@ struct btrfs_ioctl_clone_range_args {
 
 #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \
 				   struct btrfs_ioctl_vol_args)
-
+#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \
+				struct btrfs_ioctl_vol_args)
 #endif
fs/btrfs/root-tree.c +62 -4

85 lines not on this page · raw message

fs/btrfs/transaction.c +6 -2
diff -urp 4/fs/btrfs/transaction.c 5/fs/btrfs/transaction.c
@@ -1087,8 +1087,12 @@ int btrfs_clean_old_snapshots(struct btr
 
 	while (!list_empty(&list)) {
 		root = list_entry(list.next, struct btrfs_root, root_list);
-		list_del_init(&root->root_list);
-		btrfs_drop_snapshot(root, 0);
+		list_del(&root->root_list);
+		if (btrfs_header_backref_rev(root->node) <
+		    BTRFS_MIXED_BACKREF_REV)
+			btrfs_drop_snapshot(root, 0);
+		else
+			btrfs_drop_snapshot(root, 1);
 	}
 	return 0;
 }