2017-03-17 09:18:50 +03:00
// SPDX-License-Identifier: GPL-2.0
# include "bcachefs.h"
2019-09-23 02:10:21 +03:00
# include "btree_key_cache.h"
2017-03-17 09:18:50 +03:00
# include "bkey_methods.h"
# include "btree_update.h"
# include "error.h"
# include "extents.h"
2021-03-16 07:28:17 +03:00
# include "extent_update.h"
2017-03-17 09:18:50 +03:00
# include "inode.h"
2019-10-04 22:58:43 +03:00
# include "str_hash.h"
2021-03-16 07:42:25 +03:00
# include "subvolume.h"
2020-11-06 07:39:33 +03:00
# include "varint.h"
2017-03-17 09:18:50 +03:00
# include <linux/random.h>
# include <asm/unaligned.h>
2018-12-17 13:31:09 +03:00
const char * const bch2_inode_opts [ ] = {
# define x(name, ...) #name,
BCH_INODE_OPTS ( )
# undef x
NULL ,
} ;
2017-03-17 09:18:50 +03:00
static const u8 byte_table [ 8 ] = { 1 , 2 , 3 , 4 , 6 , 8 , 10 , 13 } ;
static const u8 bits_table [ 8 ] = {
1 * 8 - 1 ,
2 * 8 - 2 ,
3 * 8 - 3 ,
4 * 8 - 4 ,
6 * 8 - 5 ,
8 * 8 - 6 ,
10 * 8 - 7 ,
13 * 8 - 8 ,
} ;
static int inode_encode_field ( u8 * out , u8 * end , u64 hi , u64 lo )
{
__be64 in [ 2 ] = { cpu_to_be64 ( hi ) , cpu_to_be64 ( lo ) , } ;
unsigned shift , bytes , bits = likely ( ! hi )
? fls64 ( lo )
: fls64 ( hi ) + 64 ;
for ( shift = 1 ; shift < = 8 ; shift + + )
if ( bits < bits_table [ shift - 1 ] )
goto got_shift ;
BUG ( ) ;
got_shift :
bytes = byte_table [ shift - 1 ] ;
BUG_ON ( out + bytes > end ) ;
memcpy ( out , ( u8 * ) in + 16 - bytes , bytes ) ;
* out | = ( 1 < < 8 ) > > shift ;
return bytes ;
}
static int inode_decode_field ( const u8 * in , const u8 * end ,
u64 out [ 2 ] , unsigned * out_bits )
{
__be64 be [ 2 ] = { 0 , 0 } ;
unsigned bytes , shift ;
u8 * p ;
if ( in > = end )
return - 1 ;
if ( ! * in )
return - 1 ;
/*
* position of highest set bit indicates number of bytes :
* shift = number of bits to remove in high byte :
*/
shift = 8 - __fls ( * in ) ; /* 1 <= shift <= 8 */
bytes = byte_table [ shift - 1 ] ;
if ( in + bytes > end )
return - 1 ;
p = ( u8 * ) be + 16 - bytes ;
memcpy ( p , in , bytes ) ;
* p ^ = ( 1 < < 8 ) > > shift ;
out [ 0 ] = be64_to_cpu ( be [ 0 ] ) ;
out [ 1 ] = be64_to_cpu ( be [ 1 ] ) ;
* out_bits = out [ 0 ] ? 64 + fls64 ( out [ 0 ] ) : fls64 ( out [ 1 ] ) ;
return bytes ;
}
2020-11-06 07:39:33 +03:00
static noinline void bch2_inode_pack_v1 ( struct bkey_inode_buf * packed ,
const struct bch_inode_unpacked * inode )
2017-03-17 09:18:50 +03:00
{
2020-11-06 07:39:33 +03:00
struct bkey_i_inode * k = & packed - > inode ;
u8 * out = k - > v . fields ;
2017-03-17 09:18:50 +03:00
u8 * end = ( void * ) & packed [ 1 ] ;
u8 * last_nonzero_field = out ;
unsigned nr_fields = 0 , last_nonzero_fieldnr = 0 ;
2019-10-12 03:20:30 +03:00
unsigned bytes ;
2017-03-17 09:18:50 +03:00
2020-11-06 07:39:33 +03:00
# define x(_name, _bits) \
2017-03-17 09:18:50 +03:00
out + = inode_encode_field ( out , end , 0 , inode - > _name ) ; \
nr_fields + + ; \
\
if ( inode - > _name ) { \
last_nonzero_field = out ; \
last_nonzero_fieldnr = nr_fields ; \
}
BCH_INODE_FIELDS ( )
2018-12-13 14:01:30 +03:00
# undef x
2017-03-17 09:18:50 +03:00
out = last_nonzero_field ;
nr_fields = last_nonzero_fieldnr ;
2019-10-12 03:20:30 +03:00
bytes = out - ( u8 * ) & packed - > inode . v ;
set_bkey_val_bytes ( & packed - > inode . k , bytes ) ;
memset_u64s_tail ( & packed - > inode . v , 0 , bytes ) ;
2017-03-17 09:18:50 +03:00
2020-11-06 07:39:33 +03:00
SET_INODE_NR_FIELDS ( & k - > v , nr_fields ) ;
}
static void bch2_inode_pack_v2 ( struct bkey_inode_buf * packed ,
const struct bch_inode_unpacked * inode )
{
struct bkey_i_inode * k = & packed - > inode ;
u8 * out = k - > v . fields ;
u8 * end = ( void * ) & packed [ 1 ] ;
u8 * last_nonzero_field = out ;
unsigned nr_fields = 0 , last_nonzero_fieldnr = 0 ;
unsigned bytes ;
int ret ;
# define x(_name, _bits) \
nr_fields + + ; \
\
if ( inode - > _name ) { \
2021-07-13 23:03:51 +03:00
ret = bch2_varint_encode_fast ( out , inode - > _name ) ; \
2020-11-06 07:39:33 +03:00
out + = ret ; \
\
if ( _bits > 64 ) \
* out + + = 0 ; \
\
last_nonzero_field = out ; \
last_nonzero_fieldnr = nr_fields ; \
} else { \
* out + + = 0 ; \
\
if ( _bits > 64 ) \
* out + + = 0 ; \
}
BCH_INODE_FIELDS ( )
# undef x
BUG_ON ( out > end ) ;
out = last_nonzero_field ;
nr_fields = last_nonzero_fieldnr ;
bytes = out - ( u8 * ) & packed - > inode . v ;
set_bkey_val_bytes ( & packed - > inode . k , bytes ) ;
memset_u64s_tail ( & packed - > inode . v , 0 , bytes ) ;
SET_INODE_NR_FIELDS ( & k - > v , nr_fields ) ;
}
void bch2_inode_pack ( struct bch_fs * c ,
struct bkey_inode_buf * packed ,
const struct bch_inode_unpacked * inode )
{
bkey_inode_init ( & packed - > inode . k_i ) ;
packed - > inode . k . p . offset = inode - > bi_inum ;
packed - > inode . v . bi_hash_seed = inode - > bi_hash_seed ;
packed - > inode . v . bi_flags = cpu_to_le32 ( inode - > bi_flags ) ;
packed - > inode . v . bi_mode = cpu_to_le16 ( inode - > bi_mode ) ;
if ( c - > sb . features & ( 1ULL < < BCH_FEATURE_new_varint ) ) {
SET_INODE_NEW_VARINT ( & packed - > inode . v , true ) ;
bch2_inode_pack_v2 ( packed , inode ) ;
} else {
bch2_inode_pack_v1 ( packed , inode ) ;
}
2017-03-17 09:18:50 +03:00
if ( IS_ENABLED ( CONFIG_BCACHEFS_DEBUG ) ) {
struct bch_inode_unpacked unpacked ;
int ret = bch2_inode_unpack ( inode_i_to_s_c ( & packed - > inode ) ,
& unpacked ) ;
BUG_ON ( ret ) ;
BUG_ON ( unpacked . bi_inum ! = inode - > bi_inum ) ;
BUG_ON ( unpacked . bi_hash_seed ! = inode - > bi_hash_seed ) ;
BUG_ON ( unpacked . bi_mode ! = inode - > bi_mode ) ;
2020-11-06 07:39:33 +03:00
# define x(_name, _bits) if (unpacked._name != inode->_name) \
panic ( " unpacked %llu should be %llu " , \
( u64 ) unpacked . _name , ( u64 ) inode - > _name ) ;
2017-03-17 09:18:50 +03:00
BCH_INODE_FIELDS ( )
2018-12-13 14:01:30 +03:00
# undef x
2017-03-17 09:18:50 +03:00
}
}
2020-11-06 07:39:33 +03:00
static noinline int bch2_inode_unpack_v1 ( struct bkey_s_c_inode inode ,
struct bch_inode_unpacked * unpacked )
2017-03-17 09:18:50 +03:00
{
const u8 * in = inode . v - > fields ;
2020-11-06 07:39:33 +03:00
const u8 * end = bkey_val_end ( inode ) ;
2017-03-17 09:18:50 +03:00
u64 field [ 2 ] ;
unsigned fieldnr = 0 , field_bits ;
int ret ;
2018-12-13 14:01:30 +03:00
# define x(_name, _bits) \
2017-03-17 09:18:50 +03:00
if ( fieldnr + + = = INODE_NR_FIELDS ( inode . v ) ) { \
unsigned offset = offsetof ( struct bch_inode_unpacked , _name ) ; \
memset ( ( void * ) unpacked + offset , 0 , \
sizeof ( * unpacked ) - offset ) ; \
return 0 ; \
} \
\
ret = inode_decode_field ( in , end , field , & field_bits ) ; \
if ( ret < 0 ) \
return ret ; \
\
if ( field_bits > sizeof ( unpacked - > _name ) * 8 ) \
return - 1 ; \
\
unpacked - > _name = field [ 1 ] ; \
in + = ret ;
BCH_INODE_FIELDS ( )
2018-12-13 14:01:30 +03:00
# undef x
2017-03-17 09:18:50 +03:00
/* XXX: signal if there were more fields than expected? */
2020-11-06 07:39:33 +03:00
return 0 ;
}
static int bch2_inode_unpack_v2 ( struct bkey_s_c_inode inode ,
struct bch_inode_unpacked * unpacked )
{
const u8 * in = inode . v - > fields ;
const u8 * end = bkey_val_end ( inode ) ;
unsigned fieldnr = 0 ;
int ret ;
u64 v [ 2 ] ;
# define x(_name, _bits) \
if ( fieldnr < INODE_NR_FIELDS ( inode . v ) ) { \
2021-07-13 23:03:51 +03:00
ret = bch2_varint_decode_fast ( in , end , & v [ 0 ] ) ; \
2020-11-06 07:39:33 +03:00
if ( ret < 0 ) \
return ret ; \
in + = ret ; \
\
if ( _bits > 64 ) { \
2021-07-13 23:03:51 +03:00
ret = bch2_varint_decode_fast ( in , end , & v [ 1 ] ) ; \
2020-11-06 07:39:33 +03:00
if ( ret < 0 ) \
return ret ; \
in + = ret ; \
} else { \
v [ 1 ] = 0 ; \
} \
} else { \
v [ 0 ] = v [ 1 ] = 0 ; \
} \
\
unpacked - > _name = v [ 0 ] ; \
if ( v [ 1 ] | | v [ 0 ] ! = unpacked - > _name ) \
return - 1 ; \
fieldnr + + ;
BCH_INODE_FIELDS ( )
# undef x
/* XXX: signal if there were more fields than expected? */
return 0 ;
}
int bch2_inode_unpack ( struct bkey_s_c_inode inode ,
struct bch_inode_unpacked * unpacked )
{
unpacked - > bi_inum = inode . k - > p . offset ;
unpacked - > bi_hash_seed = inode . v - > bi_hash_seed ;
unpacked - > bi_flags = le32_to_cpu ( inode . v - > bi_flags ) ;
unpacked - > bi_mode = le16_to_cpu ( inode . v - > bi_mode ) ;
if ( INODE_NEW_VARINT ( inode . v ) ) {
return bch2_inode_unpack_v2 ( inode , unpacked ) ;
} else {
return bch2_inode_unpack_v1 ( inode , unpacked ) ;
}
2017-03-17 09:18:50 +03:00
return 0 ;
}
2021-08-30 22:18:31 +03:00
int bch2_inode_peek ( struct btree_trans * trans ,
struct btree_iter * iter ,
struct bch_inode_unpacked * inode ,
2021-03-16 07:28:17 +03:00
subvol_inum inum , unsigned flags )
2019-10-01 23:51:57 +03:00
{
struct bkey_s_c k ;
2021-03-16 07:28:17 +03:00
u32 snapshot ;
2019-10-01 23:51:57 +03:00
int ret ;
2021-06-14 00:07:18 +03:00
if ( trans - > c - > opts . inodes_use_key_cache )
flags | = BTREE_ITER_CACHED ;
2021-03-16 07:28:17 +03:00
ret = bch2_subvolume_get_snapshot ( trans , inum . subvol , & snapshot ) ;
if ( ret )
return ret ;
bch2_trans_iter_init ( trans , iter , BTREE_ID_inodes ,
SPOS ( 0 , inum . inum , snapshot ) , flags ) ;
2021-06-11 03:15:50 +03:00
k = bch2_btree_iter_peek_slot ( iter ) ;
2019-10-01 23:51:57 +03:00
ret = bkey_err ( k ) ;
if ( ret )
goto err ;
2021-04-07 10:11:07 +03:00
ret = k . k - > type = = KEY_TYPE_inode ? 0 : - ENOENT ;
2019-10-01 23:51:57 +03:00
if ( ret )
goto err ;
ret = bch2_inode_unpack ( bkey_s_c_to_inode ( k ) , inode ) ;
if ( ret )
goto err ;
2021-08-30 22:18:31 +03:00
return 0 ;
2019-10-01 23:51:57 +03:00
err :
2021-08-30 22:18:31 +03:00
bch2_trans_iter_exit ( trans , iter ) ;
return ret ;
2019-10-01 23:51:57 +03:00
}
int bch2_inode_write ( struct btree_trans * trans ,
struct btree_iter * iter ,
struct bch_inode_unpacked * inode )
{
struct bkey_inode_buf * inode_p ;
inode_p = bch2_trans_kmalloc ( trans , sizeof ( * inode_p ) ) ;
if ( IS_ERR ( inode_p ) )
return PTR_ERR ( inode_p ) ;
2020-11-06 07:39:33 +03:00
bch2_inode_pack ( trans - > c , inode_p , inode ) ;
bcachefs: Start using bpos.snapshot field
This patch starts treating the bpos.snapshot field like part of the key
in the btree code:
* bpos_successor() and bpos_predecessor() now include the snapshot field
* Keys in btrees that will be using snapshots (extents, inodes, dirents
and xattrs) now always have their snapshot field set to U32_MAX
The btree iterator code gets a new flag, BTREE_ITER_ALL_SNAPSHOTS, that
determines whether we're iterating over keys in all snapshots or not -
internally, this controlls whether bkey_(successor|predecessor)
increment/decrement the snapshot field, or only the higher bits of the
key.
We add a new member to struct btree_iter, iter->snapshot: when
BTREE_ITER_ALL_SNAPSHOTS is not set, iter->pos.snapshot should always
equal iter->snapshot, which will be 0 for btrees that don't use
snapshots, and alsways U32_MAX for btrees that will use snapshots
(until we enable snapshot creation).
This patch also introduces a new metadata version number, and compat
code for reading from/writing to older versions - this isn't a forced
upgrade (yet).
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2021-03-25 01:02:16 +03:00
inode_p - > inode . k . p . snapshot = iter - > snapshot ;
2021-06-02 07:15:07 +03:00
return bch2_trans_update ( trans , iter , & inode_p - > inode . k_i , 0 ) ;
2019-10-01 23:51:57 +03:00
}
2017-03-17 09:18:50 +03:00
const char * bch2_inode_invalid ( const struct bch_fs * c , struct bkey_s_c k )
{
2021-03-16 07:42:25 +03:00
struct bkey_s_c_inode inode = bkey_s_c_to_inode ( k ) ;
struct bch_inode_unpacked unpacked ;
2017-03-17 09:18:50 +03:00
2020-01-07 21:29:32 +03:00
if ( k . k - > p . inode )
return " nonzero k.p.inode " ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
if ( bkey_val_bytes ( k . k ) < sizeof ( struct bch_inode ) )
return " incorrect value size " ;
2017-03-17 09:18:50 +03:00
2020-01-07 21:29:32 +03:00
if ( k . k - > p . offset < BLOCKDEV_INODE_MAX )
2018-11-01 22:10:01 +03:00
return " fs inode in blockdev range " ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
if ( INODE_STR_HASH ( inode . v ) > = BCH_STR_HASH_NR )
return " invalid str hash type " ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
if ( bch2_inode_unpack ( inode , & unpacked ) )
return " invalid variable length fields " ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
if ( unpacked . bi_data_checksum > = BCH_CSUM_OPT_NR + 1 )
return " invalid data checksum type " ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
if ( unpacked . bi_compression > = BCH_COMPRESSION_OPT_NR + 1 )
return " invalid data checksum type " ;
2017-03-17 09:18:50 +03:00
2018-11-01 22:10:01 +03:00
if ( ( unpacked . bi_flags & BCH_INODE_UNLINKED ) & &
unpacked . bi_nlink ! = 0 )
return " flagged as unlinked but bi_nlink != 0 " ;
2017-03-17 09:18:50 +03:00
2021-03-16 07:42:25 +03:00
if ( unpacked . bi_subvol & & ! S_ISDIR ( unpacked . bi_mode ) )
return " subvolume root but not a directory " ;
2018-11-01 22:10:01 +03:00
return NULL ;
2017-03-17 09:18:50 +03:00
}
2021-07-31 00:59:37 +03:00
static void __bch2_inode_unpacked_to_text ( struct printbuf * out , struct bch_inode_unpacked * inode )
{
pr_buf ( out , " mode %o flags %x " , inode - > bi_mode , inode - > bi_flags ) ;
# define x(_name, _bits) \
pr_buf ( out , # _name " %llu " , ( u64 ) inode - > _name ) ;
BCH_INODE_FIELDS ( )
# undef x
}
void bch2_inode_unpacked_to_text ( struct printbuf * out , struct bch_inode_unpacked * inode )
{
pr_buf ( out , " inum: %llu " , inode - > bi_inum ) ;
__bch2_inode_unpacked_to_text ( out , inode ) ;
}
2018-11-09 09:24:07 +03:00
void bch2_inode_to_text ( struct printbuf * out , struct bch_fs * c ,
struct bkey_s_c k )
2017-03-17 09:18:50 +03:00
{
2018-11-01 22:10:01 +03:00
struct bkey_s_c_inode inode = bkey_s_c_to_inode ( k ) ;
2017-03-17 09:18:50 +03:00
struct bch_inode_unpacked unpacked ;
2018-11-01 22:10:01 +03:00
if ( bch2_inode_unpack ( inode , & unpacked ) ) {
pr_buf ( out , " (unpack error) " ) ;
return ;
}
2017-03-17 09:18:50 +03:00
2021-07-31 00:59:37 +03:00
__bch2_inode_unpacked_to_text ( out , & unpacked ) ;
2018-11-01 22:10:01 +03:00
}
const char * bch2_inode_generation_invalid ( const struct bch_fs * c ,
struct bkey_s_c k )
{
2020-01-07 21:29:32 +03:00
if ( k . k - > p . inode )
return " nonzero k.p.inode " ;
2018-11-01 22:10:01 +03:00
if ( bkey_val_bytes ( k . k ) ! = sizeof ( struct bch_inode_generation ) )
return " incorrect value size " ;
return NULL ;
}
void bch2_inode_generation_to_text ( struct printbuf * out , struct bch_fs * c ,
struct bkey_s_c k )
{
2019-06-25 00:55:15 +03:00
struct bkey_s_c_inode_generation gen = bkey_s_c_to_inode_generation ( k ) ;
pr_buf ( out , " generation: %u " , le32_to_cpu ( gen . v - > bi_generation ) ) ;
2017-03-17 09:18:50 +03:00
}
2019-10-03 01:35:36 +03:00
void bch2_inode_init_early ( struct bch_fs * c ,
struct bch_inode_unpacked * inode_u )
2017-03-17 09:18:50 +03:00
{
2019-10-04 22:58:43 +03:00
enum bch_str_hash_type str_hash =
bch2_str_hash_opt_to_type ( c , c - > opts . str_hash ) ;
2017-03-17 09:18:50 +03:00
memset ( inode_u , 0 , sizeof ( * inode_u ) ) ;
/* ick */
2019-10-04 22:58:43 +03:00
inode_u - > bi_flags | = str_hash < < INODE_STR_HASH_OFFSET ;
2018-12-17 14:11:14 +03:00
get_random_bytes ( & inode_u - > bi_hash_seed ,
sizeof ( inode_u - > bi_hash_seed ) ) ;
2019-10-03 01:35:36 +03:00
}
2017-03-17 09:18:50 +03:00
2019-10-03 01:35:36 +03:00
void bch2_inode_init_late ( struct bch_inode_unpacked * inode_u , u64 now ,
uid_t uid , gid_t gid , umode_t mode , dev_t rdev ,
struct bch_inode_unpacked * parent )
{
2017-03-17 09:18:50 +03:00
inode_u - > bi_mode = mode ;
inode_u - > bi_uid = uid ;
inode_u - > bi_gid = gid ;
inode_u - > bi_dev = rdev ;
inode_u - > bi_atime = now ;
inode_u - > bi_mtime = now ;
inode_u - > bi_ctime = now ;
inode_u - > bi_otime = now ;
2019-10-03 01:35:36 +03:00
if ( parent & & parent - > bi_mode & S_ISGID ) {
inode_u - > bi_gid = parent - > bi_gid ;
if ( S_ISDIR ( mode ) )
inode_u - > bi_mode | = S_ISGID ;
}
2017-03-17 09:18:50 +03:00
if ( parent ) {
2018-12-13 16:24:21 +03:00
# define x(_name, ...) inode_u->bi_##_name = parent->bi_##_name;
BCH_INODE_OPTS ( )
2018-12-13 14:01:30 +03:00
# undef x
2017-03-17 09:18:50 +03:00
}
}
2019-10-03 01:35:36 +03:00
void bch2_inode_init ( struct bch_fs * c , struct bch_inode_unpacked * inode_u ,
uid_t uid , gid_t gid , umode_t mode , dev_t rdev ,
struct bch_inode_unpacked * parent )
{
bch2_inode_init_early ( c , inode_u ) ;
bch2_inode_init_late ( inode_u , bch2_current_time ( c ) ,
uid , gid , mode , rdev , parent ) ;
}
2017-03-17 09:18:50 +03:00
static inline u32 bkey_generation ( struct bkey_s_c k )
{
switch ( k . k - > type ) {
2018-11-01 22:10:01 +03:00
case KEY_TYPE_inode :
2017-03-17 09:18:50 +03:00
BUG ( ) ;
2018-11-01 22:10:01 +03:00
case KEY_TYPE_inode_generation :
2017-03-17 09:18:50 +03:00
return le32_to_cpu ( bkey_s_c_to_inode_generation ( k ) . v - > bi_generation ) ;
default :
return 0 ;
}
}
2021-03-16 07:28:17 +03:00
/*
* This just finds an empty slot :
*/
2021-08-30 22:18:31 +03:00
int bch2_inode_create ( struct btree_trans * trans ,
struct btree_iter * iter ,
struct bch_inode_unpacked * inode_u ,
u32 snapshot , u64 cpu )
2020-10-28 01:56:21 +03:00
{
struct bch_fs * c = trans - > c ;
struct bkey_s_c k ;
2021-03-16 02:18:30 +03:00
u64 min , max , start , pos , * hint ;
2021-05-15 03:02:44 +03:00
int ret = 0 ;
2021-05-28 03:20:20 +03:00
unsigned bits = ( c - > opts . inodes_32bit ? 31 : 63 ) ;
2020-11-03 07:51:33 +03:00
2021-05-28 03:20:20 +03:00
if ( c - > opts . shard_inode_numbers ) {
bits - = c - > inode_shard_bits ;
2020-11-03 07:51:33 +03:00
2021-05-28 03:20:20 +03:00
min = ( cpu < < bits ) ;
max = ( cpu < < bits ) | ~ ( ULLONG_MAX < < bits ) ;
min = max_t ( u64 , min , BLOCKDEV_INODE_MAX ) ;
hint = c - > unused_inode_hints + cpu ;
} else {
min = BLOCKDEV_INODE_MAX ;
max = ~ ( ULLONG_MAX < < bits ) ;
hint = c - > unused_inode_hints ;
}
2020-11-03 07:51:33 +03:00
start = READ_ONCE ( * hint ) ;
if ( start > = max | | start < min )
start = min ;
2021-03-16 02:18:30 +03:00
pos = start ;
2021-08-30 22:18:31 +03:00
bch2_trans_iter_init ( trans , iter , BTREE_ID_inodes , POS ( 0 , pos ) ,
BTREE_ITER_ALL_SNAPSHOTS |
BTREE_ITER_INTENT ) ;
2020-11-03 07:51:33 +03:00
again :
2021-03-16 02:18:30 +03:00
while ( ( k = bch2_btree_iter_peek ( iter ) ) . k & &
! ( ret = bkey_err ( k ) ) & &
bkey_cmp ( k . k - > p , POS ( 0 , max ) ) < 0 ) {
while ( pos < iter - > pos . offset ) {
if ( ! bch2_btree_key_cache_find ( c , BTREE_ID_inodes , POS ( 0 , pos ) ) )
goto found_slot ;
pos + + ;
}
if ( k . k - > p . snapshot = = snapshot & &
k . k - > type ! = KEY_TYPE_inode & &
! bch2_btree_key_cache_find ( c , BTREE_ID_inodes , SPOS ( 0 , pos , snapshot ) ) ) {
2021-07-25 02:50:40 +03:00
bch2_btree_iter_advance ( iter ) ;
2021-03-16 02:18:30 +03:00
continue ;
}
2017-03-17 09:18:50 +03:00
2020-11-03 07:51:33 +03:00
/*
2021-03-16 02:18:30 +03:00
* We don ' t need to iterate over keys in every snapshot once
* we ' ve found just one :
2020-11-03 07:51:33 +03:00
*/
2021-03-16 02:18:30 +03:00
pos = iter - > pos . offset + 1 ;
bch2_btree_iter_set_pos ( iter , POS ( 0 , pos ) ) ;
}
while ( ! ret & & pos < max ) {
if ( ! bch2_btree_key_cache_find ( c , BTREE_ID_inodes , POS ( 0 , pos ) ) )
2020-11-03 07:51:33 +03:00
goto found_slot ;
2021-03-16 02:18:30 +03:00
pos + + ;
2020-10-28 01:56:21 +03:00
}
2021-03-16 02:18:30 +03:00
if ( ! ret & & start = = min )
ret = - ENOSPC ;
2020-10-28 01:56:21 +03:00
2021-03-16 02:18:30 +03:00
if ( ret ) {
2021-08-30 22:18:31 +03:00
bch2_trans_iter_exit ( trans , iter ) ;
return ret ;
2020-11-03 07:51:33 +03:00
}
2017-03-17 09:18:50 +03:00
2021-03-16 02:18:30 +03:00
/* Retry from start */
pos = start = min ;
bch2_btree_iter_set_pos ( iter , POS ( 0 , pos ) ) ;
goto again ;
2020-11-03 07:51:33 +03:00
found_slot :
2021-03-16 02:18:30 +03:00
bch2_btree_iter_set_pos ( iter , SPOS ( 0 , pos , snapshot ) ) ;
k = bch2_btree_iter_peek_slot ( iter ) ;
ret = bkey_err ( k ) ;
if ( ret ) {
2021-08-30 22:18:31 +03:00
bch2_trans_iter_exit ( trans , iter ) ;
return ret ;
2021-03-16 02:18:30 +03:00
}
/* We may have raced while the iterator wasn't pointing at pos: */
if ( k . k - > type = = KEY_TYPE_inode | |
bch2_btree_key_cache_find ( c , BTREE_ID_inodes , k . k - > p ) )
goto again ;
2020-11-03 07:51:33 +03:00
* hint = k . k - > p . offset ;
inode_u - > bi_inum = k . k - > p . offset ;
inode_u - > bi_generation = bkey_generation ( k ) ;
2021-08-30 22:18:31 +03:00
return 0 ;
2017-03-17 09:18:50 +03:00
}
2021-03-16 07:28:17 +03:00
static int bch2_inode_delete_keys ( struct btree_trans * trans ,
subvol_inum inum , enum btree_id id )
{
u64 offset = 0 ;
int ret = 0 ;
while ( ! ret | | ret = = - EINTR ) {
struct btree_iter iter ;
struct bkey_s_c k ;
struct bkey_i delete ;
u32 snapshot ;
bch2_trans_begin ( trans ) ;
ret = bch2_subvolume_get_snapshot ( trans , inum . subvol , & snapshot ) ;
if ( ret )
continue ;
bch2_trans_iter_init ( trans , & iter , id ,
SPOS ( inum . inum , offset , snapshot ) ,
BTREE_ITER_INTENT ) ;
k = bch2_btree_iter_peek ( & iter ) ;
if ( ! k . k | | iter . pos . inode ! = inum . inum ) {
bch2_trans_iter_exit ( trans , & iter ) ;
break ;
}
ret = bkey_err ( k ) ;
if ( ret )
goto err ;
bkey_init ( & delete . k ) ;
delete . k . p = iter . pos ;
if ( btree_node_type_is_extents ( iter . btree_id ) ) {
unsigned max_sectors =
min_t ( u64 , U64_MAX - iter . pos . offset ,
KEY_SIZE_MAX & ( ~ 0 < < trans - > c - > block_bits ) ) ;
/* create the biggest key we can */
bch2_key_resize ( & delete . k , max_sectors ) ;
ret = bch2_extent_trim_atomic ( trans , & iter , & delete ) ;
if ( ret )
goto err ;
}
ret = bch2_trans_update ( trans , & iter , & delete , 0 ) ? :
bch2_trans_commit ( trans , NULL , NULL ,
BTREE_INSERT_NOFAIL ) ;
err :
offset = iter . pos . offset ;
bch2_trans_iter_exit ( trans , & iter ) ;
}
return ret ;
}
int bch2_inode_rm ( struct bch_fs * c , subvol_inum inum , bool cached )
2017-03-17 09:18:50 +03:00
{
2019-03-14 03:49:16 +03:00
struct btree_trans trans ;
2021-08-30 22:18:31 +03:00
struct btree_iter iter = { NULL } ;
2017-03-17 09:18:50 +03:00
struct bkey_i_inode_generation delete ;
2021-03-22 05:01:12 +03:00
struct bch_inode_unpacked inode_u ;
2019-09-23 02:10:21 +03:00
struct bkey_s_c k ;
2021-06-14 00:07:18 +03:00
unsigned iter_flags = BTREE_ITER_INTENT ;
2021-03-16 07:28:17 +03:00
u32 snapshot ;
2017-03-17 09:18:50 +03:00
int ret ;
2021-06-14 00:07:18 +03:00
if ( cached & & c - > opts . inodes_use_key_cache )
iter_flags | = BTREE_ITER_CACHED ;
2021-06-03 06:31:42 +03:00
bch2_trans_init ( & trans , c , 0 , 1024 ) ;
2020-11-21 05:28:55 +03:00
2017-03-17 09:18:50 +03:00
/*
* If this was a directory , there shouldn ' t be any real dirents left -
* but there could be whiteouts ( from hash collisions ) that we should
* delete :
*
* XXX : the dirent could ideally would delete whiteouts when they ' re no
* longer needed
*/
2021-03-16 07:28:17 +03:00
ret = bch2_inode_delete_keys ( & trans , inum , BTREE_ID_extents ) ? :
bch2_inode_delete_keys ( & trans , inum , BTREE_ID_xattrs ) ? :
bch2_inode_delete_keys ( & trans , inum , BTREE_ID_dirents ) ;
2018-08-09 02:53:30 +03:00
if ( ret )
2020-11-21 05:28:55 +03:00
goto err ;
2019-09-23 02:10:21 +03:00
retry :
bch2_trans_begin ( & trans ) ;
2021-03-16 07:28:17 +03:00
ret = bch2_subvolume_get_snapshot ( & trans , inum . subvol , & snapshot ) ;
if ( ret )
goto err ;
2021-08-30 22:18:31 +03:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_inodes ,
2021-03-16 07:28:17 +03:00
SPOS ( 0 , inum . inum , snapshot ) , iter_flags ) ;
2021-08-30 22:18:31 +03:00
k = bch2_btree_iter_peek_slot ( & iter ) ;
2017-03-17 09:18:50 +03:00
2019-09-23 02:10:21 +03:00
ret = bkey_err ( k ) ;
if ( ret )
goto err ;
2017-03-17 09:18:50 +03:00
2021-03-22 05:01:12 +03:00
if ( k . k - > type ! = KEY_TYPE_inode ) {
bch2_fs_inconsistent ( trans . c ,
" inode %llu not found when deleting " ,
2021-03-16 07:28:17 +03:00
inum . inum ) ;
2021-03-22 05:01:12 +03:00
ret = - EIO ;
goto err ;
2019-09-23 02:10:21 +03:00
}
2017-03-17 09:18:50 +03:00
2021-03-22 05:01:12 +03:00
bch2_inode_unpack ( bkey_s_c_to_inode ( k ) , & inode_u ) ;
2021-03-16 07:42:25 +03:00
/* Subvolume root? */
2021-10-11 19:03:19 +03:00
BUG_ON ( inode_u . bi_subvol ) ;
2021-03-16 07:42:25 +03:00
2021-03-22 05:01:12 +03:00
bkey_inode_generation_init ( & delete . k_i ) ;
2021-08-30 22:18:31 +03:00
delete . k . p = iter . pos ;
2021-03-22 05:01:12 +03:00
delete . v . bi_generation = cpu_to_le32 ( inode_u . bi_generation + 1 ) ;
2017-03-17 09:18:50 +03:00
2021-08-30 22:18:31 +03:00
ret = bch2_trans_update ( & trans , & iter , & delete . k_i , 0 ) ? :
2021-06-02 07:15:07 +03:00
bch2_trans_commit ( & trans , NULL , NULL ,
2019-09-23 02:10:21 +03:00
BTREE_INSERT_NOFAIL ) ;
err :
2021-08-30 22:18:31 +03:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-09-23 02:10:21 +03:00
if ( ret = = - EINTR )
goto retry ;
2017-03-17 09:18:50 +03:00
2019-03-14 03:49:16 +03:00
bch2_trans_exit ( & trans ) ;
2017-03-17 09:18:50 +03:00
return ret ;
}
2021-03-16 07:28:17 +03:00
static int bch2_inode_find_by_inum_trans ( struct btree_trans * trans ,
subvol_inum inum ,
2021-04-07 10:11:07 +03:00
struct bch_inode_unpacked * inode )
2017-03-17 09:18:50 +03:00
{
2021-03-16 07:28:17 +03:00
struct btree_iter iter ;
2019-10-26 02:06:26 +03:00
int ret ;
2017-03-17 09:18:50 +03:00
2021-03-16 07:28:17 +03:00
ret = bch2_inode_peek ( trans , & iter , inode , inum , 0 ) ;
if ( ! ret )
bch2_trans_iter_exit ( trans , & iter ) ;
2019-04-01 00:37:30 +03:00
return ret ;
}
2021-03-16 07:28:17 +03:00
int bch2_inode_find_by_inum ( struct bch_fs * c , subvol_inum inum ,
2019-04-01 00:37:30 +03:00
struct bch_inode_unpacked * inode )
{
2019-12-23 07:04:30 +03:00
return bch2_trans_do ( c , NULL , NULL , 0 ,
2021-03-16 07:28:17 +03:00
bch2_inode_find_by_inum_trans ( & trans , inum , inode ) ) ;
2017-03-17 09:18:50 +03:00
}