Chris Mason | 6cbd557 | 2007-06-12 09:07:21 -0400 | [diff] [blame] | 1 | /* |
| 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 Mason | 9f5fae2 | 2007-03-20 14:38:32 -0400 | [diff] [blame] | 19 | #include "ctree.h" |
| 20 | #include "disk-io.h" |
| 21 | #include "transaction.h" |
| 22 | |
Chris Mason | 1b05da2 | 2007-04-10 12:13:09 -0400 | [diff] [blame] | 23 | int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid) |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 24 | { |
| 25 | struct btrfs_path *path; |
| 26 | int ret; |
Chris Mason | 5f39d39 | 2007-10-15 16:14:19 -0400 | [diff] [blame] | 27 | struct extent_buffer *l; |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 28 | struct btrfs_key search_key; |
Chris Mason | 5f39d39 | 2007-10-15 16:14:19 -0400 | [diff] [blame] | 29 | struct btrfs_key found_key; |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 30 | int slot; |
| 31 | |
| 32 | path = btrfs_alloc_path(); |
Tsutomu Itoh | db5b493 | 2011-03-23 08:14:16 +0000 | [diff] [blame] | 33 | if (!path) |
| 34 | return -ENOMEM; |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 35 | |
Zheng Yan | 6527cdb | 2008-09-05 16:43:53 -0400 | [diff] [blame] | 36 | search_key.objectid = BTRFS_LAST_FREE_OBJECTID; |
| 37 | search_key.type = -1; |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 38 | search_key.offset = (u64)-1; |
| 39 | ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); |
| 40 | if (ret < 0) |
| 41 | goto error; |
| 42 | BUG_ON(ret == 0); |
| 43 | if (path->slots[0] > 0) { |
| 44 | slot = path->slots[0] - 1; |
Chris Mason | 5f39d39 | 2007-10-15 16:14:19 -0400 | [diff] [blame] | 45 | l = path->nodes[0]; |
| 46 | btrfs_item_key_to_cpu(l, &found_key, slot); |
Yan, Zheng | 13a8a7c | 2009-09-21 15:56:00 -0400 | [diff] [blame] | 47 | *objectid = max_t(u64, found_key.objectid, |
| 48 | BTRFS_FIRST_FREE_OBJECTID - 1); |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 49 | } else { |
Yan, Zheng | 13a8a7c | 2009-09-21 15:56:00 -0400 | [diff] [blame] | 50 | *objectid = BTRFS_FIRST_FREE_OBJECTID - 1; |
Chris Mason | 5be6f7f | 2007-04-05 13:35:25 -0400 | [diff] [blame] | 51 | } |
| 52 | ret = 0; |
| 53 | error: |
| 54 | btrfs_free_path(path); |
| 55 | return ret; |
| 56 | } |
| 57 | |
Chris Mason | 9f5fae2 | 2007-03-20 14:38:32 -0400 | [diff] [blame] | 58 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, |
Chris Mason | 1b05da2 | 2007-04-10 12:13:09 -0400 | [diff] [blame] | 59 | struct btrfs_root *root, |
Chris Mason | 9f5fae2 | 2007-03-20 14:38:32 -0400 | [diff] [blame] | 60 | u64 dirid, u64 *objectid) |
| 61 | { |
Chris Mason | 9f5fae2 | 2007-03-20 14:38:32 -0400 | [diff] [blame] | 62 | int ret; |
Chris Mason | a213501 | 2008-06-25 16:01:30 -0400 | [diff] [blame] | 63 | mutex_lock(&root->objectid_mutex); |
Yan, Zheng | 13a8a7c | 2009-09-21 15:56:00 -0400 | [diff] [blame] | 64 | |
| 65 | if (unlikely(root->highest_objectid < BTRFS_FIRST_FREE_OBJECTID)) { |
| 66 | ret = btrfs_find_highest_inode(root, &root->highest_objectid); |
| 67 | if (ret) |
| 68 | goto out; |
Chris Mason | a213501 | 2008-06-25 16:01:30 -0400 | [diff] [blame] | 69 | } |
Chris Mason | b1a4d96 | 2007-04-04 15:27:52 -0400 | [diff] [blame] | 70 | |
Yan, Zheng | 13a8a7c | 2009-09-21 15:56:00 -0400 | [diff] [blame] | 71 | if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) { |
| 72 | ret = -ENOSPC; |
| 73 | goto out; |
Chris Mason | 9f5fae2 | 2007-03-20 14:38:32 -0400 | [diff] [blame] | 74 | } |
Yan, Zheng | 13a8a7c | 2009-09-21 15:56:00 -0400 | [diff] [blame] | 75 | |
| 76 | *objectid = ++root->highest_objectid; |
| 77 | ret = 0; |
| 78 | out: |
Chris Mason | a213501 | 2008-06-25 16:01:30 -0400 | [diff] [blame] | 79 | mutex_unlock(&root->objectid_mutex); |
Chris Mason | 9f5fae2 | 2007-03-20 14:38:32 -0400 | [diff] [blame] | 80 | return ret; |
| 81 | } |