2007-03-21 18:12:56 +03:00
# include <linux/module.h>
2007-03-20 21:38:32 +03:00
# include "ctree.h"
# include "disk-io.h"
# include "transaction.h"
/*
* walks the btree of allocated inodes and find a hole .
*/
int btrfs_find_free_objectid ( struct btrfs_trans_handle * trans ,
struct btrfs_root * fs_root ,
u64 dirid , u64 * objectid )
{
2007-04-02 22:53:59 +04:00
struct btrfs_path * path ;
2007-03-20 21:38:32 +03:00
struct btrfs_key key ;
int ret ;
u64 hole_size = 0 ;
int slot = 0 ;
2007-03-22 19:13:20 +03:00
u64 last_ino = 0 ;
2007-03-20 21:38:32 +03:00
int start_found ;
struct btrfs_leaf * l ;
struct btrfs_root * root = fs_root - > fs_info - > inode_root ;
struct btrfs_key search_key ;
u64 search_start = dirid ;
2007-04-04 23:27:52 +04:00
path = btrfs_alloc_path ( ) ;
BUG_ON ( ! path ) ;
search_key . flags = 0 ;
btrfs_set_key_type ( & search_key , BTRFS_INODE_MAP_ITEM_KEY ) ;
2007-03-20 21:38:32 +03:00
2007-04-04 23:27:52 +04:00
search_start = fs_root - > fs_info - > last_inode_alloc ;
if ( search_start = = 0 ) {
struct btrfs_disk_key * last_key ;
btrfs_init_path ( path ) ;
search_key . objectid = ( u64 ) - 1 ;
search_key . offset = ( u64 ) - 1 ;
ret = btrfs_search_slot ( trans , root , & search_key , path , 0 , 0 ) ;
if ( ret < 0 )
goto error ;
BUG_ON ( ret = = 0 ) ;
if ( path - > slots [ 0 ] > 0 )
path - > slots [ 0 ] - - ;
l = btrfs_buffer_leaf ( path - > nodes [ 0 ] ) ;
last_key = & l - > items [ path - > slots [ 0 ] ] . key ;
search_start = btrfs_disk_key_objectid ( last_key ) ;
}
2007-03-27 14:33:00 +04:00
search_start = max ( search_start , BTRFS_FIRST_FREE_OBJECTID ) ;
2007-03-20 21:38:32 +03:00
search_key . objectid = search_start ;
search_key . offset = 0 ;
2007-04-02 22:53:59 +04:00
btrfs_init_path ( path ) ;
2007-03-20 21:38:32 +03:00
start_found = 0 ;
2007-04-02 22:53:59 +04:00
ret = btrfs_search_slot ( trans , root , & search_key , path , 0 , 0 ) ;
2007-03-20 21:38:32 +03:00
if ( ret < 0 )
goto error ;
2007-04-02 22:53:59 +04:00
if ( path - > slots [ 0 ] > 0 )
path - > slots [ 0 ] - - ;
2007-03-20 21:38:32 +03:00
while ( 1 ) {
2007-04-02 22:53:59 +04:00
l = btrfs_buffer_leaf ( path - > nodes [ 0 ] ) ;
slot = path - > slots [ 0 ] ;
2007-03-20 21:38:32 +03:00
if ( slot > = btrfs_header_nritems ( & l - > header ) ) {
2007-04-02 22:53:59 +04:00
ret = btrfs_next_leaf ( root , path ) ;
2007-03-20 21:38:32 +03:00
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 ;
2007-04-02 22:53:59 +04:00
path - > slots [ 0 ] + + ;
2007-03-20 21:38:32 +03:00
}
// FIXME -ENOSPC
found :
root - > fs_info - > last_inode_alloc = * objectid ;
2007-04-02 22:53:59 +04:00
btrfs_release_path ( root , path ) ;
btrfs_free_path ( path ) ;
2007-03-20 21:38:32 +03:00
BUG_ON ( * objectid < search_start ) ;
return 0 ;
error :
2007-04-02 22:53:59 +04:00
btrfs_release_path ( root , path ) ;
btrfs_free_path ( path ) ;
2007-03-20 21:38:32 +03:00
return ret ;
}
int btrfs_insert_inode_map ( struct btrfs_trans_handle * trans ,
struct btrfs_root * fs_root ,
u64 objectid , struct btrfs_key * location )
{
int ret = 0 ;
2007-04-02 22:53:59 +04:00
struct btrfs_path * path ;
2007-03-20 21:38:32 +03:00
struct btrfs_inode_map_item * inode_item ;
struct btrfs_key key ;
struct btrfs_root * inode_root = fs_root - > fs_info - > inode_root ;
key . objectid = objectid ;
key . flags = 0 ;
btrfs_set_key_type ( & key , BTRFS_INODE_MAP_ITEM_KEY ) ;
key . offset = 0 ;
2007-04-02 22:53:59 +04:00
path = btrfs_alloc_path ( ) ;
BUG_ON ( ! path ) ;
btrfs_init_path ( path ) ;
ret = btrfs_insert_empty_item ( trans , inode_root , path , & key ,
2007-03-20 21:38:32 +03:00
sizeof ( struct btrfs_inode_map_item ) ) ;
if ( ret )
goto out ;
2007-04-02 22:53:59 +04:00
inode_item = btrfs_item_ptr ( btrfs_buffer_leaf ( path - > nodes [ 0 ] ) ,
path - > slots [ 0 ] , struct btrfs_inode_map_item ) ;
2007-03-20 21:38:32 +03:00
btrfs_cpu_key_to_disk ( & inode_item - > key , location ) ;
2007-04-02 22:53:59 +04:00
btrfs_mark_buffer_dirty ( path - > nodes [ 0 ] ) ;
2007-03-20 21:38:32 +03:00
out :
2007-04-02 22:53:59 +04:00
btrfs_release_path ( inode_root , path ) ;
btrfs_free_path ( path ) ;
2007-03-20 21:38:32 +03:00
return ret ;
}
int btrfs_lookup_inode_map ( struct btrfs_trans_handle * trans ,
struct btrfs_root * fs_root , struct btrfs_path * path ,
u64 objectid , int mod )
{
int ret ;
struct btrfs_key key ;
int ins_len = mod < 0 ? - 1 : 0 ;
int cow = mod ! = 0 ;
struct btrfs_root * inode_root = fs_root - > fs_info - > inode_root ;
key . objectid = objectid ;
key . flags = 0 ;
key . offset = 0 ;
btrfs_set_key_type ( & key , BTRFS_INODE_MAP_ITEM_KEY ) ;
ret = btrfs_search_slot ( trans , inode_root , & key , path , ins_len , cow ) ;
return ret ;
}