inode-map.c 3.2 KB
Newer Older
C
Chris Mason 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

19 20 21 22
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"

C
Chris Mason 已提交
23
int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid)
C
Chris Mason 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
{
	struct btrfs_path *path;
	int ret;
	struct btrfs_leaf *l;
	struct btrfs_key search_key;
	int slot;

	path = btrfs_alloc_path();
	BUG_ON(!path);

	search_key.objectid = (u64)-1;
	search_key.offset = (u64)-1;
	ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
	if (ret < 0)
		goto error;
	BUG_ON(ret == 0);
	if (path->slots[0] > 0) {
		slot = path->slots[0] - 1;
		l = btrfs_buffer_leaf(path->nodes[0]);
		*objectid = btrfs_disk_key_objectid(&l->items[slot].key);
	} else {
		*objectid = BTRFS_FIRST_FREE_OBJECTID;
	}
	ret = 0;
error:
	btrfs_free_path(path);
	return ret;
}

53 54 55 56
/*
 * walks the btree of allocated inodes and find a hole.
 */
int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
C
Chris Mason 已提交
57
			     struct btrfs_root *root,
58 59
			     u64 dirid, u64 *objectid)
{
C
Chris Mason 已提交
60
	struct btrfs_path *path;
61 62 63 64
	struct btrfs_key key;
	int ret;
	u64 hole_size = 0;
	int slot = 0;
C
Chris Mason 已提交
65
	u64 last_ino = 0;
66 67 68 69 70
	int start_found;
	struct btrfs_leaf *l;
	struct btrfs_key search_key;
	u64 search_start = dirid;

71 72 73
	path = btrfs_alloc_path();
	BUG_ON(!path);
	search_key.flags = 0;
C
Chris Mason 已提交
74
	search_start = root->last_inode_alloc;
75
	search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
76 77 78
	search_key.objectid = search_start;
	search_key.offset = 0;

C
Chris Mason 已提交
79
	btrfs_init_path(path);
80
	start_found = 0;
C
Chris Mason 已提交
81
	ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0);
82 83 84
	if (ret < 0)
		goto error;

C
Chris Mason 已提交
85 86
	if (path->slots[0] > 0)
		path->slots[0]--;
87 88

	while (1) {
C
Chris Mason 已提交
89 90
		l = btrfs_buffer_leaf(path->nodes[0]);
		slot = path->slots[0];
91
		if (slot >= btrfs_header_nritems(&l->header)) {
C
Chris Mason 已提交
92
			ret = btrfs_next_leaf(root, path);
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
			if (ret == 0)
				continue;
			if (ret < 0)
				goto error;
			if (!start_found) {
				*objectid = search_start;
				start_found = 1;
				goto found;
			}
			*objectid = last_ino > search_start ?
				last_ino : search_start;
			goto found;
		}
		btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
		if (key.objectid >= search_start) {
			if (start_found) {
				if (last_ino < search_start)
					last_ino = search_start;
				hole_size = key.objectid - last_ino;
				if (hole_size > 0) {
					*objectid = last_ino;
					goto found;
				}
			}
		}
		start_found = 1;
		last_ino = key.objectid + 1;
C
Chris Mason 已提交
120
		path->slots[0]++;
121 122 123
	}
	// FIXME -ENOSPC
found:
C
Chris Mason 已提交
124
	root->last_inode_alloc = *objectid;
C
Chris Mason 已提交
125 126
	btrfs_release_path(root, path);
	btrfs_free_path(path);
127 128 129
	BUG_ON(*objectid < search_start);
	return 0;
error:
C
Chris Mason 已提交
130 131
	btrfs_release_path(root, path);
	btrfs_free_path(path);
132 133
	return ret;
}