2005-04-17 02:20:36 +04:00
/*
2005-11-02 06:58:39 +03:00
* Copyright ( c ) 2000 - 2002 , 2005 Silicon Graphics , Inc .
* All Rights Reserved .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:58:39 +03:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
2005-04-17 02:20:36 +04:00
* published by the Free Software Foundation .
*
2005-11-02 06:58:39 +03:00
* This program is distributed in the hope that it would 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 .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:58:39 +03:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-04-17 02:20:36 +04:00
*/
# include "xfs.h"
2005-11-02 06:38:42 +03:00
# include "xfs_fs.h"
2005-04-17 02:20:36 +04:00
# include "xfs_types.h"
2005-11-02 06:38:42 +03:00
# include "xfs_bit.h"
2005-04-17 02:20:36 +04:00
# include "xfs_log.h"
2005-11-02 06:38:42 +03:00
# include "xfs_inum.h"
2005-04-17 02:20:36 +04:00
# include "xfs_trans.h"
# include "xfs_sb.h"
2005-11-02 06:38:42 +03:00
# include "xfs_ag.h"
2005-04-17 02:20:36 +04:00
# include "xfs_mount.h"
# include "xfs_trans_priv.h"
# include "xfs_bmap_btree.h"
# include "xfs_dinode.h"
# include "xfs_inode.h"
2005-11-02 06:38:42 +03:00
# include "xfs_inode_item.h"
2008-04-10 06:22:24 +04:00
# include "xfs_error.h"
2009-12-15 02:14:59 +03:00
# include "xfs_trace.h"
2005-04-17 02:20:36 +04:00
kmem_zone_t * xfs_ili_zone ; /* inode log item zone */
2010-06-23 12:11:15 +04:00
static inline struct xfs_inode_log_item * INODE_ITEM ( struct xfs_log_item * lip )
{
return container_of ( lip , struct xfs_inode_log_item , ili_item ) ;
}
2005-04-17 02:20:36 +04:00
/*
* This returns the number of iovecs needed to log the given inode item .
*
* We need one iovec for the inode log format structure , one for the
* inode core , and possibly one for the inode data / extents / b - tree root
* and one for the inode attribute data / extents / b - tree root .
*/
STATIC uint
xfs_inode_item_size (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
uint nvecs = 2 ;
2005-04-17 02:20:36 +04:00
/*
* Only log the data / extents / b - tree root if there is something
* left to log .
*/
iip - > ili_format . ilf_fields | = XFS_ILOG_CORE ;
switch ( ip - > i_d . di_format ) {
case XFS_DINODE_FMT_EXTENTS :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
XFS_ILOG_DEV | XFS_ILOG_UUID ) ;
if ( ( iip - > ili_format . ilf_fields & XFS_ILOG_DEXT ) & &
( ip - > i_d . di_nextents > 0 ) & &
( ip - > i_df . if_bytes > 0 ) ) {
ASSERT ( ip - > i_df . if_u1 . if_extents ! = NULL ) ;
nvecs + + ;
} else {
iip - > ili_format . ilf_fields & = ~ XFS_ILOG_DEXT ;
}
break ;
case XFS_DINODE_FMT_BTREE :
ASSERT ( ip - > i_df . if_ext_max = =
XFS_IFORK_DSIZE ( ip ) / ( uint ) sizeof ( xfs_bmbt_rec_t ) ) ;
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_DDATA | XFS_ILOG_DEXT |
XFS_ILOG_DEV | XFS_ILOG_UUID ) ;
if ( ( iip - > ili_format . ilf_fields & XFS_ILOG_DBROOT ) & &
( ip - > i_df . if_broot_bytes > 0 ) ) {
ASSERT ( ip - > i_df . if_broot ! = NULL ) ;
nvecs + + ;
} else {
ASSERT ( ! ( iip - > ili_format . ilf_fields &
XFS_ILOG_DBROOT ) ) ;
# ifdef XFS_TRANS_DEBUG
if ( iip - > ili_root_size > 0 ) {
ASSERT ( iip - > ili_root_size = =
ip - > i_df . if_broot_bytes ) ;
ASSERT ( memcmp ( iip - > ili_orig_root ,
ip - > i_df . if_broot ,
iip - > ili_root_size ) = = 0 ) ;
} else {
ASSERT ( ip - > i_df . if_broot_bytes = = 0 ) ;
}
# endif
iip - > ili_format . ilf_fields & = ~ XFS_ILOG_DBROOT ;
}
break ;
case XFS_DINODE_FMT_LOCAL :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_DEXT | XFS_ILOG_DBROOT |
XFS_ILOG_DEV | XFS_ILOG_UUID ) ;
if ( ( iip - > ili_format . ilf_fields & XFS_ILOG_DDATA ) & &
( ip - > i_df . if_bytes > 0 ) ) {
ASSERT ( ip - > i_df . if_u1 . if_data ! = NULL ) ;
ASSERT ( ip - > i_d . di_size > 0 ) ;
nvecs + + ;
} else {
iip - > ili_format . ilf_fields & = ~ XFS_ILOG_DDATA ;
}
break ;
case XFS_DINODE_FMT_DEV :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
XFS_ILOG_DEXT | XFS_ILOG_UUID ) ;
break ;
case XFS_DINODE_FMT_UUID :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
XFS_ILOG_DEXT | XFS_ILOG_DEV ) ;
break ;
default :
ASSERT ( 0 ) ;
break ;
}
/*
* If there are no attributes associated with this file ,
* then there cannot be anything more to log .
* Clear all attribute - related log flags .
*/
if ( ! XFS_IFORK_Q ( ip ) ) {
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT ) ;
return nvecs ;
}
/*
* Log any necessary attribute data .
*/
switch ( ip - > i_d . di_aformat ) {
case XFS_DINODE_FMT_EXTENTS :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_ADATA | XFS_ILOG_ABROOT ) ;
if ( ( iip - > ili_format . ilf_fields & XFS_ILOG_AEXT ) & &
( ip - > i_d . di_anextents > 0 ) & &
( ip - > i_afp - > if_bytes > 0 ) ) {
ASSERT ( ip - > i_afp - > if_u1 . if_extents ! = NULL ) ;
nvecs + + ;
} else {
iip - > ili_format . ilf_fields & = ~ XFS_ILOG_AEXT ;
}
break ;
case XFS_DINODE_FMT_BTREE :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_ADATA | XFS_ILOG_AEXT ) ;
if ( ( iip - > ili_format . ilf_fields & XFS_ILOG_ABROOT ) & &
( ip - > i_afp - > if_broot_bytes > 0 ) ) {
ASSERT ( ip - > i_afp - > if_broot ! = NULL ) ;
nvecs + + ;
} else {
iip - > ili_format . ilf_fields & = ~ XFS_ILOG_ABROOT ;
}
break ;
case XFS_DINODE_FMT_LOCAL :
iip - > ili_format . ilf_fields & =
~ ( XFS_ILOG_AEXT | XFS_ILOG_ABROOT ) ;
if ( ( iip - > ili_format . ilf_fields & XFS_ILOG_ADATA ) & &
( ip - > i_afp - > if_bytes > 0 ) ) {
ASSERT ( ip - > i_afp - > if_u1 . if_data ! = NULL ) ;
nvecs + + ;
} else {
iip - > ili_format . ilf_fields & = ~ XFS_ILOG_ADATA ;
}
break ;
default :
ASSERT ( 0 ) ;
break ;
}
return nvecs ;
}
/*
* This is called to fill in the vector of log iovecs for the
* given inode log item . It fills the first item with an inode
* log format structure , the second with the on - disk inode structure ,
* and a possible third and / or fourth with the inode data / extents / b - tree
* root and inode attributes data / extents / b - tree root .
*/
STATIC void
xfs_inode_item_format (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip ,
struct xfs_log_iovec * vecp )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
2005-04-17 02:20:36 +04:00
uint nvecs ;
size_t data_bytes ;
xfs_bmbt_rec_t * ext_buffer ;
xfs_mount_t * mp ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = & iip - > ili_format ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = sizeof ( xfs_inode_log_format_t ) ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IFORMAT ;
2005-04-17 02:20:36 +04:00
vecp + + ;
nvecs = 1 ;
/*
* Clear i_update_core if the timestamps ( or any other
* non - transactional modification ) need flushing / logging
* and we ' re about to log them with the rest of the core .
*
* This is the same logic as xfs_iflush ( ) but this code can ' t
* run at the same time as xfs_iflush because we ' re in commit
* processing here and so we have the inode lock held in
* exclusive mode . Although it doesn ' t really matter
* for the timestamps if both routines were to grab the
* timestamps or not . That would be ok .
*
* We clear i_update_core before copying out the data .
* This is for coordination with our timestamp updates
* that don ' t hold the inode lock . They will always
* update the timestamps BEFORE setting i_update_core ,
* so if we clear i_update_core after they set it we
* are guaranteed to see their updates to the timestamps
* either here . Likewise , if they set it after we clear it
* here , we ' ll see it either on the next commit of this
* inode or the next time the inode gets flushed via
* xfs_iflush ( ) . This depends on strongly ordered memory
* semantics , but we have that . We use the SYNCHRONIZE
* macro to make sure that the compiler does not reorder
* the i_update_core access below the data copy below .
*/
if ( ip - > i_update_core ) {
ip - > i_update_core = 0 ;
SYNCHRONIZE ( ) ;
}
2006-01-11 07:35:17 +03:00
/*
2009-10-07 00:29:26 +04:00
* Make sure to get the latest timestamps from the Linux inode .
2006-01-11 07:35:17 +03:00
*/
2009-10-07 00:29:26 +04:00
xfs_synchronize_times ( ip ) ;
2007-11-23 08:29:18 +03:00
2010-06-23 12:11:15 +04:00
vecp - > i_addr = & ip - > i_d ;
2008-11-28 06:23:39 +03:00
vecp - > i_len = sizeof ( struct xfs_icdinode ) ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_ICORE ;
2005-04-17 02:20:36 +04:00
vecp + + ;
nvecs + + ;
iip - > ili_format . ilf_fields | = XFS_ILOG_CORE ;
/*
* If this is really an old format inode , then we need to
* log it as such . This means that we have to copy the link
* count from the new field to the old . We don ' t have to worry
* about the new fields , because nothing trusts them as long as
* the old inode version number is there . If the superblock already
* has a new version number , then we don ' t bother converting back .
*/
mp = ip - > i_mount ;
2008-11-28 06:23:39 +03:00
ASSERT ( ip - > i_d . di_version = = 1 | | xfs_sb_version_hasnlink ( & mp - > m_sb ) ) ;
if ( ip - > i_d . di_version = = 1 ) {
2008-03-06 05:44:28 +03:00
if ( ! xfs_sb_version_hasnlink ( & mp - > m_sb ) ) {
2005-04-17 02:20:36 +04:00
/*
* Convert it back .
*/
ASSERT ( ip - > i_d . di_nlink < = XFS_MAXLINK_1 ) ;
ip - > i_d . di_onlink = ip - > i_d . di_nlink ;
} else {
/*
* The superblock version has already been bumped ,
* so just make the conversion to the new inode
* format permanent .
*/
2008-11-28 06:23:39 +03:00
ip - > i_d . di_version = 2 ;
2005-04-17 02:20:36 +04:00
ip - > i_d . di_onlink = 0 ;
memset ( & ( ip - > i_d . di_pad [ 0 ] ) , 0 , sizeof ( ip - > i_d . di_pad ) ) ;
}
}
switch ( ip - > i_d . di_format ) {
case XFS_DINODE_FMT_EXTENTS :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
XFS_ILOG_DEV | XFS_ILOG_UUID ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_DEXT ) {
ASSERT ( ip - > i_df . if_bytes > 0 ) ;
ASSERT ( ip - > i_df . if_u1 . if_extents ! = NULL ) ;
ASSERT ( ip - > i_d . di_nextents > 0 ) ;
ASSERT ( iip - > ili_extents_buf = = NULL ) ;
2010-07-20 11:54:45 +04:00
ASSERT ( ( ip - > i_df . if_bytes /
( uint ) sizeof ( xfs_bmbt_rec_t ) ) > 0 ) ;
2005-09-08 09:30:05 +04:00
# ifdef XFS_NATIVE_HOST
2010-07-26 22:51:46 +04:00
if ( ip - > i_d . di_nextents = = ip - > i_df . if_bytes /
( uint ) sizeof ( xfs_bmbt_rec_t ) ) {
2005-04-17 02:20:36 +04:00
/*
* There are no delayed allocation
* extents , so just point to the
* real extents array .
*/
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ip - > i_df . if_u1 . if_extents ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = ip - > i_df . if_bytes ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IEXT ;
2005-04-17 02:20:36 +04:00
} else
# endif
{
/*
* There are delayed allocation extents
* in the inode , or we need to convert
* the extents to on disk format .
* Use xfs_iextents_copy ( )
* to copy only the real extents into
* a separate buffer . We ' ll free the
* buffer in the unlock routine .
*/
ext_buffer = kmem_alloc ( ip - > i_df . if_bytes ,
KM_SLEEP ) ;
iip - > ili_extents_buf = ext_buffer ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ext_buffer ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = xfs_iextents_copy ( ip , ext_buffer ,
XFS_DATA_FORK ) ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IEXT ;
2005-04-17 02:20:36 +04:00
}
ASSERT ( vecp - > i_len < = ip - > i_df . if_bytes ) ;
iip - > ili_format . ilf_dsize = vecp - > i_len ;
vecp + + ;
nvecs + + ;
}
break ;
case XFS_DINODE_FMT_BTREE :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_DDATA | XFS_ILOG_DEXT |
XFS_ILOG_DEV | XFS_ILOG_UUID ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_DBROOT ) {
ASSERT ( ip - > i_df . if_broot_bytes > 0 ) ;
ASSERT ( ip - > i_df . if_broot ! = NULL ) ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ip - > i_df . if_broot ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = ip - > i_df . if_broot_bytes ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IBROOT ;
2005-04-17 02:20:36 +04:00
vecp + + ;
nvecs + + ;
iip - > ili_format . ilf_dsize = ip - > i_df . if_broot_bytes ;
}
break ;
case XFS_DINODE_FMT_LOCAL :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_DBROOT | XFS_ILOG_DEXT |
XFS_ILOG_DEV | XFS_ILOG_UUID ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_DDATA ) {
ASSERT ( ip - > i_df . if_bytes > 0 ) ;
ASSERT ( ip - > i_df . if_u1 . if_data ! = NULL ) ;
ASSERT ( ip - > i_d . di_size > 0 ) ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ip - > i_df . if_u1 . if_data ;
2005-04-17 02:20:36 +04:00
/*
* Round i_bytes up to a word boundary .
* The underlying memory is guaranteed to
* to be there by xfs_idata_realloc ( ) .
*/
data_bytes = roundup ( ip - > i_df . if_bytes , 4 ) ;
ASSERT ( ( ip - > i_df . if_real_bytes = = 0 ) | |
( ip - > i_df . if_real_bytes = = data_bytes ) ) ;
vecp - > i_len = ( int ) data_bytes ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_ILOCAL ;
2005-04-17 02:20:36 +04:00
vecp + + ;
nvecs + + ;
iip - > ili_format . ilf_dsize = ( unsigned ) data_bytes ;
}
break ;
case XFS_DINODE_FMT_DEV :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_DBROOT | XFS_ILOG_DEXT |
XFS_ILOG_DDATA | XFS_ILOG_UUID ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_DEV ) {
iip - > ili_format . ilf_u . ilfu_rdev =
ip - > i_df . if_u2 . if_rdev ;
}
break ;
case XFS_DINODE_FMT_UUID :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_DBROOT | XFS_ILOG_DEXT |
XFS_ILOG_DDATA | XFS_ILOG_DEV ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_UUID ) {
iip - > ili_format . ilf_u . ilfu_uuid =
ip - > i_df . if_u2 . if_uuid ;
}
break ;
default :
ASSERT ( 0 ) ;
break ;
}
/*
* If there are no attributes associated with the file ,
* then we ' re done .
* Assert that no attribute - related log flags are set .
*/
if ( ! XFS_IFORK_Q ( ip ) ) {
2010-06-23 12:11:15 +04:00
ASSERT ( nvecs = = lip - > li_desc - > lid_size ) ;
2005-04-17 02:20:36 +04:00
iip - > ili_format . ilf_size = nvecs ;
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT ) ) ) ;
return ;
}
switch ( ip - > i_d . di_aformat ) {
case XFS_DINODE_FMT_EXTENTS :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_ADATA | XFS_ILOG_ABROOT ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_AEXT ) {
# ifdef DEBUG
2010-07-20 11:54:45 +04:00
int nrecs = ip - > i_afp - > if_bytes /
2005-04-17 02:20:36 +04:00
( uint ) sizeof ( xfs_bmbt_rec_t ) ;
ASSERT ( nrecs > 0 ) ;
ASSERT ( nrecs = = ip - > i_d . di_anextents ) ;
2010-07-20 11:54:45 +04:00
ASSERT ( ip - > i_afp - > if_bytes > 0 ) ;
ASSERT ( ip - > i_afp - > if_u1 . if_extents ! = NULL ) ;
ASSERT ( ip - > i_d . di_anextents > 0 ) ;
# endif
2005-09-08 09:30:05 +04:00
# ifdef XFS_NATIVE_HOST
2005-04-17 02:20:36 +04:00
/*
* There are not delayed allocation extents
* for attributes , so just point at the array .
*/
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ip - > i_afp - > if_u1 . if_extents ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = ip - > i_afp - > if_bytes ;
# else
ASSERT ( iip - > ili_aextents_buf = = NULL ) ;
/*
* Need to endian flip before logging
*/
ext_buffer = kmem_alloc ( ip - > i_afp - > if_bytes ,
KM_SLEEP ) ;
iip - > ili_aextents_buf = ext_buffer ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ext_buffer ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = xfs_iextents_copy ( ip , ext_buffer ,
XFS_ATTR_FORK ) ;
# endif
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IATTR_EXT ;
2005-04-17 02:20:36 +04:00
iip - > ili_format . ilf_asize = vecp - > i_len ;
vecp + + ;
nvecs + + ;
}
break ;
case XFS_DINODE_FMT_BTREE :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_ADATA | XFS_ILOG_AEXT ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_ABROOT ) {
ASSERT ( ip - > i_afp - > if_broot_bytes > 0 ) ;
ASSERT ( ip - > i_afp - > if_broot ! = NULL ) ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ip - > i_afp - > if_broot ;
2005-04-17 02:20:36 +04:00
vecp - > i_len = ip - > i_afp - > if_broot_bytes ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IATTR_BROOT ;
2005-04-17 02:20:36 +04:00
vecp + + ;
nvecs + + ;
iip - > ili_format . ilf_asize = ip - > i_afp - > if_broot_bytes ;
}
break ;
case XFS_DINODE_FMT_LOCAL :
ASSERT ( ! ( iip - > ili_format . ilf_fields &
( XFS_ILOG_ABROOT | XFS_ILOG_AEXT ) ) ) ;
if ( iip - > ili_format . ilf_fields & XFS_ILOG_ADATA ) {
ASSERT ( ip - > i_afp - > if_bytes > 0 ) ;
ASSERT ( ip - > i_afp - > if_u1 . if_data ! = NULL ) ;
2010-06-23 12:11:15 +04:00
vecp - > i_addr = ip - > i_afp - > if_u1 . if_data ;
2005-04-17 02:20:36 +04:00
/*
* Round i_bytes up to a word boundary .
* The underlying memory is guaranteed to
* to be there by xfs_idata_realloc ( ) .
*/
data_bytes = roundup ( ip - > i_afp - > if_bytes , 4 ) ;
ASSERT ( ( ip - > i_afp - > if_real_bytes = = 0 ) | |
( ip - > i_afp - > if_real_bytes = = data_bytes ) ) ;
vecp - > i_len = ( int ) data_bytes ;
2010-01-19 12:56:45 +03:00
vecp - > i_type = XLOG_REG_TYPE_IATTR_LOCAL ;
2005-04-17 02:20:36 +04:00
vecp + + ;
nvecs + + ;
iip - > ili_format . ilf_asize = ( unsigned ) data_bytes ;
}
break ;
default :
ASSERT ( 0 ) ;
break ;
}
2010-06-23 12:11:15 +04:00
ASSERT ( nvecs = = lip - > li_desc - > lid_size ) ;
2005-04-17 02:20:36 +04:00
iip - > ili_format . ilf_size = nvecs ;
}
/*
* This is called to pin the inode associated with the inode log
2010-02-18 15:43:22 +03:00
* item in memory so it cannot be written out .
2005-04-17 02:20:36 +04:00
*/
STATIC void
xfs_inode_item_pin (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode * ip = INODE_ITEM ( lip ) - > ili_inode ;
2010-02-18 15:43:22 +03:00
2010-06-23 12:11:15 +04:00
ASSERT ( xfs_isilocked ( ip , XFS_ILOCK_EXCL ) ) ;
trace_xfs_inode_pin ( ip , _RET_IP_ ) ;
atomic_inc ( & ip - > i_pincount ) ;
2005-04-17 02:20:36 +04:00
}
/*
* This is called to unpin the inode associated with the inode log
* item which was previously pinned with a call to xfs_inode_item_pin ( ) .
2010-02-18 15:43:22 +03:00
*
* Also wake up anyone in xfs_iunpin_wait ( ) if the count goes to 0.
2005-04-17 02:20:36 +04:00
*/
STATIC void
xfs_inode_item_unpin (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip ,
2010-06-23 12:11:15 +04:00
int remove )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode * ip = INODE_ITEM ( lip ) - > ili_inode ;
2010-02-18 15:43:22 +03:00
2010-03-08 03:24:07 +03:00
trace_xfs_inode_unpin ( ip , _RET_IP_ ) ;
2010-02-18 15:43:22 +03:00
ASSERT ( atomic_read ( & ip - > i_pincount ) > 0 ) ;
if ( atomic_dec_and_test ( & ip - > i_pincount ) )
wake_up ( & ip - > i_ipin_wait ) ;
2005-04-17 02:20:36 +04:00
}
/*
* This is called to attempt to lock the inode associated with this
* inode log item , in preparation for the push routine which does the actual
* iflush . Don ' t sleep on the inode lock or the flush lock .
*
* If the flush lock is already held , indicating that the inode has
* been or is in the process of being flushed , then ( ideally ) we ' d like to
* see if the inode ' s buffer is still incore , and if so give it a nudge .
* We delay doing so until the pushbuf routine , though , to avoid holding
2006-03-29 02:55:14 +04:00
* the AIL lock across a call to the blackhole which is the buffer cache .
2005-04-17 02:20:36 +04:00
* Also we don ' t want to sleep in any device strategy routines , which can happen
* if we do the subsequent bawrite in here .
*/
STATIC uint
xfs_inode_item_trylock (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
2005-04-17 02:20:36 +04:00
2010-06-23 12:11:15 +04:00
if ( xfs_ipincount ( ip ) > 0 )
2005-04-17 02:20:36 +04:00
return XFS_ITEM_PINNED ;
2010-06-23 12:11:15 +04:00
if ( ! xfs_ilock_nowait ( ip , XFS_ILOCK_SHARED ) )
2005-04-17 02:20:36 +04:00
return XFS_ITEM_LOCKED ;
if ( ! xfs_iflock_nowait ( ip ) ) {
/*
2010-02-02 02:13:42 +03:00
* inode has already been flushed to the backing buffer ,
* leave it locked in shared mode , pushbuf routine will
* unlock it .
2005-04-17 02:20:36 +04:00
*/
2010-02-02 02:13:42 +03:00
return XFS_ITEM_PUSHBUF ;
2005-04-17 02:20:36 +04:00
}
/* Stale items should force out the iclog */
if ( ip - > i_flags & XFS_ISTALE ) {
xfs_ifunlock ( ip ) ;
2010-02-02 02:13:42 +03:00
/*
* we hold the AIL lock - notify the unlock routine of this
* so it doesn ' t try to get the lock again .
*/
2005-04-17 02:20:36 +04:00
xfs_iunlock ( ip , XFS_ILOCK_SHARED | XFS_IUNLOCK_NONOTIFY ) ;
return XFS_ITEM_PINNED ;
}
# ifdef DEBUG
if ( ! XFS_FORCED_SHUTDOWN ( ip - > i_mount ) ) {
ASSERT ( iip - > ili_format . ilf_fields ! = 0 ) ;
ASSERT ( iip - > ili_logged = = 0 ) ;
2010-06-23 12:11:15 +04:00
ASSERT ( lip - > li_flags & XFS_LI_IN_AIL ) ;
2005-04-17 02:20:36 +04:00
}
# endif
return XFS_ITEM_SUCCESS ;
}
/*
* Unlock the inode associated with the inode log item .
* Clear the fields of the inode and inode log item that
* are specific to the current transaction . If the
* hold flags is set , do not unlock the inode .
*/
STATIC void
xfs_inode_item_unlock (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
2010-06-24 05:36:58 +04:00
unsigned short lock_flags ;
2005-04-17 02:20:36 +04:00
ASSERT ( iip - > ili_inode - > i_itemp ! = NULL ) ;
2008-04-22 11:34:00 +04:00
ASSERT ( xfs_isilocked ( iip - > ili_inode , XFS_ILOCK_EXCL ) ) ;
2010-06-23 12:11:15 +04:00
2005-04-17 02:20:36 +04:00
/*
* Clear the transaction pointer in the inode .
*/
ip - > i_transp = NULL ;
/*
* If the inode needed a separate buffer with which to log
* its extents , then free it now .
*/
if ( iip - > ili_extents_buf ! = NULL ) {
ASSERT ( ip - > i_d . di_format = = XFS_DINODE_FMT_EXTENTS ) ;
ASSERT ( ip - > i_d . di_nextents > 0 ) ;
ASSERT ( iip - > ili_format . ilf_fields & XFS_ILOG_DEXT ) ;
ASSERT ( ip - > i_df . if_bytes > 0 ) ;
2008-05-19 10:31:57 +04:00
kmem_free ( iip - > ili_extents_buf ) ;
2005-04-17 02:20:36 +04:00
iip - > ili_extents_buf = NULL ;
}
if ( iip - > ili_aextents_buf ! = NULL ) {
ASSERT ( ip - > i_d . di_aformat = = XFS_DINODE_FMT_EXTENTS ) ;
ASSERT ( ip - > i_d . di_anextents > 0 ) ;
ASSERT ( iip - > ili_format . ilf_fields & XFS_ILOG_AEXT ) ;
ASSERT ( ip - > i_afp - > if_bytes > 0 ) ;
2008-05-19 10:31:57 +04:00
kmem_free ( iip - > ili_aextents_buf ) ;
2005-04-17 02:20:36 +04:00
iip - > ili_aextents_buf = NULL ;
}
2010-06-24 05:36:58 +04:00
lock_flags = iip - > ili_lock_flags ;
iip - > ili_lock_flags = 0 ;
2010-06-24 05:52:50 +04:00
if ( lock_flags ) {
xfs_iunlock ( iip - > ili_inode , lock_flags ) ;
IRELE ( iip - > ili_inode ) ;
}
2005-04-17 02:20:36 +04:00
}
/*
2010-11-30 07:15:46 +03:00
* This is called to find out where the oldest active copy of the inode log
* item in the on disk log resides now that the last log write of it completed
* at the given lsn . Since we always re - log all dirty data in an inode , the
* latest copy in the on disk log is the only one that matters . Therefore ,
* simply return the given lsn .
*
* If the inode has been marked stale because the cluster is being freed , we
* don ' t want to ( re - ) insert this inode into the AIL . There is a race condition
* where the cluster buffer may be unpinned before the inode is inserted into
* the AIL during transaction committed processing . If the buffer is unpinned
* before the inode item has been committed and inserted , then it is possible
* for the buffer to be written and IO completions before the inode is inserted
* into the AIL . In that case , we ' d be inserting a clean , stale inode into the
* AIL which will never get removed . It will , however , get reclaimed which
* triggers an assert in xfs_inode_free ( ) complaining about freein an inode
* still in the AIL .
*
* To avoid this , return a lower LSN than the one passed in so that the
* transaction committed code will not move the inode forward in the AIL but
* will still unpin it properly .
2005-04-17 02:20:36 +04:00
*/
STATIC xfs_lsn_t
xfs_inode_item_committed (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip ,
2005-04-17 02:20:36 +04:00
xfs_lsn_t lsn )
{
2010-11-30 07:15:46 +03:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
if ( xfs_iflags_test ( ip , XFS_ISTALE ) )
return lsn - 1 ;
2010-06-23 12:11:15 +04:00
return lsn ;
2005-04-17 02:20:36 +04:00
}
/*
* This gets called by xfs_trans_push_ail ( ) , when IOP_TRYLOCK
* failed to get the inode flush lock but did get the inode locked SHARED .
* Here we ' re trying to see if the inode buffer is incore , and if so whether it ' s
2010-02-02 02:13:42 +03:00
* marked delayed write . If that ' s the case , we ' ll promote it and that will
* allow the caller to write the buffer by triggering the xfsbufd to run .
2005-04-17 02:20:36 +04:00
*/
STATIC void
xfs_inode_item_pushbuf (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
struct xfs_buf * bp ;
2005-04-17 02:20:36 +04:00
2008-04-22 11:34:00 +04:00
ASSERT ( xfs_isilocked ( ip , XFS_ILOCK_SHARED ) ) ;
2005-04-17 02:20:36 +04:00
/*
2008-08-13 10:41:16 +04:00
* If a flush is not in progress anymore , chances are that the
* inode was taken off the AIL . So , just get out .
2005-04-17 02:20:36 +04:00
*/
2008-08-13 10:41:16 +04:00
if ( completion_done ( & ip - > i_flush ) | |
2010-06-23 12:11:15 +04:00
! ( lip - > li_flags & XFS_LI_IN_AIL ) ) {
2005-04-17 02:20:36 +04:00
xfs_iunlock ( ip , XFS_ILOCK_SHARED ) ;
return ;
}
2010-06-23 12:11:15 +04:00
bp = xfs_incore ( ip - > i_mount - > m_ddev_targp , iip - > ili_format . ilf_blkno ,
iip - > ili_format . ilf_len , XBF_TRYLOCK ) ;
2005-04-17 02:20:36 +04:00
xfs_iunlock ( ip , XFS_ILOCK_SHARED ) ;
2010-02-02 02:13:42 +03:00
if ( ! bp )
return ;
if ( XFS_BUF_ISDELAYWRITE ( bp ) )
xfs_buf_delwri_promote ( bp ) ;
xfs_buf_relse ( bp ) ;
2005-04-17 02:20:36 +04:00
}
/*
* This is called to asynchronously write the inode associated with this
* inode log item out to disk . The inode will already have been locked by
* a successful call to xfs_inode_item_trylock ( ) .
*/
STATIC void
xfs_inode_item_push (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip = INODE_ITEM ( lip ) ;
struct xfs_inode * ip = iip - > ili_inode ;
2005-04-17 02:20:36 +04:00
2008-04-22 11:34:00 +04:00
ASSERT ( xfs_isilocked ( ip , XFS_ILOCK_SHARED ) ) ;
2008-08-13 10:41:16 +04:00
ASSERT ( ! completion_done ( & ip - > i_flush ) ) ;
2010-06-23 12:11:15 +04:00
2005-04-17 02:20:36 +04:00
/*
* Since we were able to lock the inode ' s flush lock and
* we found it on the AIL , the inode must be dirty . This
* is because the inode is removed from the AIL while still
* holding the flush lock in xfs_iflush_done ( ) . Thus , if
* we found it in the AIL and were able to obtain the flush
* lock without sleeping , then there must not have been
* anyone in the process of flushing the inode .
*/
ASSERT ( XFS_FORCED_SHUTDOWN ( ip - > i_mount ) | |
iip - > ili_format . ilf_fields ! = 0 ) ;
/*
2010-02-06 04:39:36 +03:00
* Push the inode to it ' s backing buffer . This will not remove the
* inode from the AIL - a further push will be required to trigger a
* buffer push . However , this allows all the dirty inodes to be pushed
2011-03-26 01:13:55 +03:00
* to the buffer before it is pushed to disk . The buffer IO completion
* will pull the inode from the AIL , mark it clean and unlock the flush
2010-02-06 04:39:36 +03:00
* lock .
2005-04-17 02:20:36 +04:00
*/
2011-03-26 01:13:55 +03:00
( void ) xfs_iflush ( ip , SYNC_TRYLOCK ) ;
2005-04-17 02:20:36 +04:00
xfs_iunlock ( ip , XFS_ILOCK_SHARED ) ;
}
/*
* XXX rcc - this one really has to do something . Probably needs
* to stamp in a new field in the incore inode .
*/
STATIC void
xfs_inode_item_committing (
2010-06-23 12:11:15 +04:00
struct xfs_log_item * lip ,
2005-04-17 02:20:36 +04:00
xfs_lsn_t lsn )
{
2010-06-23 12:11:15 +04:00
INODE_ITEM ( lip ) - > ili_last_lsn = lsn ;
2005-04-17 02:20:36 +04:00
}
/*
* This is the ops vector shared by all buf log items .
*/
2007-02-10 10:34:56 +03:00
static struct xfs_item_ops xfs_inode_item_ops = {
2010-06-23 12:11:15 +04:00
. iop_size = xfs_inode_item_size ,
. iop_format = xfs_inode_item_format ,
. iop_pin = xfs_inode_item_pin ,
. iop_unpin = xfs_inode_item_unpin ,
. iop_trylock = xfs_inode_item_trylock ,
. iop_unlock = xfs_inode_item_unlock ,
. iop_committed = xfs_inode_item_committed ,
. iop_push = xfs_inode_item_push ,
. iop_pushbuf = xfs_inode_item_pushbuf ,
. iop_committing = xfs_inode_item_committing
2005-04-17 02:20:36 +04:00
} ;
/*
* Initialize the inode log item for a newly allocated ( in - core ) inode .
*/
void
xfs_inode_item_init (
2010-06-23 12:11:15 +04:00
struct xfs_inode * ip ,
struct xfs_mount * mp )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
struct xfs_inode_log_item * iip ;
2005-04-17 02:20:36 +04:00
ASSERT ( ip - > i_itemp = = NULL ) ;
iip = ip - > i_itemp = kmem_zone_zalloc ( xfs_ili_zone , KM_SLEEP ) ;
iip - > ili_inode = ip ;
2010-03-23 02:10:00 +03:00
xfs_log_item_init ( mp , & iip - > ili_item , XFS_LI_INODE ,
& xfs_inode_item_ops ) ;
2005-04-17 02:20:36 +04:00
iip - > ili_format . ilf_type = XFS_LI_INODE ;
iip - > ili_format . ilf_ino = ip - > i_ino ;
2008-11-28 06:23:41 +03:00
iip - > ili_format . ilf_blkno = ip - > i_imap . im_blkno ;
iip - > ili_format . ilf_len = ip - > i_imap . im_len ;
iip - > ili_format . ilf_boffset = ip - > i_imap . im_boffset ;
2005-04-17 02:20:36 +04:00
}
/*
* Free the inode log item and any memory hanging off of it .
*/
void
xfs_inode_item_destroy (
xfs_inode_t * ip )
{
# ifdef XFS_TRANS_DEBUG
if ( ip - > i_itemp - > ili_root_size ! = 0 ) {
2008-05-19 10:31:57 +04:00
kmem_free ( ip - > i_itemp - > ili_orig_root ) ;
2005-04-17 02:20:36 +04:00
}
# endif
kmem_zone_free ( xfs_ili_zone , ip - > i_itemp ) ;
}
/*
* This is the inode flushing I / O completion routine . It is called
* from interrupt level when the buffer containing the inode is
* flushed to disk . It is responsible for removing the inode item
* from the AIL if it has not been re - logged , and unlocking the inode ' s
* flush lock .
2010-12-20 04:03:17 +03:00
*
* To reduce AIL lock traffic as much as possible , we scan the buffer log item
* list for other inodes that will run this function . We remove them from the
* buffer list so we can process all the inode IO completions in one AIL lock
* traversal .
2005-04-17 02:20:36 +04:00
*/
void
xfs_iflush_done (
2010-06-23 12:11:15 +04:00
struct xfs_buf * bp ,
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-12-20 04:03:17 +03:00
struct xfs_inode_log_item * iip ;
struct xfs_log_item * blip ;
struct xfs_log_item * next ;
struct xfs_log_item * prev ;
2010-06-23 12:11:15 +04:00
struct xfs_ail * ailp = lip - > li_ailp ;
2010-12-20 04:03:17 +03:00
int need_ail = 0 ;
/*
* Scan the buffer IO completions for other inodes being completed and
* attach them to the current inode log item .
*/
blip = XFS_BUF_FSPRIVATE ( bp , xfs_log_item_t * ) ;
prev = NULL ;
while ( blip ! = NULL ) {
if ( lip - > li_cb ! = xfs_iflush_done ) {
prev = blip ;
blip = blip - > li_bio_list ;
continue ;
}
/* remove from list */
next = blip - > li_bio_list ;
if ( ! prev ) {
XFS_BUF_SET_FSPRIVATE ( bp , next ) ;
} else {
prev - > li_bio_list = next ;
}
/* add to current list */
blip - > li_bio_list = lip - > li_bio_list ;
lip - > li_bio_list = blip ;
/*
* while we have the item , do the unlocked check for needing
* the AIL lock .
*/
iip = INODE_ITEM ( blip ) ;
if ( iip - > ili_logged & & blip - > li_lsn = = iip - > ili_flush_lsn )
need_ail + + ;
blip = next ;
}
/* make sure we capture the state of the initial inode. */
iip = INODE_ITEM ( lip ) ;
if ( iip - > ili_logged & & lip - > li_lsn = = iip - > ili_flush_lsn )
need_ail + + ;
2005-04-17 02:20:36 +04:00
/*
* We only want to pull the item from the AIL if it is
* actually there and its location in the log has not
* changed since we started the flush . Thus , we only bother
* if the ili_logged flag is set and the inode ' s lsn has not
* changed . First we check the lsn outside
* the lock since it ' s cheaper , and then we recheck while
* holding the lock before removing the inode from the AIL .
*/
2010-12-20 04:03:17 +03:00
if ( need_ail ) {
struct xfs_log_item * log_items [ need_ail ] ;
int i = 0 ;
2008-10-30 09:39:58 +03:00
spin_lock ( & ailp - > xa_lock ) ;
2010-12-20 04:03:17 +03:00
for ( blip = lip ; blip ; blip = blip - > li_bio_list ) {
iip = INODE_ITEM ( blip ) ;
if ( iip - > ili_logged & &
blip - > li_lsn = = iip - > ili_flush_lsn ) {
log_items [ i + + ] = blip ;
}
ASSERT ( i < = need_ail ) ;
2005-04-17 02:20:36 +04:00
}
2010-12-20 04:03:17 +03:00
/* xfs_trans_ail_delete_bulk() drops the AIL lock. */
xfs_trans_ail_delete_bulk ( ailp , log_items , i ) ;
2005-04-17 02:20:36 +04:00
}
/*
2010-12-20 04:03:17 +03:00
* clean up and unlock the flush lock now we are done . We can clear the
* ili_last_fields bits now that we know that the data corresponding to
* them is safely on disk .
2005-04-17 02:20:36 +04:00
*/
2010-12-20 04:03:17 +03:00
for ( blip = lip ; blip ; blip = next ) {
next = blip - > li_bio_list ;
blip - > li_bio_list = NULL ;
iip = INODE_ITEM ( blip ) ;
iip - > ili_logged = 0 ;
iip - > ili_last_fields = 0 ;
xfs_ifunlock ( iip - > ili_inode ) ;
}
2005-04-17 02:20:36 +04:00
}
/*
* This is the inode flushing abort routine . It is called
* from xfs_iflush when the filesystem is shutting down to clean
* up the inode state .
* It is responsible for removing the inode item
* from the AIL if it has not been re - logged , and unlocking the inode ' s
* flush lock .
*/
void
xfs_iflush_abort (
xfs_inode_t * ip )
{
2008-10-30 09:39:58 +03:00
xfs_inode_log_item_t * iip = ip - > i_itemp ;
2005-04-17 02:20:36 +04:00
iip = ip - > i_itemp ;
if ( iip ) {
2008-10-30 09:39:58 +03:00
struct xfs_ail * ailp = iip - > ili_item . li_ailp ;
2005-04-17 02:20:36 +04:00
if ( iip - > ili_item . li_flags & XFS_LI_IN_AIL ) {
2008-10-30 09:39:58 +03:00
spin_lock ( & ailp - > xa_lock ) ;
2005-04-17 02:20:36 +04:00
if ( iip - > ili_item . li_flags & XFS_LI_IN_AIL ) {
2008-10-30 09:39:58 +03:00
/* xfs_trans_ail_delete() drops the AIL lock. */
xfs_trans_ail_delete ( ailp , ( xfs_log_item_t * ) iip ) ;
2005-04-17 02:20:36 +04:00
} else
2008-10-30 09:39:58 +03:00
spin_unlock ( & ailp - > xa_lock ) ;
2005-04-17 02:20:36 +04:00
}
iip - > ili_logged = 0 ;
/*
* Clear the ili_last_fields bits now that we know that the
* data corresponding to them is safely on disk .
*/
iip - > ili_last_fields = 0 ;
/*
* Clear the inode logging fields so no more flushes are
* attempted .
*/
iip - > ili_format . ilf_fields = 0 ;
}
/*
* Release the inode ' s flush lock since we ' re done with it .
*/
xfs_ifunlock ( ip ) ;
}
void
xfs_istale_done (
2010-06-23 12:11:15 +04:00
struct xfs_buf * bp ,
struct xfs_log_item * lip )
2005-04-17 02:20:36 +04:00
{
2010-06-23 12:11:15 +04:00
xfs_iflush_abort ( INODE_ITEM ( lip ) - > ili_inode ) ;
2005-04-17 02:20:36 +04:00
}
2006-06-09 08:55:38 +04:00
/*
* convert an xfs_inode_log_format struct from either 32 or 64 bit versions
* ( which can have different field alignments ) to the native version
*/
int
xfs_inode_item_format_convert (
xfs_log_iovec_t * buf ,
xfs_inode_log_format_t * in_f )
{
if ( buf - > i_len = = sizeof ( xfs_inode_log_format_32_t ) ) {
2010-06-23 12:11:15 +04:00
xfs_inode_log_format_32_t * in_f32 = buf - > i_addr ;
2006-06-09 08:55:38 +04:00
in_f - > ilf_type = in_f32 - > ilf_type ;
in_f - > ilf_size = in_f32 - > ilf_size ;
in_f - > ilf_fields = in_f32 - > ilf_fields ;
in_f - > ilf_asize = in_f32 - > ilf_asize ;
in_f - > ilf_dsize = in_f32 - > ilf_dsize ;
in_f - > ilf_ino = in_f32 - > ilf_ino ;
/* copy biggest field of ilf_u */
memcpy ( in_f - > ilf_u . ilfu_uuid . __u_bits ,
in_f32 - > ilf_u . ilfu_uuid . __u_bits ,
sizeof ( uuid_t ) ) ;
in_f - > ilf_blkno = in_f32 - > ilf_blkno ;
in_f - > ilf_len = in_f32 - > ilf_len ;
in_f - > ilf_boffset = in_f32 - > ilf_boffset ;
return 0 ;
} else if ( buf - > i_len = = sizeof ( xfs_inode_log_format_64_t ) ) {
2010-06-23 12:11:15 +04:00
xfs_inode_log_format_64_t * in_f64 = buf - > i_addr ;
2006-06-09 08:55:38 +04:00
in_f - > ilf_type = in_f64 - > ilf_type ;
in_f - > ilf_size = in_f64 - > ilf_size ;
in_f - > ilf_fields = in_f64 - > ilf_fields ;
in_f - > ilf_asize = in_f64 - > ilf_asize ;
in_f - > ilf_dsize = in_f64 - > ilf_dsize ;
in_f - > ilf_ino = in_f64 - > ilf_ino ;
/* copy biggest field of ilf_u */
memcpy ( in_f - > ilf_u . ilfu_uuid . __u_bits ,
in_f64 - > ilf_u . ilfu_uuid . __u_bits ,
sizeof ( uuid_t ) ) ;
in_f - > ilf_blkno = in_f64 - > ilf_blkno ;
in_f - > ilf_len = in_f64 - > ilf_len ;
in_f - > ilf_boffset = in_f64 - > ilf_boffset ;
return 0 ;
}
return EFSCORRUPTED ;
}