2005-12-16 01:31:24 +03:00
/* -*- mode: c; c-basic-offset: 8; -*-
* vim : noexpandtab sw = 8 ts = 8 sts = 0 :
*
* inode . c
*
* vfs ' aops , fops , dops and iops
*
* Copyright ( C ) 2002 , 2004 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 as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* 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 .
*/
# include <linux/fs.h>
# include <linux/types.h>
# include <linux/highmem.h>
# include <linux/pagemap.h>
2008-10-09 21:38:40 +04:00
# include <linux/quotaops.h>
2017-12-11 14:35:17 +03:00
# include <linux/iversion.h>
2005-12-16 01:31:24 +03:00
# include <asm/byteorder.h>
# include <cluster/masklog.h>
# include "ocfs2.h"
# include "alloc.h"
2008-11-13 03:27:44 +03:00
# include "dir.h"
2008-10-18 01:55:01 +04:00
# include "blockcheck.h"
2005-12-16 01:31:24 +03:00
# include "dlmglue.h"
# include "extent_map.h"
# include "file.h"
2006-02-23 04:35:08 +03:00
# include "heartbeat.h"
2005-12-16 01:31:24 +03:00
# include "inode.h"
# include "journal.h"
# include "namei.h"
# include "suballoc.h"
# include "super.h"
# include "symlink.h"
# include "sysfile.h"
# include "uptodate.h"
2008-08-18 13:11:00 +04:00
# include "xattr.h"
2009-08-18 07:43:49 +04:00
# include "refcounttree.h"
2011-02-22 17:24:57 +03:00
# include "ocfs2_trace.h"
2016-03-23 00:24:30 +03:00
# include "filecheck.h"
2005-12-16 01:31:24 +03:00
# include "buffer_head_io.h"
struct ocfs2_find_inode_args
{
u64 fi_blkno ;
unsigned long fi_ino ;
unsigned int fi_flags ;
2008-01-11 02:11:45 +03:00
unsigned int fi_sysfile_type ;
2005-12-16 01:31:24 +03:00
} ;
2008-01-11 02:11:45 +03:00
static struct lock_class_key ocfs2_sysfile_lock_key [ NUM_SYSTEM_INODES ] ;
2005-12-16 01:31:24 +03:00
static int ocfs2_read_locked_inode ( struct inode * inode ,
struct ocfs2_find_inode_args * args ) ;
static int ocfs2_init_locked_inode ( struct inode * inode , void * opaque ) ;
static int ocfs2_find_actor ( struct inode * inode , void * opaque ) ;
static int ocfs2_truncate_for_delete ( struct ocfs2_super * osb ,
struct inode * inode ,
struct buffer_head * fe_bh ) ;
2016-03-23 00:24:30 +03:00
static int ocfs2_filecheck_read_inode_block_full ( struct inode * inode ,
struct buffer_head * * bh ,
int flags , int type ) ;
static int ocfs2_filecheck_validate_inode_block ( struct super_block * sb ,
struct buffer_head * bh ) ;
static int ocfs2_filecheck_repair_inode_block ( struct super_block * sb ,
struct buffer_head * bh ) ;
2006-07-04 04:27:12 +04:00
void ocfs2_set_inode_flags ( struct inode * inode )
{
unsigned int flags = OCFS2_I ( inode ) - > ip_attr ;
inode - > i_flags & = ~ ( S_IMMUTABLE |
S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC ) ;
if ( flags & OCFS2_IMMUTABLE_FL )
inode - > i_flags | = S_IMMUTABLE ;
if ( flags & OCFS2_SYNC_FL )
inode - > i_flags | = S_SYNC ;
if ( flags & OCFS2_APPEND_FL )
inode - > i_flags | = S_APPEND ;
if ( flags & OCFS2_NOATIME_FL )
inode - > i_flags | = S_NOATIME ;
if ( flags & OCFS2_DIRSYNC_FL )
inode - > i_flags | = S_DIRSYNC ;
}
2007-04-27 22:08:01 +04:00
/* Propagate flags from i_flags to OCFS2_I(inode)->ip_attr */
void ocfs2_get_inode_flags ( struct ocfs2_inode_info * oi )
{
unsigned int flags = oi - > vfs_inode . i_flags ;
oi - > ip_attr & = ~ ( OCFS2_SYNC_FL | OCFS2_APPEND_FL |
OCFS2_IMMUTABLE_FL | OCFS2_NOATIME_FL | OCFS2_DIRSYNC_FL ) ;
if ( flags & S_SYNC )
oi - > ip_attr | = OCFS2_SYNC_FL ;
if ( flags & S_APPEND )
oi - > ip_attr | = OCFS2_APPEND_FL ;
if ( flags & S_IMMUTABLE )
oi - > ip_attr | = OCFS2_IMMUTABLE_FL ;
if ( flags & S_NOATIME )
oi - > ip_attr | = OCFS2_NOATIME_FL ;
if ( flags & S_DIRSYNC )
oi - > ip_attr | = OCFS2_DIRSYNC_FL ;
}
2009-03-06 16:29:10 +03:00
struct inode * ocfs2_ilookup ( struct super_block * sb , u64 blkno )
{
struct ocfs2_find_inode_args args ;
args . fi_blkno = blkno ;
args . fi_flags = 0 ;
args . fi_ino = ino_from_blkno ( sb , blkno ) ;
args . fi_sysfile_type = 0 ;
return ilookup5 ( sb , blkno , ocfs2_find_actor , & args ) ;
}
2008-01-11 02:11:45 +03:00
struct inode * ocfs2_iget ( struct ocfs2_super * osb , u64 blkno , unsigned flags ,
int sysfile_type )
2005-12-16 01:31:24 +03:00
{
2017-07-07 01:36:07 +03:00
int rc = - ESTALE ;
2005-12-16 01:31:24 +03:00
struct inode * inode = NULL ;
struct super_block * sb = osb - > sb ;
struct ocfs2_find_inode_args args ;
2014-04-04 01:46:48 +04:00
journal_t * journal = OCFS2_SB ( sb ) - > journal - > j_journal ;
2005-12-16 01:31:24 +03:00
2011-02-22 17:24:57 +03:00
trace_ocfs2_iget_begin ( ( unsigned long long ) blkno , flags ,
sysfile_type ) ;
2005-12-16 01:31:24 +03:00
/* Ok. By now we've either got the offsets passed to us by the
* caller , or we just pulled them off the bh . Lets do some
* sanity checks to make sure they ' re OK . */
if ( blkno = = 0 ) {
inode = ERR_PTR ( - EINVAL ) ;
mlog_errno ( PTR_ERR ( inode ) ) ;
goto bail ;
}
args . fi_blkno = blkno ;
2006-09-23 04:28:19 +04:00
args . fi_flags = flags ;
2005-12-16 01:31:24 +03:00
args . fi_ino = ino_from_blkno ( sb , blkno ) ;
2008-01-11 02:11:45 +03:00
args . fi_sysfile_type = sysfile_type ;
2005-12-16 01:31:24 +03:00
inode = iget5_locked ( sb , args . fi_ino , ocfs2_find_actor ,
ocfs2_init_locked_inode , & args ) ;
/* inode was *not* in the inode cache. 2.6.x requires
* us to do our own read_inode call and unlock it
* afterwards . */
if ( inode = = NULL ) {
inode = ERR_PTR ( - ENOMEM ) ;
mlog_errno ( PTR_ERR ( inode ) ) ;
goto bail ;
}
2011-02-22 17:24:57 +03:00
trace_ocfs2_iget5_locked ( inode - > i_state ) ;
2011-02-21 06:18:30 +03:00
if ( inode - > i_state & I_NEW ) {
2016-03-23 00:24:30 +03:00
rc = ocfs2_read_locked_inode ( inode , & args ) ;
2011-02-21 06:18:30 +03:00
unlock_new_inode ( inode ) ;
}
2005-12-16 01:31:24 +03:00
if ( is_bad_inode ( inode ) ) {
iput ( inode ) ;
2016-05-27 01:16:16 +03:00
inode = ERR_PTR ( rc ) ;
2005-12-16 01:31:24 +03:00
goto bail ;
}
2014-04-04 01:46:48 +04:00
/*
* Set transaction id ' s of transactions that have to be committed
* to finish f [ data ] sync . We set them to currently running transaction
* as we cannot be sure that the inode or some of its metadata isn ' t
* part of the transaction - the inode could have been reclaimed and
* now it is reread from disk .
*/
if ( journal ) {
transaction_t * transaction ;
tid_t tid ;
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
read_lock ( & journal - > j_state_lock ) ;
if ( journal - > j_running_transaction )
transaction = journal - > j_running_transaction ;
else
transaction = journal - > j_committing_transaction ;
if ( transaction )
tid = transaction - > t_tid ;
else
tid = journal - > j_commit_sequence ;
read_unlock ( & journal - > j_state_lock ) ;
oi - > i_sync_tid = tid ;
oi - > i_datasync_tid = tid ;
}
2005-12-16 01:31:24 +03:00
bail :
if ( ! IS_ERR ( inode ) ) {
2011-02-22 17:24:57 +03:00
trace_ocfs2_iget_end ( inode ,
( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno ) ;
2007-01-04 04:06:59 +03:00
}
2005-12-16 01:31:24 +03:00
return inode ;
}
/*
* here ' s how inodes get read from disk :
* iget5_locked - > find_actor - > OCFS2_FIND_ACTOR
* found ? : return the in - memory inode
* not found ? : get_new_inode - > OCFS2_INIT_LOCKED_INODE
*/
static int ocfs2_find_actor ( struct inode * inode , void * opaque )
{
struct ocfs2_find_inode_args * args = NULL ;
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
int ret = 0 ;
args = opaque ;
mlog_bug_on_msg ( ! inode , " No inode in find actor! \n " ) ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_find_actor ( inode , inode - > i_ino , opaque , args - > fi_blkno ) ;
2005-12-16 01:31:24 +03:00
if ( oi - > ip_blkno ! = args - > fi_blkno )
goto bail ;
ret = 1 ;
bail :
return ret ;
}
/*
* initialize the new inode , but don ' t do anything that would cause
* us to sleep .
* return 0 on success , 1 on failure
*/
static int ocfs2_init_locked_inode ( struct inode * inode , void * opaque )
{
struct ocfs2_find_inode_args * args = opaque ;
2009-06-04 17:26:50 +04:00
static struct lock_class_key ocfs2_quota_ip_alloc_sem_key ,
ocfs2_file_ip_alloc_sem_key ;
2005-12-16 01:31:24 +03:00
inode - > i_ino = args - > fi_ino ;
OCFS2_I ( inode ) - > ip_blkno = args - > fi_blkno ;
2008-01-11 02:11:45 +03:00
if ( args - > fi_sysfile_type ! = 0 )
2016-04-15 22:08:36 +03:00
lockdep_set_class ( & inode - > i_rwsem ,
2008-01-11 02:11:45 +03:00
& ocfs2_sysfile_lock_key [ args - > fi_sysfile_type ] ) ;
2009-06-04 17:26:50 +04:00
if ( args - > fi_sysfile_type = = USER_QUOTA_SYSTEM_INODE | |
args - > fi_sysfile_type = = GROUP_QUOTA_SYSTEM_INODE | |
args - > fi_sysfile_type = = LOCAL_USER_QUOTA_SYSTEM_INODE | |
args - > fi_sysfile_type = = LOCAL_GROUP_QUOTA_SYSTEM_INODE )
lockdep_set_class ( & OCFS2_I ( inode ) - > ip_alloc_sem ,
& ocfs2_quota_ip_alloc_sem_key ) ;
else
lockdep_set_class ( & OCFS2_I ( inode ) - > ip_alloc_sem ,
& ocfs2_file_ip_alloc_sem_key ) ;
2005-12-16 01:31:24 +03:00
return 0 ;
}
2008-11-14 01:49:11 +03:00
void ocfs2_populate_inode ( struct inode * inode , struct ocfs2_dinode * fe ,
int create_ino )
2005-12-16 01:31:24 +03:00
{
struct super_block * sb ;
struct ocfs2_super * osb ;
2008-07-22 01:29:16 +04:00
int use_plocks = 1 ;
2005-12-16 01:31:24 +03:00
sb = inode - > i_sb ;
osb = OCFS2_SB ( sb ) ;
2008-07-22 01:29:16 +04:00
if ( ( osb - > s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS ) | |
ocfs2_mount_local ( osb ) | | ! ocfs2_stack_supports_plocks ( ) )
use_plocks = 0 ;
2008-11-14 01:49:11 +03:00
/*
* These have all been checked by ocfs2_read_inode_block ( ) or set
* by ocfs2_mknod_locked ( ) , so a failure is a code bug .
*/
BUG_ON ( ! OCFS2_IS_VALID_DINODE ( fe ) ) ; /* This means that read_inode
cannot create a superblock
inode today . change if
that is needed . */
BUG_ON ( ! ( fe - > i_flags & cpu_to_le32 ( OCFS2_VALID_FL ) ) ) ;
BUG_ON ( le32_to_cpu ( fe - > i_fs_generation ) ! = osb - > fs_generation ) ;
2005-12-16 01:31:24 +03:00
2007-03-23 02:53:23 +03:00
OCFS2_I ( inode ) - > ip_clusters = le32_to_cpu ( fe - > i_clusters ) ;
OCFS2_I ( inode ) - > ip_attr = le32_to_cpu ( fe - > i_attr ) ;
2007-09-08 00:58:15 +04:00
OCFS2_I ( inode ) - > ip_dyn_features = le16_to_cpu ( fe - > i_dyn_features ) ;
2007-03-23 02:53:23 +03:00
2017-12-11 14:35:17 +03:00
inode_set_iversion ( inode , 1 ) ;
2005-12-16 01:31:24 +03:00
inode - > i_generation = le32_to_cpu ( fe - > i_generation ) ;
inode - > i_rdev = huge_decode_dev ( le64_to_cpu ( fe - > id1 . dev1 . i_rdev ) ) ;
inode - > i_mode = le16_to_cpu ( fe - > i_mode ) ;
2013-02-01 05:27:11 +04:00
i_uid_write ( inode , le32_to_cpu ( fe - > i_uid ) ) ;
i_gid_write ( inode , le32_to_cpu ( fe - > i_gid ) ) ;
2005-12-16 01:31:24 +03:00
/* Fast symlinks will have i_size but no allocated clusters. */
2012-05-03 18:14:29 +04:00
if ( S_ISLNK ( inode - > i_mode ) & & ! fe - > i_clusters ) {
2005-12-16 01:31:24 +03:00
inode - > i_blocks = 0 ;
2012-05-03 18:14:29 +04:00
inode - > i_mapping - > a_ops = & ocfs2_fast_symlink_aops ;
} else {
2007-03-23 02:53:23 +03:00
inode - > i_blocks = ocfs2_inode_sector_count ( inode ) ;
2012-05-03 18:14:29 +04:00
inode - > i_mapping - > a_ops = & ocfs2_aops ;
}
2005-12-16 01:31:24 +03:00
inode - > i_atime . tv_sec = le64_to_cpu ( fe - > i_atime ) ;
inode - > i_atime . tv_nsec = le32_to_cpu ( fe - > i_atime_nsec ) ;
inode - > i_mtime . tv_sec = le64_to_cpu ( fe - > i_mtime ) ;
inode - > i_mtime . tv_nsec = le32_to_cpu ( fe - > i_mtime_nsec ) ;
inode - > i_ctime . tv_sec = le64_to_cpu ( fe - > i_ctime ) ;
inode - > i_ctime . tv_nsec = le32_to_cpu ( fe - > i_ctime_nsec ) ;
if ( OCFS2_I ( inode ) - > ip_blkno ! = le64_to_cpu ( fe - > i_blkno ) )
mlog ( ML_ERROR ,
2006-03-03 21:24:33 +03:00
" ip_blkno %llu != i_blkno %llu! \n " ,
( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno ,
2007-04-28 03:01:25 +04:00
( unsigned long long ) le64_to_cpu ( fe - > i_blkno ) ) ;
2005-12-16 01:31:24 +03:00
2011-10-28 16:13:29 +04:00
set_nlink ( inode , ocfs2_read_links_count ( fe ) ) ;
2005-12-16 01:31:24 +03:00
2011-02-22 17:24:57 +03:00
trace_ocfs2_populate_inode ( OCFS2_I ( inode ) - > ip_blkno ,
le32_to_cpu ( fe - > i_flags ) ) ;
2008-08-21 20:22:30 +04:00
if ( fe - > i_flags & cpu_to_le32 ( OCFS2_SYSTEM_FL ) ) {
2006-09-23 04:28:19 +04:00
OCFS2_I ( inode ) - > ip_flags | = OCFS2_INODE_SYSTEM_FILE ;
2008-08-21 20:22:30 +04:00
inode - > i_flags | = S_NOQUOTA ;
}
2011-02-22 17:24:57 +03:00
2005-12-16 01:31:24 +03:00
if ( fe - > i_flags & cpu_to_le32 ( OCFS2_LOCAL_ALLOC_FL ) ) {
OCFS2_I ( inode ) - > ip_flags | = OCFS2_INODE_BITMAP ;
} else if ( fe - > i_flags & cpu_to_le32 ( OCFS2_BITMAP_FL ) ) {
OCFS2_I ( inode ) - > ip_flags | = OCFS2_INODE_BITMAP ;
2008-08-20 17:43:36 +04:00
} else if ( fe - > i_flags & cpu_to_le32 ( OCFS2_QUOTA_FL ) ) {
inode - > i_flags | = S_NOQUOTA ;
2005-12-16 01:31:24 +03:00
} else if ( fe - > i_flags & cpu_to_le32 ( OCFS2_SUPER_BLOCK_FL ) ) {
/* we can't actually hit this as read_inode can't
* handle superblocks today ; - ) */
BUG ( ) ;
}
switch ( inode - > i_mode & S_IFMT ) {
case S_IFREG :
2008-07-22 01:29:16 +04:00
if ( use_plocks )
inode - > i_fop = & ocfs2_fops ;
else
inode - > i_fop = & ocfs2_fops_no_plocks ;
2005-12-16 01:31:24 +03:00
inode - > i_op = & ocfs2_file_iops ;
i_size_write ( inode , le64_to_cpu ( fe - > i_size ) ) ;
break ;
case S_IFDIR :
inode - > i_op = & ocfs2_dir_iops ;
2008-07-22 01:29:16 +04:00
if ( use_plocks )
inode - > i_fop = & ocfs2_dops ;
else
inode - > i_fop = & ocfs2_dops_no_plocks ;
2005-12-16 01:31:24 +03:00
i_size_write ( inode , le64_to_cpu ( fe - > i_size ) ) ;
2010-06-28 19:04:32 +04:00
OCFS2_I ( inode ) - > ip_dir_lock_gen = 1 ;
2005-12-16 01:31:24 +03:00
break ;
case S_IFLNK :
2012-05-03 18:14:29 +04:00
inode - > i_op = & ocfs2_symlink_inode_operations ;
2015-11-17 09:07:57 +03:00
inode_nohighmem ( inode ) ;
2005-12-16 01:31:24 +03:00
i_size_write ( inode , le64_to_cpu ( fe - > i_size ) ) ;
break ;
default :
inode - > i_op = & ocfs2_special_file_iops ;
init_special_inode ( inode , inode - > i_mode ,
inode - > i_rdev ) ;
break ;
}
2006-09-23 04:28:19 +04:00
if ( create_ino ) {
inode - > i_ino = ino_from_blkno ( inode - > i_sb ,
le64_to_cpu ( fe - > i_blkno ) ) ;
/*
* If we ever want to create system files from kernel ,
* the generation argument to
* ocfs2_inode_lock_res_init ( ) will have to change .
*/
2007-04-28 03:01:25 +04:00
BUG_ON ( le32_to_cpu ( fe - > i_flags ) & OCFS2_SYSTEM_FL ) ;
2006-09-23 04:28:19 +04:00
2007-10-19 02:30:42 +04:00
ocfs2_inode_lock_res_init ( & OCFS2_I ( inode ) - > ip_inode_lockres ,
2006-09-23 04:28:19 +04:00
OCFS2_LOCK_TYPE_META , 0 , inode ) ;
2007-03-21 02:01:38 +03:00
ocfs2_inode_lock_res_init ( & OCFS2_I ( inode ) - > ip_open_lockres ,
OCFS2_LOCK_TYPE_OPEN , 0 , inode ) ;
2006-09-23 04:28:19 +04:00
}
2005-12-16 01:31:24 +03:00
ocfs2_inode_lock_res_init ( & OCFS2_I ( inode ) - > ip_rw_lockres ,
2006-09-23 04:28:19 +04:00
OCFS2_LOCK_TYPE_RW , inode - > i_generation ,
inode ) ;
2006-07-04 04:27:12 +04:00
ocfs2_set_inode_flags ( inode ) ;
2009-02-24 19:53:23 +03:00
OCFS2_I ( inode ) - > ip_last_used_slot = 0 ;
OCFS2_I ( inode ) - > ip_last_used_group = 0 ;
2009-12-08 00:16:07 +03:00
if ( S_ISDIR ( inode - > i_mode ) )
ocfs2_resv_set_type ( & OCFS2_I ( inode ) - > ip_la_data_resv ,
OCFS2_RESV_FLAG_DIR ) ;
2005-12-16 01:31:24 +03:00
}
static int ocfs2_read_locked_inode ( struct inode * inode ,
struct ocfs2_find_inode_args * args )
{
struct super_block * sb ;
struct ocfs2_super * osb ;
struct ocfs2_dinode * fe ;
struct buffer_head * bh = NULL ;
2016-03-23 00:24:30 +03:00
int status , can_lock , lock_level = 0 ;
2006-09-23 04:28:19 +04:00
u32 generation = 0 ;
2005-12-16 01:31:24 +03:00
status = - EINVAL ;
sb = inode - > i_sb ;
osb = OCFS2_SB ( sb ) ;
2006-09-23 04:28:19 +04:00
/*
* To improve performance of cold - cache inode stats , we take
* the cluster lock here if possible .
*
* Generally , OCFS2 never trusts the contents of an inode
* unless it ' s holding a cluster lock , so taking it here isn ' t
* a correctness issue as much as it is a performance
* improvement .
*
* There are three times when taking the lock is not a good idea :
*
* 1 ) During startup , before we have initialized the DLM .
*
* 2 ) If we are reading certain system files which never get
* cluster locks ( local alloc , truncate log ) .
*
* 3 ) If the process doing the iget ( ) is responsible for
* orphan dir recovery . We ' re holding the orphan dir lock and
* can get into a deadlock with another process on another
* node in - > delete_inode ( ) .
*
* # 1 and # 2 can be simply solved by never taking the lock
* here for system files ( which are the only type we read
* during mount ) . It ' s a heavier approach , but our main
tree-wide: fix comment/printk typos
"gadget", "through", "command", "maintain", "maintain", "controller", "address",
"between", "initiali[zs]e", "instead", "function", "select", "already",
"equal", "access", "management", "hierarchy", "registration", "interest",
"relative", "memory", "offset", "already",
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2010-11-01 22:38:34 +03:00
* concern is user - accessible files anyway .
2006-09-23 04:28:19 +04:00
*
* # 3 works itself out because we ' ll eventually take the
* cluster lock before trusting anything anyway .
*/
can_lock = ! ( args - > fi_flags & OCFS2_FI_FLAG_SYSFILE )
2007-03-21 02:01:38 +03:00
& & ! ( args - > fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY )
2006-12-06 04:56:35 +03:00
& & ! ocfs2_mount_local ( osb ) ;
2006-09-23 04:28:19 +04:00
2011-02-22 17:24:57 +03:00
trace_ocfs2_read_locked_inode (
( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno , can_lock ) ;
2006-09-23 04:28:19 +04:00
/*
* To maintain backwards compatibility with older versions of
* ocfs2 - tools , we still store the generation value for system
* files . The only ones that actually matter to userspace are
* the journals , but it ' s easier and inexpensive to just flag
* all system files similarly .
*/
if ( args - > fi_flags & OCFS2_FI_FLAG_SYSFILE )
generation = osb - > fs_generation ;
2007-10-19 02:30:42 +04:00
ocfs2_inode_lock_res_init ( & OCFS2_I ( inode ) - > ip_inode_lockres ,
2006-09-23 04:28:19 +04:00
OCFS2_LOCK_TYPE_META ,
generation , inode ) ;
2007-03-21 02:01:38 +03:00
ocfs2_inode_lock_res_init ( & OCFS2_I ( inode ) - > ip_open_lockres ,
OCFS2_LOCK_TYPE_OPEN ,
0 , inode ) ;
2006-09-23 04:28:19 +04:00
if ( can_lock ) {
2007-03-21 02:01:38 +03:00
status = ocfs2_open_lock ( inode ) ;
if ( status ) {
make_bad_inode ( inode ) ;
mlog_errno ( status ) ;
return status ;
}
2016-03-23 00:24:30 +03:00
status = ocfs2_inode_lock ( inode , NULL , lock_level ) ;
2006-09-23 04:28:19 +04:00
if ( status ) {
make_bad_inode ( inode ) ;
mlog_errno ( status ) ;
return status ;
}
2005-12-16 01:31:24 +03:00
}
2007-03-21 02:01:38 +03:00
if ( args - > fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY ) {
status = ocfs2_try_open_lock ( inode , 0 ) ;
if ( status ) {
2010-01-26 03:57:38 +03:00
make_bad_inode ( inode ) ;
2007-03-21 02:01:38 +03:00
return status ;
}
}
2008-11-14 01:49:11 +03:00
if ( can_lock ) {
2016-03-23 00:24:30 +03:00
if ( args - > fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK )
status = ocfs2_filecheck_read_inode_block_full ( inode ,
& bh , OCFS2_BH_IGNORE_CACHE , 0 ) ;
else if ( args - > fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX )
status = ocfs2_filecheck_read_inode_block_full ( inode ,
& bh , OCFS2_BH_IGNORE_CACHE , 1 ) ;
else
status = ocfs2_read_inode_block_full ( inode ,
& bh , OCFS2_BH_IGNORE_CACHE ) ;
2008-11-14 01:49:11 +03:00
} else {
2008-10-10 04:20:29 +04:00
status = ocfs2_read_blocks_sync ( osb , args - > fi_blkno , 1 , & bh ) ;
2010-08-13 03:24:26 +04:00
/*
* If buffer is in jbd , then its checksum may not have been
* computed as yet .
*/
2016-03-23 00:24:30 +03:00
if ( ! status & & ! buffer_jbd ( bh ) ) {
if ( args - > fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK )
status = ocfs2_filecheck_validate_inode_block (
osb - > sb , bh ) ;
else if ( args - > fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX )
status = ocfs2_filecheck_repair_inode_block (
osb - > sb , bh ) ;
else
status = ocfs2_validate_inode_block (
osb - > sb , bh ) ;
}
2008-11-14 01:49:11 +03:00
}
2005-12-16 01:31:24 +03:00
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail ;
}
2006-09-23 04:28:19 +04:00
status = - EINVAL ;
2005-12-16 01:31:24 +03:00
fe = ( struct ocfs2_dinode * ) bh - > b_data ;
2006-09-23 04:28:19 +04:00
/*
* This is a code bug . Right now the caller needs to
* understand whether it is asking for a system file inode or
* not so the proper lock names can be built .
*/
mlog_bug_on_msg ( ! ! ( fe - > i_flags & cpu_to_le32 ( OCFS2_SYSTEM_FL ) ) ! =
! ! ( args - > fi_flags & OCFS2_FI_FLAG_SYSFILE ) ,
" Inode %llu: system file state is ambigous \n " ,
( unsigned long long ) args - > fi_blkno ) ;
2005-12-16 01:31:24 +03:00
if ( S_ISCHR ( le16_to_cpu ( fe - > i_mode ) ) | |
S_ISBLK ( le16_to_cpu ( fe - > i_mode ) ) )
2008-11-14 01:49:11 +03:00
inode - > i_rdev = huge_decode_dev ( le64_to_cpu ( fe - > id1 . dev1 . i_rdev ) ) ;
2005-12-16 01:31:24 +03:00
2008-11-14 01:49:11 +03:00
ocfs2_populate_inode ( inode , fe , 0 ) ;
2005-12-16 01:31:24 +03:00
BUG_ON ( args - > fi_blkno ! = le64_to_cpu ( fe - > i_blkno ) ) ;
2016-03-23 00:24:30 +03:00
if ( buffer_dirty ( bh ) & & ! buffer_jbd ( bh ) ) {
if ( can_lock ) {
ocfs2_inode_unlock ( inode , lock_level ) ;
lock_level = 1 ;
ocfs2_inode_lock ( inode , NULL , lock_level ) ;
}
status = ocfs2_write_block ( osb , bh , INODE_CACHE ( inode ) ) ;
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail ;
}
}
2005-12-16 01:31:24 +03:00
status = 0 ;
bail :
2006-09-23 04:28:19 +04:00
if ( can_lock )
2016-03-23 00:24:30 +03:00
ocfs2_inode_unlock ( inode , lock_level ) ;
2006-09-23 04:28:19 +04:00
if ( status < 0 )
make_bad_inode ( inode ) ;
2014-12-11 02:41:42 +03:00
brelse ( bh ) ;
2005-12-16 01:31:24 +03:00
return status ;
}
void ocfs2_sync_blockdev ( struct super_block * sb )
{
sync_blockdev ( sb - > s_bdev ) ;
}
static int ocfs2_truncate_for_delete ( struct ocfs2_super * osb ,
struct inode * inode ,
struct buffer_head * fe_bh )
{
int status = 0 ;
struct ocfs2_dinode * fe ;
2007-02-16 22:46:50 +03:00
handle_t * handle = NULL ;
2005-12-16 01:31:24 +03:00
fe = ( struct ocfs2_dinode * ) fe_bh - > b_data ;
2007-09-08 01:46:51 +04:00
/*
* This check will also skip truncate of inodes with inline
* data and fast symlinks .
*/
2007-01-17 23:53:31 +03:00
if ( fe - > i_clusters ) {
2008-09-04 07:03:41 +04:00
if ( ocfs2_should_order_data ( inode ) )
ocfs2_begin_ordered_truncate ( inode , 0 ) ;
2007-02-16 22:46:50 +03:00
handle = ocfs2_start_trans ( osb , OCFS2_INODE_UPDATE_CREDITS ) ;
if ( IS_ERR ( handle ) ) {
status = PTR_ERR ( handle ) ;
2010-04-22 13:39:29 +04:00
handle = NULL ;
2007-02-16 22:46:50 +03:00
mlog_errno ( status ) ;
goto out ;
}
2009-02-13 03:41:25 +03:00
status = ocfs2_journal_access_di ( handle , INODE_CACHE ( inode ) ,
fe_bh ,
2008-10-18 06:25:01 +04:00
OCFS2_JOURNAL_ACCESS_WRITE ) ;
2007-02-16 22:46:50 +03:00
if ( status < 0 ) {
mlog_errno ( status ) ;
goto out ;
}
i_size_write ( inode , 0 ) ;
status = ocfs2_mark_inode_dirty ( handle , inode , fe_bh ) ;
if ( status < 0 ) {
mlog_errno ( status ) ;
goto out ;
}
ocfs2_commit_trans ( osb , handle ) ;
handle = NULL ;
2010-05-11 13:54:42 +04:00
status = ocfs2_commit_truncate ( osb , inode , fe_bh ) ;
2018-08-18 01:44:27 +03:00
if ( status < 0 )
2007-01-17 23:53:31 +03:00
mlog_errno ( status ) ;
2005-12-16 01:31:24 +03:00
}
2007-02-16 22:46:50 +03:00
out :
if ( handle )
ocfs2_commit_trans ( osb , handle ) ;
2005-12-16 01:31:24 +03:00
return status ;
}
static int ocfs2_remove_inode ( struct inode * inode ,
struct buffer_head * di_bh ,
struct inode * orphan_dir_inode ,
struct buffer_head * orphan_dir_bh )
{
int status ;
struct inode * inode_alloc_inode = NULL ;
struct buffer_head * inode_alloc_bh = NULL ;
2006-10-10 05:11:45 +04:00
handle_t * handle ;
2005-12-16 01:31:24 +03:00
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
struct ocfs2_dinode * di = ( struct ocfs2_dinode * ) di_bh - > b_data ;
inode_alloc_inode =
ocfs2_get_system_file_inode ( osb , INODE_ALLOC_SYSTEM_INODE ,
le16_to_cpu ( di - > i_suballoc_slot ) ) ;
if ( ! inode_alloc_inode ) {
2015-04-15 01:43:24 +03:00
status = - ENOENT ;
2005-12-16 01:31:24 +03:00
mlog_errno ( status ) ;
goto bail ;
}
2016-01-22 23:40:57 +03:00
inode_lock ( inode_alloc_inode ) ;
2007-10-19 02:30:42 +04:00
status = ocfs2_inode_lock ( inode_alloc_inode , & inode_alloc_bh , 1 ) ;
2005-12-16 01:31:24 +03:00
if ( status < 0 ) {
2016-01-22 23:40:57 +03:00
inode_unlock ( inode_alloc_inode ) ;
2005-12-16 01:31:24 +03:00
mlog_errno ( status ) ;
goto bail ;
}
2008-10-09 21:38:40 +04:00
handle = ocfs2_start_trans ( osb , OCFS2_DELETE_INODE_CREDITS +
2008-11-13 03:27:44 +03:00
ocfs2_quota_trans_credits ( inode - > i_sb ) ) ;
2005-12-16 01:31:24 +03:00
if ( IS_ERR ( handle ) ) {
status = PTR_ERR ( handle ) ;
mlog_errno ( status ) ;
goto bail_unlock ;
}
2010-04-22 12:11:19 +04:00
if ( ! ( OCFS2_I ( inode ) - > ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR ) ) {
status = ocfs2_orphan_del ( osb , handle , orphan_dir_inode , inode ,
2015-02-17 02:59:54 +03:00
orphan_dir_bh , false ) ;
2010-04-22 12:11:19 +04:00
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail_commit ;
}
2005-12-16 01:31:24 +03:00
}
/* set the inodes dtime */
2009-02-13 03:41:25 +03:00
status = ocfs2_journal_access_di ( handle , INODE_CACHE ( inode ) , di_bh ,
2008-10-18 06:25:01 +04:00
OCFS2_JOURNAL_ACCESS_WRITE ) ;
2005-12-16 01:31:24 +03:00
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail_commit ;
}
2016-12-13 03:41:26 +03:00
di - > i_dtime = cpu_to_le64 ( ktime_get_real_seconds ( ) ) ;
2007-12-25 17:52:59 +03:00
di - > i_flags & = cpu_to_le32 ( ~ ( OCFS2_VALID_FL | OCFS2_ORPHANED_FL ) ) ;
2010-03-20 00:13:52 +03:00
ocfs2_journal_dirty ( handle , di_bh ) ;
2005-12-16 01:31:24 +03:00
2009-02-11 07:00:41 +03:00
ocfs2_remove_from_cache ( INODE_CACHE ( inode ) , di_bh ) ;
2010-03-03 17:05:01 +03:00
dquot_free_inode ( inode ) ;
2005-12-16 01:31:24 +03:00
status = ocfs2_free_dinode ( handle , inode_alloc_inode ,
inode_alloc_bh , di ) ;
if ( status < 0 )
mlog_errno ( status ) ;
bail_commit :
2006-10-10 03:48:10 +04:00
ocfs2_commit_trans ( osb , handle ) ;
2005-12-16 01:31:24 +03:00
bail_unlock :
2007-10-19 02:30:42 +04:00
ocfs2_inode_unlock ( inode_alloc_inode , 1 ) ;
2016-01-22 23:40:57 +03:00
inode_unlock ( inode_alloc_inode ) ;
2005-12-16 01:31:24 +03:00
brelse ( inode_alloc_bh ) ;
bail :
iput ( inode_alloc_inode ) ;
return status ;
}
2010-01-26 03:57:38 +03:00
/*
2006-02-23 04:35:08 +03:00
* Serialize with orphan dir recovery . If the process doing
* recovery on this orphan dir does an iget ( ) with the dir
* i_mutex held , we ' ll deadlock here . Instead we detect this
* and exit early - recovery will wipe this inode for us .
*/
static int ocfs2_check_orphan_recovery_state ( struct ocfs2_super * osb ,
int slot )
{
int ret = 0 ;
spin_lock ( & osb - > osb_lock ) ;
if ( ocfs2_node_map_test_bit ( osb , & osb - > osb_recovering_orphan_dirs , slot ) ) {
ret = - EDEADLK ;
goto out ;
}
/* This signals to the orphan recovery process that it should
* wait for us to handle the wipe . */
osb - > osb_orphan_wipes [ slot ] + + ;
out :
spin_unlock ( & osb - > osb_lock ) ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_check_orphan_recovery_state ( slot , ret ) ;
2006-02-23 04:35:08 +03:00
return ret ;
}
static void ocfs2_signal_wipe_completion ( struct ocfs2_super * osb ,
int slot )
{
spin_lock ( & osb - > osb_lock ) ;
osb - > osb_orphan_wipes [ slot ] - - ;
spin_unlock ( & osb - > osb_lock ) ;
wake_up ( & osb - > osb_wipe_event ) ;
}
2005-12-16 01:31:24 +03:00
static int ocfs2_wipe_inode ( struct inode * inode ,
struct buffer_head * di_bh )
{
2010-05-04 06:15:49 +04:00
int status , orphaned_slot = - 1 ;
2005-12-16 01:31:24 +03:00
struct inode * orphan_dir_inode = NULL ;
struct buffer_head * orphan_dir_bh = NULL ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
2010-04-22 12:11:19 +04:00
struct ocfs2_dinode * di = ( struct ocfs2_dinode * ) di_bh - > b_data ;
2005-12-16 01:31:24 +03:00
2010-04-22 12:11:19 +04:00
if ( ! ( OCFS2_I ( inode ) - > ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR ) ) {
orphaned_slot = le16_to_cpu ( di - > i_orphaned_slot ) ;
2006-02-23 04:35:08 +03:00
2010-04-22 12:11:19 +04:00
status = ocfs2_check_orphan_recovery_state ( osb , orphaned_slot ) ;
if ( status )
return status ;
2006-02-23 04:35:08 +03:00
2010-04-22 12:11:19 +04:00
orphan_dir_inode = ocfs2_get_system_file_inode ( osb ,
ORPHAN_DIR_SYSTEM_INODE ,
orphaned_slot ) ;
if ( ! orphan_dir_inode ) {
2015-04-15 01:43:24 +03:00
status = - ENOENT ;
2010-04-22 12:11:19 +04:00
mlog_errno ( status ) ;
goto bail ;
}
2005-12-16 01:31:24 +03:00
2010-04-22 12:11:19 +04:00
/* Lock the orphan dir. The lock will be held for the entire
* delete_inode operation . We do this now to avoid races with
* recovery completion on other nodes . */
2016-01-22 23:40:57 +03:00
inode_lock ( orphan_dir_inode ) ;
2010-04-22 12:11:19 +04:00
status = ocfs2_inode_lock ( orphan_dir_inode , & orphan_dir_bh , 1 ) ;
if ( status < 0 ) {
2016-01-22 23:40:57 +03:00
inode_unlock ( orphan_dir_inode ) ;
2005-12-16 01:31:24 +03:00
2010-04-22 12:11:19 +04:00
mlog_errno ( status ) ;
goto bail ;
}
2005-12-16 01:31:24 +03:00
}
/* we do this while holding the orphan dir lock because we
2007-09-25 02:56:19 +04:00
* don ' t want recovery being run from another node to try an
* inode delete underneath us - - this will result in two nodes
2005-12-16 01:31:24 +03:00
* truncating the same file ! */
status = ocfs2_truncate_for_delete ( osb , inode , di_bh ) ;
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail_unlock_dir ;
}
2008-11-13 03:27:44 +03:00
/* Remove any dir index tree */
if ( S_ISDIR ( inode - > i_mode ) ) {
status = ocfs2_dx_dir_truncate ( inode , di_bh ) ;
if ( status ) {
mlog_errno ( status ) ;
goto bail_unlock_dir ;
}
}
2008-08-18 13:11:00 +04:00
/*Free extended attribute resources associated with this inode.*/
status = ocfs2_xattr_remove ( inode , di_bh ) ;
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail_unlock_dir ;
}
2009-08-18 07:43:49 +04:00
status = ocfs2_remove_refcount_tree ( inode , di_bh ) ;
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail_unlock_dir ;
}
2005-12-16 01:31:24 +03:00
status = ocfs2_remove_inode ( inode , di_bh , orphan_dir_inode ,
orphan_dir_bh ) ;
if ( status < 0 )
mlog_errno ( status ) ;
bail_unlock_dir :
2010-04-22 12:11:19 +04:00
if ( OCFS2_I ( inode ) - > ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR )
return status ;
2007-10-19 02:30:42 +04:00
ocfs2_inode_unlock ( orphan_dir_inode , 1 ) ;
2016-01-22 23:40:57 +03:00
inode_unlock ( orphan_dir_inode ) ;
2005-12-16 01:31:24 +03:00
brelse ( orphan_dir_bh ) ;
bail :
iput ( orphan_dir_inode ) ;
2006-02-23 04:35:08 +03:00
ocfs2_signal_wipe_completion ( osb , orphaned_slot ) ;
2005-12-16 01:31:24 +03:00
return status ;
}
/* There is a series of simple checks that should be done before a
2007-09-25 02:56:19 +04:00
* trylock is even considered . Encapsulate those in this function . */
2005-12-16 01:31:24 +03:00
static int ocfs2_inode_is_valid_to_delete ( struct inode * inode )
{
int ret = 0 ;
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_inode_is_valid_to_delete ( current , osb - > dc_task ,
( unsigned long long ) oi - > ip_blkno ,
oi - > ip_flags ) ;
2005-12-16 01:31:24 +03:00
/* We shouldn't be getting here for the root directory
* inode . . */
if ( inode = = osb - > root_inode ) {
mlog ( ML_ERROR , " Skipping delete of root inode. \n " ) ;
goto bail ;
}
2014-04-04 01:46:54 +04:00
/*
* If we ' re coming from downconvert_thread we can ' t go into our own
* voting [ hello , deadlock city ! ] so we cannot delete the inode . But
* since we dropped last inode ref when downconverting dentry lock ,
* we cannot have the file open and thus the node doing unlink will
* take care of deleting the inode .
*/
2011-02-22 17:24:57 +03:00
if ( current = = osb - > dc_task )
2005-12-16 01:31:24 +03:00
goto bail ;
spin_lock ( & oi - > ip_lock ) ;
/* OCFS2 *never* deletes system files. This should technically
* never get here as system file inodes should always have a
* positive link count . */
if ( oi - > ip_flags & OCFS2_INODE_SYSTEM_FILE ) {
2006-03-03 21:24:33 +03:00
mlog ( ML_ERROR , " Skipping delete of system file %llu \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2005-12-16 01:31:24 +03:00
goto bail_unlock ;
}
ret = 1 ;
bail_unlock :
spin_unlock ( & oi - > ip_lock ) ;
bail :
return ret ;
}
/* Query the cluster to determine whether we should wipe an inode from
* disk or not .
*
* Requires the inode to have the cluster lock . */
static int ocfs2_query_inode_wipe ( struct inode * inode ,
struct buffer_head * di_bh ,
int * wipe )
{
2011-02-22 17:24:57 +03:00
int status = 0 , reason = 0 ;
2005-12-16 01:31:24 +03:00
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
struct ocfs2_dinode * di ;
* wipe = 0 ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_query_inode_wipe_begin ( ( unsigned long long ) oi - > ip_blkno ,
inode - > i_nlink ) ;
2005-12-16 01:31:24 +03:00
/* While we were waiting for the cluster lock in
* ocfs2_delete_inode , another node might have asked to delete
* the inode . Recheck our flags to catch this . */
if ( ! ocfs2_inode_is_valid_to_delete ( inode ) ) {
2011-02-22 17:24:57 +03:00
reason = 1 ;
2005-12-16 01:31:24 +03:00
goto bail ;
}
/* Now that we have an up to date inode, we can double check
* the link count . */
2011-02-22 17:24:57 +03:00
if ( inode - > i_nlink )
2005-12-16 01:31:24 +03:00
goto bail ;
/* Do some basic inode verification... */
di = ( struct ocfs2_dinode * ) di_bh - > b_data ;
2010-04-22 12:11:19 +04:00
if ( ! ( di - > i_flags & cpu_to_le32 ( OCFS2_ORPHANED_FL ) ) & &
! ( oi - > ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR ) ) {
2010-03-19 04:21:10 +03:00
/*
* Inodes in the orphan dir must have ORPHANED_FL . The only
* inodes that come back out of the orphan dir are reflink
* targets . A reflink target may be moved out of the orphan
* dir between the time we scan the directory and the time we
* process it . This would lead to HAS_REFCOUNT_FL being set but
* ORPHANED_FL not .
*/
if ( di - > i_dyn_features & cpu_to_le16 ( OCFS2_HAS_REFCOUNT_FL ) ) {
2011-02-22 17:24:57 +03:00
reason = 2 ;
2010-03-19 04:21:10 +03:00
goto bail ;
}
2005-12-16 01:31:24 +03:00
/* for lack of a better error? */
status = - EEXIST ;
mlog ( ML_ERROR ,
2006-03-03 21:24:33 +03:00
" Inode %llu (on-disk %llu) not orphaned! "
2005-12-16 01:31:24 +03:00
" Disk flags 0x%x, inode flags 0x%x \n " ,
2006-03-03 21:24:33 +03:00
( unsigned long long ) oi - > ip_blkno ,
2007-04-28 03:01:25 +04:00
( unsigned long long ) le64_to_cpu ( di - > i_blkno ) ,
le32_to_cpu ( di - > i_flags ) , oi - > ip_flags ) ;
2005-12-16 01:31:24 +03:00
goto bail ;
}
/* has someone already deleted us?! baaad... */
if ( di - > i_dtime ) {
status = - EEXIST ;
mlog_errno ( status ) ;
goto bail ;
}
2007-03-21 03:17:54 +03:00
/*
* This is how ocfs2 determines whether an inode is still live
* within the cluster . Every node takes a shared read lock on
* the inode open lock in ocfs2_read_locked_inode ( ) . When we
* get to - > delete_inode ( ) , each node tries to convert it ' s
* lock to an exclusive . Trylocks are serialized by the inode
2011-03-31 05:57:33 +04:00
* meta data lock . If the upconvert succeeds , we know the inode
2007-03-21 03:17:54 +03:00
* is no longer live and can be deleted .
*
* Though we call this with the meta data lock held , the
* trylock keeps us from ABBA deadlock .
*/
status = ocfs2_try_open_lock ( inode , 1 ) ;
2007-03-21 02:01:38 +03:00
if ( status = = - EAGAIN ) {
2005-12-16 01:31:24 +03:00
status = 0 ;
2011-02-22 17:24:57 +03:00
reason = 3 ;
2005-12-16 01:31:24 +03:00
goto bail ;
}
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail ;
}
2007-03-21 02:01:38 +03:00
* wipe = 1 ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_query_inode_wipe_succ ( le16_to_cpu ( di - > i_orphaned_slot ) ) ;
2005-12-16 01:31:24 +03:00
bail :
2011-02-22 17:24:57 +03:00
trace_ocfs2_query_inode_wipe_end ( status , reason ) ;
2005-12-16 01:31:24 +03:00
return status ;
}
/* Support function for ocfs2_delete_inode. Will help us keep the
* inode data in a consistent state for clear_inode . Always truncates
* pages , optionally sync ' s them first . */
static void ocfs2_cleanup_delete_inode ( struct inode * inode ,
int sync_data )
{
2011-02-22 17:24:57 +03:00
trace_ocfs2_cleanup_delete_inode (
( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno , sync_data ) ;
2005-12-16 01:31:24 +03:00
if ( sync_data )
2011-11-08 03:20:39 +04:00
filemap_write_and_wait ( inode - > i_mapping ) ;
2014-04-04 01:47:49 +04:00
truncate_inode_pages_final ( & inode - > i_data ) ;
2005-12-16 01:31:24 +03:00
}
2010-06-09 05:28:10 +04:00
static void ocfs2_delete_inode ( struct inode * inode )
2005-12-16 01:31:24 +03:00
{
int wipe , status ;
2009-09-03 04:17:36 +04:00
sigset_t oldset ;
2005-12-16 01:31:24 +03:00
struct buffer_head * di_bh = NULL ;
2015-09-05 01:44:40 +03:00
struct ocfs2_dinode * di = NULL ;
2005-12-16 01:31:24 +03:00
2011-02-22 17:24:57 +03:00
trace_ocfs2_delete_inode ( inode - > i_ino ,
( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno ,
is_bad_inode ( inode ) ) ;
2005-12-16 01:31:24 +03:00
2008-10-09 21:38:40 +04:00
/* When we fail in read_inode() we mark inode as bad. The second test
* catches the case when inode allocation fails before allocating
* a block for inode . */
2011-02-22 17:24:57 +03:00
if ( is_bad_inode ( inode ) | | ! OCFS2_I ( inode ) - > ip_blkno )
2005-12-16 01:31:24 +03:00
goto bail ;
if ( ! ocfs2_inode_is_valid_to_delete ( inode ) ) {
/* It's probably not necessary to truncate_inode_pages
* here but we do it for safety anyway ( it will most
* likely be a no - op anyway ) */
ocfs2_cleanup_delete_inode ( inode , 0 ) ;
goto bail ;
}
2014-04-04 01:46:54 +04:00
dquot_initialize ( inode ) ;
2005-12-16 01:31:24 +03:00
/* We want to block signals in delete_inode as the lock and
* messaging paths may return us - ERESTARTSYS . Which would
* cause us to exit early , resulting in inodes being orphaned
* forever . */
2009-09-03 04:17:36 +04:00
ocfs2_block_signals ( & oldset ) ;
2005-12-16 01:31:24 +03:00
2009-03-06 16:29:10 +03:00
/*
* Synchronize us against ocfs2_get_dentry . We take this in
* shared mode so that all nodes can still concurrently
* process deletes .
*/
status = ocfs2_nfs_sync_lock ( OCFS2_SB ( inode - > i_sb ) , 0 ) ;
if ( status < 0 ) {
mlog ( ML_ERROR , " getting nfs sync lock(PR) failed %d \n " , status ) ;
ocfs2_cleanup_delete_inode ( inode , 0 ) ;
goto bail_unblock ;
}
2005-12-16 01:31:24 +03:00
/* Lock down the inode. This gives us an up to date view of
* it ' s metadata ( for verification ) , and allows us to
2007-09-25 02:56:19 +04:00
* serialize delete_inode on multiple nodes .
2005-12-16 01:31:24 +03:00
*
* Even though we might be doing a truncate , we don ' t take the
* allocation lock here as it won ' t be needed - nobody will
* have the file open .
*/
2007-10-19 02:30:42 +04:00
status = ocfs2_inode_lock ( inode , & di_bh , 1 ) ;
2005-12-16 01:31:24 +03:00
if ( status < 0 ) {
if ( status ! = - ENOENT )
mlog_errno ( status ) ;
ocfs2_cleanup_delete_inode ( inode , 0 ) ;
2009-03-06 16:29:10 +03:00
goto bail_unlock_nfs_sync ;
2005-12-16 01:31:24 +03:00
}
2015-09-05 01:44:40 +03:00
di = ( struct ocfs2_dinode * ) di_bh - > b_data ;
/* Skip inode deletion and wait for dio orphan entry recovered
* first */
if ( unlikely ( di - > i_flags & cpu_to_le32 ( OCFS2_DIO_ORPHANED_FL ) ) ) {
ocfs2_cleanup_delete_inode ( inode , 0 ) ;
goto bail_unlock_inode ;
}
2005-12-16 01:31:24 +03:00
/* Query the cluster. This will be the final decision made
* before we go ahead and wipe the inode . */
status = ocfs2_query_inode_wipe ( inode , di_bh , & wipe ) ;
if ( ! wipe | | status < 0 ) {
2007-09-25 02:56:19 +04:00
/* Error and remote inode busy both mean we won't be
2005-12-16 01:31:24 +03:00
* removing the inode , so they take almost the same
* path . */
if ( status < 0 )
mlog_errno ( status ) ;
2007-09-25 02:56:19 +04:00
/* Someone in the cluster has disallowed a wipe of
* this inode , or it was never completely
* orphaned . Write out the pages and exit now . */
2005-12-16 01:31:24 +03:00
ocfs2_cleanup_delete_inode ( inode , 1 ) ;
goto bail_unlock_inode ;
}
ocfs2_cleanup_delete_inode ( inode , 0 ) ;
status = ocfs2_wipe_inode ( inode , di_bh ) ;
if ( status < 0 ) {
2006-02-23 04:35:08 +03:00
if ( status ! = - EDEADLK )
mlog_errno ( status ) ;
2005-12-16 01:31:24 +03:00
goto bail_unlock_inode ;
}
2006-09-23 04:28:19 +04:00
/*
* Mark the inode as successfully deleted .
*
* This is important for ocfs2_clear_inode ( ) as it will check
* this flag and skip any checkpointing work
*
* ocfs2_stuff_meta_lvb ( ) also uses this flag to invalidate
* the LVB for other nodes .
*/
2005-12-16 01:31:24 +03:00
OCFS2_I ( inode ) - > ip_flags | = OCFS2_INODE_DELETED ;
bail_unlock_inode :
2007-10-19 02:30:42 +04:00
ocfs2_inode_unlock ( inode , 1 ) ;
2005-12-16 01:31:24 +03:00
brelse ( di_bh ) ;
2009-03-06 16:29:10 +03:00
bail_unlock_nfs_sync :
ocfs2_nfs_sync_unlock ( OCFS2_SB ( inode - > i_sb ) , 0 ) ;
2005-12-16 01:31:24 +03:00
bail_unblock :
2009-09-03 04:17:36 +04:00
ocfs2_unblock_signals ( & oldset ) ;
2005-12-16 01:31:24 +03:00
bail :
2011-03-07 11:43:21 +03:00
return ;
2005-12-16 01:31:24 +03:00
}
2010-06-09 05:28:10 +04:00
static void ocfs2_clear_inode ( struct inode * inode )
2005-12-16 01:31:24 +03:00
{
int status ;
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
2014-04-04 01:46:57 +04:00
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
2005-12-16 01:31:24 +03:00
2012-05-03 16:48:02 +04:00
clear_inode ( inode ) ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_clear_inode ( ( unsigned long long ) oi - > ip_blkno ,
inode - > i_nlink ) ;
2005-12-16 01:31:24 +03:00
2018-04-06 02:18:33 +03:00
mlog_bug_on_msg ( osb = = NULL ,
2005-12-16 01:31:24 +03:00
" Inode=%lu \n " , inode - > i_ino ) ;
2010-03-03 17:05:05 +03:00
dquot_drop ( inode ) ;
2010-03-03 17:05:04 +03:00
2007-09-25 02:56:19 +04:00
/* To preven remote deletes we hold open lock before, now it
* is time to unlock PR and EX open locks . */
2007-03-21 02:01:38 +03:00
ocfs2_open_unlock ( inode ) ;
2005-12-16 01:31:24 +03:00
/* Do these before all the other work so that we don't bounce
2007-09-25 02:56:19 +04:00
* the downconvert thread while waiting to destroy the locks . */
2014-04-04 01:46:57 +04:00
ocfs2_mark_lockres_freeing ( osb , & oi - > ip_rw_lockres ) ;
ocfs2_mark_lockres_freeing ( osb , & oi - > ip_inode_lockres ) ;
ocfs2_mark_lockres_freeing ( osb , & oi - > ip_open_lockres ) ;
2005-12-16 01:31:24 +03:00
2018-04-06 02:18:33 +03:00
ocfs2_resv_discard ( & osb - > osb_la_resmap ,
2009-12-08 00:15:40 +03:00
& oi - > ip_la_data_resv ) ;
ocfs2_resv_init_once ( & oi - > ip_la_data_resv ) ;
2005-12-16 01:31:24 +03:00
/* We very well may get a clear_inode before all an inodes
* metadata has hit disk . Of course , we can ' t drop any cluster
* locks until the journal has finished with it . The only
* exception here are successfully wiped inodes - their
* metadata can now be considered to be part of the system
* inodes from which it came . */
2018-04-06 02:18:37 +03:00
if ( ! ( oi - > ip_flags & OCFS2_INODE_DELETED ) )
2005-12-16 01:31:24 +03:00
ocfs2_checkpoint_inode ( inode ) ;
mlog_bug_on_msg ( ! list_empty ( & oi - > ip_io_markers ) ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu, inode has io markers \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2016-03-26 00:21:06 +03:00
mlog_bug_on_msg ( ! list_empty ( & oi - > ip_unwritten_list ) ,
" Clear inode of %llu, inode has unwritten extents \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2005-12-16 01:31:24 +03:00
2007-04-24 05:53:12 +04:00
ocfs2_extent_map_trunc ( inode , 0 ) ;
2005-12-16 01:31:24 +03:00
status = ocfs2_drop_inode_locks ( inode ) ;
if ( status < 0 )
mlog_errno ( status ) ;
ocfs2_lock_res_free ( & oi - > ip_rw_lockres ) ;
2007-10-19 02:30:42 +04:00
ocfs2_lock_res_free ( & oi - > ip_inode_lockres ) ;
2007-03-21 02:01:38 +03:00
ocfs2_lock_res_free ( & oi - > ip_open_lockres ) ;
2005-12-16 01:31:24 +03:00
2009-02-13 02:24:40 +03:00
ocfs2_metadata_cache_exit ( INODE_CACHE ( inode ) ) ;
2005-12-16 01:31:24 +03:00
2009-02-11 07:00:41 +03:00
mlog_bug_on_msg ( INODE_CACHE ( inode ) - > ci_num_cached ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu, inode has %u cache items \n " ,
2009-02-11 07:00:41 +03:00
( unsigned long long ) oi - > ip_blkno ,
INODE_CACHE ( inode ) - > ci_num_cached ) ;
2005-12-16 01:31:24 +03:00
2009-02-11 07:00:41 +03:00
mlog_bug_on_msg ( ! ( INODE_CACHE ( inode ) - > ci_flags & OCFS2_CACHE_FL_INLINE ) ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu, inode has a bad flag \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2005-12-16 01:31:24 +03:00
mlog_bug_on_msg ( spin_is_locked ( & oi - > ip_lock ) ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu, inode is locked \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2005-12-16 01:31:24 +03:00
2006-01-11 02:41:43 +03:00
mlog_bug_on_msg ( ! mutex_trylock ( & oi - > ip_io_mutex ) ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu, io_mutex is locked \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2006-01-11 02:41:43 +03:00
mutex_unlock ( & oi - > ip_io_mutex ) ;
2005-12-16 01:31:24 +03:00
/*
* down_trylock ( ) returns 0 , down_write_trylock ( ) returns 1
* kernel 1 , world 0
*/
mlog_bug_on_msg ( ! down_write_trylock ( & oi - > ip_alloc_sem ) ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu, alloc_sem is locked \n " ,
( unsigned long long ) oi - > ip_blkno ) ;
2005-12-16 01:31:24 +03:00
up_write ( & oi - > ip_alloc_sem ) ;
mlog_bug_on_msg ( oi - > ip_open_count ,
2006-03-03 21:24:33 +03:00
" Clear inode of %llu has open count %d \n " ,
( unsigned long long ) oi - > ip_blkno , oi - > ip_open_count ) ;
2005-12-16 01:31:24 +03:00
/* Clear all other flags. */
2009-02-11 03:05:07 +03:00
oi - > ip_flags = 0 ;
2005-12-16 01:31:24 +03:00
oi - > ip_dir_start_lookup = 0 ;
oi - > ip_blkno = 0ULL ;
2008-10-23 00:24:29 +04:00
/*
* ip_jinode is used to track txns against this inode . We ensure that
* the journal is flushed before journal shutdown . Thus it is safe to
* have inodes get cleaned up after journal shutdown .
*/
2018-04-06 02:18:33 +03:00
jbd2_journal_release_jbd_inode ( osb - > journal - > j_journal ,
2008-09-04 07:03:41 +04:00
& oi - > ip_jinode ) ;
2005-12-16 01:31:24 +03:00
}
2010-06-09 05:28:10 +04:00
void ocfs2_evict_inode ( struct inode * inode )
{
if ( ! inode - > i_nlink | |
( OCFS2_I ( inode ) - > ip_flags & OCFS2_INODE_MAYBE_ORPHANED ) ) {
ocfs2_delete_inode ( inode ) ;
} else {
2014-04-04 01:47:49 +04:00
truncate_inode_pages_final ( & inode - > i_data ) ;
2010-06-09 05:28:10 +04:00
}
ocfs2_clear_inode ( inode ) ;
}
2005-12-16 01:31:24 +03:00
/* Called under inode_lock, with no more references on the
* struct inode , so it ' s safe here to check the flags field
* and to manipulate i_nlink without any other locks . */
2010-06-07 21:43:19 +04:00
int ocfs2_drop_inode ( struct inode * inode )
2005-12-16 01:31:24 +03:00
{
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_drop_inode ( ( unsigned long long ) oi - > ip_blkno ,
inode - > i_nlink , oi - > ip_flags ) ;
2005-12-16 01:31:24 +03:00
2015-09-05 01:44:11 +03:00
assert_spin_locked ( & inode - > i_lock ) ;
inode - > i_state | = I_WILL_FREE ;
spin_unlock ( & inode - > i_lock ) ;
write_inode_now ( inode , 1 ) ;
spin_lock ( & inode - > i_lock ) ;
WARN_ON ( inode - > i_state & I_NEW ) ;
inode - > i_state & = ~ I_WILL_FREE ;
2005-12-16 01:31:24 +03:00
2015-09-05 01:44:11 +03:00
return 1 ;
2005-12-16 01:31:24 +03:00
}
/*
* This is called from our getattr .
*/
int ocfs2_inode_revalidate ( struct dentry * dentry )
{
2015-03-18 01:25:59 +03:00
struct inode * inode = d_inode ( dentry ) ;
2005-12-16 01:31:24 +03:00
int status = 0 ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_inode_revalidate ( inode ,
inode ? ( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno : 0ULL ,
inode ? ( unsigned long long ) OCFS2_I ( inode ) - > ip_flags : 0 ) ;
2005-12-16 01:31:24 +03:00
if ( ! inode ) {
status = - ENOENT ;
goto bail ;
}
spin_lock ( & OCFS2_I ( inode ) - > ip_lock ) ;
if ( OCFS2_I ( inode ) - > ip_flags & OCFS2_INODE_DELETED ) {
spin_unlock ( & OCFS2_I ( inode ) - > ip_lock ) ;
status = - ENOENT ;
goto bail ;
}
spin_unlock ( & OCFS2_I ( inode ) - > ip_lock ) ;
2007-10-19 02:30:42 +04:00
/* Let ocfs2_inode_lock do the work of updating our struct
2005-12-16 01:31:24 +03:00
* inode for us . */
2007-10-19 02:30:42 +04:00
status = ocfs2_inode_lock ( inode , NULL , 0 ) ;
2005-12-16 01:31:24 +03:00
if ( status < 0 ) {
if ( status ! = - ENOENT )
mlog_errno ( status ) ;
goto bail ;
}
2007-10-19 02:30:42 +04:00
ocfs2_inode_unlock ( inode , 0 ) ;
2005-12-16 01:31:24 +03:00
bail :
return status ;
}
/*
* Updates a disk inode from a
* struct inode .
* Only takes ip_lock .
*/
2006-10-10 05:11:45 +04:00
int ocfs2_mark_inode_dirty ( handle_t * handle ,
2005-12-16 01:31:24 +03:00
struct inode * inode ,
struct buffer_head * bh )
{
int status ;
struct ocfs2_dinode * fe = ( struct ocfs2_dinode * ) bh - > b_data ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_mark_inode_dirty ( ( unsigned long long ) OCFS2_I ( inode ) - > ip_blkno ) ;
2005-12-16 01:31:24 +03:00
2009-02-13 03:41:25 +03:00
status = ocfs2_journal_access_di ( handle , INODE_CACHE ( inode ) , bh ,
2008-10-18 06:25:01 +04:00
OCFS2_JOURNAL_ACCESS_WRITE ) ;
2005-12-16 01:31:24 +03:00
if ( status < 0 ) {
mlog_errno ( status ) ;
goto leave ;
}
spin_lock ( & OCFS2_I ( inode ) - > ip_lock ) ;
fe - > i_clusters = cpu_to_le32 ( OCFS2_I ( inode ) - > ip_clusters ) ;
2007-04-27 22:08:01 +04:00
ocfs2_get_inode_flags ( OCFS2_I ( inode ) ) ;
2006-07-04 04:27:12 +04:00
fe - > i_attr = cpu_to_le32 ( OCFS2_I ( inode ) - > ip_attr ) ;
2007-09-08 00:58:15 +04:00
fe - > i_dyn_features = cpu_to_le16 ( OCFS2_I ( inode ) - > ip_dyn_features ) ;
2005-12-16 01:31:24 +03:00
spin_unlock ( & OCFS2_I ( inode ) - > ip_lock ) ;
fe - > i_size = cpu_to_le64 ( i_size_read ( inode ) ) ;
2008-11-21 04:54:57 +03:00
ocfs2_set_links_count ( fe , inode - > i_nlink ) ;
2013-02-01 05:27:11 +04:00
fe - > i_uid = cpu_to_le32 ( i_uid_read ( inode ) ) ;
fe - > i_gid = cpu_to_le32 ( i_gid_read ( inode ) ) ;
2005-12-16 01:31:24 +03:00
fe - > i_mode = cpu_to_le16 ( inode - > i_mode ) ;
fe - > i_atime = cpu_to_le64 ( inode - > i_atime . tv_sec ) ;
fe - > i_atime_nsec = cpu_to_le32 ( inode - > i_atime . tv_nsec ) ;
fe - > i_ctime = cpu_to_le64 ( inode - > i_ctime . tv_sec ) ;
fe - > i_ctime_nsec = cpu_to_le32 ( inode - > i_ctime . tv_nsec ) ;
fe - > i_mtime = cpu_to_le64 ( inode - > i_mtime . tv_sec ) ;
fe - > i_mtime_nsec = cpu_to_le32 ( inode - > i_mtime . tv_nsec ) ;
2010-03-20 00:13:52 +03:00
ocfs2_journal_dirty ( handle , bh ) ;
2014-04-04 01:46:48 +04:00
ocfs2_update_inode_fsync_trans ( handle , inode , 1 ) ;
2005-12-16 01:31:24 +03:00
leave :
return status ;
}
/*
*
* Updates a struct inode from a disk inode .
* does no i / o , only takes ip_lock .
*/
void ocfs2_refresh_inode ( struct inode * inode ,
struct ocfs2_dinode * fe )
{
spin_lock ( & OCFS2_I ( inode ) - > ip_lock ) ;
OCFS2_I ( inode ) - > ip_clusters = le32_to_cpu ( fe - > i_clusters ) ;
2006-07-04 04:27:12 +04:00
OCFS2_I ( inode ) - > ip_attr = le32_to_cpu ( fe - > i_attr ) ;
2007-09-08 00:58:15 +04:00
OCFS2_I ( inode ) - > ip_dyn_features = le16_to_cpu ( fe - > i_dyn_features ) ;
2006-07-04 04:27:12 +04:00
ocfs2_set_inode_flags ( inode ) ;
2005-12-16 01:31:24 +03:00
i_size_write ( inode , le64_to_cpu ( fe - > i_size ) ) ;
2011-10-28 16:13:29 +04:00
set_nlink ( inode , ocfs2_read_links_count ( fe ) ) ;
2013-02-01 05:27:11 +04:00
i_uid_write ( inode , le32_to_cpu ( fe - > i_uid ) ) ;
i_gid_write ( inode , le32_to_cpu ( fe - > i_gid ) ) ;
2005-12-16 01:31:24 +03:00
inode - > i_mode = le16_to_cpu ( fe - > i_mode ) ;
if ( S_ISLNK ( inode - > i_mode ) & & le32_to_cpu ( fe - > i_clusters ) = = 0 )
inode - > i_blocks = 0 ;
else
2007-03-23 02:53:23 +03:00
inode - > i_blocks = ocfs2_inode_sector_count ( inode ) ;
2005-12-16 01:31:24 +03:00
inode - > i_atime . tv_sec = le64_to_cpu ( fe - > i_atime ) ;
inode - > i_atime . tv_nsec = le32_to_cpu ( fe - > i_atime_nsec ) ;
inode - > i_mtime . tv_sec = le64_to_cpu ( fe - > i_mtime ) ;
inode - > i_mtime . tv_nsec = le32_to_cpu ( fe - > i_mtime_nsec ) ;
inode - > i_ctime . tv_sec = le64_to_cpu ( fe - > i_ctime ) ;
inode - > i_ctime . tv_nsec = le32_to_cpu ( fe - > i_ctime_nsec ) ;
spin_unlock ( & OCFS2_I ( inode ) - > ip_lock ) ;
}
2008-11-14 01:49:11 +03:00
int ocfs2_validate_inode_block ( struct super_block * sb ,
struct buffer_head * bh )
{
2008-10-18 01:55:01 +04:00
int rc ;
2008-11-14 01:49:11 +03:00
struct ocfs2_dinode * di = ( struct ocfs2_dinode * ) bh - > b_data ;
2011-02-22 17:24:57 +03:00
trace_ocfs2_validate_inode_block ( ( unsigned long long ) bh - > b_blocknr ) ;
2008-11-14 01:49:19 +03:00
2008-11-14 01:49:11 +03:00
BUG_ON ( ! buffer_uptodate ( bh ) ) ;
2008-10-18 01:55:01 +04:00
/*
* If the ecc fails , we return the error but otherwise
* leave the filesystem running . We know any error is
* local to this block .
*/
rc = ocfs2_validate_meta_ecc ( sb , bh - > b_data , & di - > i_check ) ;
2008-10-18 06:25:01 +04:00
if ( rc ) {
mlog ( ML_ERROR , " Checksum failed for dinode %llu \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
2008-10-18 01:55:01 +04:00
goto bail ;
2008-10-18 06:25:01 +04:00
}
2008-10-18 01:55:01 +04:00
/*
* Errors after here are fatal .
*/
rc = - EINVAL ;
2008-11-14 01:49:11 +03:00
if ( ! OCFS2_IS_VALID_DINODE ( di ) ) {
2015-09-05 01:44:17 +03:00
rc = ocfs2_error ( sb , " Invalid dinode #%llu: signature = %.*s \n " ,
2015-09-05 01:44:51 +03:00
( unsigned long long ) bh - > b_blocknr , 7 ,
di - > i_signature ) ;
2008-11-14 01:49:11 +03:00
goto bail ;
}
if ( le64_to_cpu ( di - > i_blkno ) ! = bh - > b_blocknr ) {
2015-09-05 01:44:17 +03:00
rc = ocfs2_error ( sb , " Invalid dinode #%llu: i_blkno is %llu \n " ,
2015-09-05 01:44:51 +03:00
( unsigned long long ) bh - > b_blocknr ,
( unsigned long long ) le64_to_cpu ( di - > i_blkno ) ) ;
2008-11-14 01:49:11 +03:00
goto bail ;
}
if ( ! ( di - > i_flags & cpu_to_le32 ( OCFS2_VALID_FL ) ) ) {
2015-09-05 01:44:17 +03:00
rc = ocfs2_error ( sb ,
2015-09-05 01:44:51 +03:00
" Invalid dinode #%llu: OCFS2_VALID_FL not set \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
2008-11-14 01:49:11 +03:00
goto bail ;
}
if ( le32_to_cpu ( di - > i_fs_generation ) ! =
OCFS2_SB ( sb ) - > fs_generation ) {
2015-09-05 01:44:17 +03:00
rc = ocfs2_error ( sb ,
2015-09-05 01:44:51 +03:00
" Invalid dinode #%llu: fs_generation is %u \n " ,
( unsigned long long ) bh - > b_blocknr ,
le32_to_cpu ( di - > i_fs_generation ) ) ;
2008-11-14 01:49:11 +03:00
goto bail ;
}
rc = 0 ;
bail :
return rc ;
}
2016-03-23 00:24:30 +03:00
static int ocfs2_filecheck_validate_inode_block ( struct super_block * sb ,
struct buffer_head * bh )
{
int rc = 0 ;
struct ocfs2_dinode * di = ( struct ocfs2_dinode * ) bh - > b_data ;
trace_ocfs2_filecheck_validate_inode_block (
( unsigned long long ) bh - > b_blocknr ) ;
BUG_ON ( ! buffer_uptodate ( bh ) ) ;
/*
* Call ocfs2_validate_meta_ecc ( ) first since it has ecc repair
* function , but we should not return error immediately when ecc
* validation fails , because the reason is quite likely the invalid
* inode number inputed .
*/
rc = ocfs2_validate_meta_ecc ( sb , bh - > b_data , & di - > i_check ) ;
if ( rc ) {
mlog ( ML_ERROR ,
" Filecheck: checksum failed for dinode %llu \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
rc = - OCFS2_FILECHECK_ERR_BLOCKECC ;
}
if ( ! OCFS2_IS_VALID_DINODE ( di ) ) {
mlog ( ML_ERROR ,
" Filecheck: invalid dinode #%llu: signature = %.*s \n " ,
( unsigned long long ) bh - > b_blocknr , 7 , di - > i_signature ) ;
rc = - OCFS2_FILECHECK_ERR_INVALIDINO ;
goto bail ;
} else if ( rc )
goto bail ;
if ( le64_to_cpu ( di - > i_blkno ) ! = bh - > b_blocknr ) {
mlog ( ML_ERROR ,
" Filecheck: invalid dinode #%llu: i_blkno is %llu \n " ,
( unsigned long long ) bh - > b_blocknr ,
( unsigned long long ) le64_to_cpu ( di - > i_blkno ) ) ;
rc = - OCFS2_FILECHECK_ERR_BLOCKNO ;
goto bail ;
}
if ( ! ( di - > i_flags & cpu_to_le32 ( OCFS2_VALID_FL ) ) ) {
mlog ( ML_ERROR ,
" Filecheck: invalid dinode #%llu: OCFS2_VALID_FL "
" not set \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
rc = - OCFS2_FILECHECK_ERR_VALIDFLAG ;
goto bail ;
}
if ( le32_to_cpu ( di - > i_fs_generation ) ! =
OCFS2_SB ( sb ) - > fs_generation ) {
mlog ( ML_ERROR ,
" Filecheck: invalid dinode #%llu: fs_generation is %u \n " ,
( unsigned long long ) bh - > b_blocknr ,
le32_to_cpu ( di - > i_fs_generation ) ) ;
rc = - OCFS2_FILECHECK_ERR_GENERATION ;
}
bail :
return rc ;
}
static int ocfs2_filecheck_repair_inode_block ( struct super_block * sb ,
struct buffer_head * bh )
{
int changed = 0 ;
struct ocfs2_dinode * di = ( struct ocfs2_dinode * ) bh - > b_data ;
if ( ! ocfs2_filecheck_validate_inode_block ( sb , bh ) )
return 0 ;
trace_ocfs2_filecheck_repair_inode_block (
( unsigned long long ) bh - > b_blocknr ) ;
if ( ocfs2_is_hard_readonly ( OCFS2_SB ( sb ) ) | |
ocfs2_is_soft_readonly ( OCFS2_SB ( sb ) ) ) {
mlog ( ML_ERROR ,
" Filecheck: cannot repair dinode #%llu "
" on readonly filesystem \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
return - OCFS2_FILECHECK_ERR_READONLY ;
}
if ( buffer_jbd ( bh ) ) {
mlog ( ML_ERROR ,
" Filecheck: cannot repair dinode #%llu, "
" its buffer is in jbd \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
return - OCFS2_FILECHECK_ERR_INJBD ;
}
if ( ! OCFS2_IS_VALID_DINODE ( di ) ) {
/* Cannot fix invalid inode block */
return - OCFS2_FILECHECK_ERR_INVALIDINO ;
}
if ( ! ( di - > i_flags & cpu_to_le32 ( OCFS2_VALID_FL ) ) ) {
/* Cannot just add VALID_FL flag back as a fix,
* need more things to check here .
*/
return - OCFS2_FILECHECK_ERR_VALIDFLAG ;
}
if ( le64_to_cpu ( di - > i_blkno ) ! = bh - > b_blocknr ) {
di - > i_blkno = cpu_to_le64 ( bh - > b_blocknr ) ;
changed = 1 ;
mlog ( ML_ERROR ,
" Filecheck: reset dinode #%llu: i_blkno to %llu \n " ,
( unsigned long long ) bh - > b_blocknr ,
( unsigned long long ) le64_to_cpu ( di - > i_blkno ) ) ;
}
if ( le32_to_cpu ( di - > i_fs_generation ) ! =
OCFS2_SB ( sb ) - > fs_generation ) {
di - > i_fs_generation = cpu_to_le32 ( OCFS2_SB ( sb ) - > fs_generation ) ;
changed = 1 ;
mlog ( ML_ERROR ,
" Filecheck: reset dinode #%llu: fs_generation to %u \n " ,
( unsigned long long ) bh - > b_blocknr ,
le32_to_cpu ( di - > i_fs_generation ) ) ;
}
if ( changed | | ocfs2_validate_meta_ecc ( sb , bh - > b_data , & di - > i_check ) ) {
ocfs2_compute_meta_ecc ( sb , bh - > b_data , & di - > i_check ) ;
mark_buffer_dirty ( bh ) ;
mlog ( ML_ERROR ,
" Filecheck: reset dinode #%llu: compute meta ecc \n " ,
( unsigned long long ) bh - > b_blocknr ) ;
}
return 0 ;
}
static int
ocfs2_filecheck_read_inode_block_full ( struct inode * inode ,
struct buffer_head * * bh ,
int flags , int type )
{
int rc ;
struct buffer_head * tmp = * bh ;
if ( ! type ) /* Check inode block */
rc = ocfs2_read_blocks ( INODE_CACHE ( inode ) ,
OCFS2_I ( inode ) - > ip_blkno ,
1 , & tmp , flags ,
ocfs2_filecheck_validate_inode_block ) ;
else /* Repair inode block */
rc = ocfs2_read_blocks ( INODE_CACHE ( inode ) ,
OCFS2_I ( inode ) - > ip_blkno ,
1 , & tmp , flags ,
ocfs2_filecheck_repair_inode_block ) ;
/* If ocfs2_read_blocks() got us a new bh, pass it up. */
if ( ! rc & & ! * bh )
* bh = tmp ;
return rc ;
}
2008-11-14 01:49:11 +03:00
int ocfs2_read_inode_block_full ( struct inode * inode , struct buffer_head * * bh ,
int flags )
{
int rc ;
struct buffer_head * tmp = * bh ;
2009-02-11 07:00:41 +03:00
rc = ocfs2_read_blocks ( INODE_CACHE ( inode ) , OCFS2_I ( inode ) - > ip_blkno ,
1 , & tmp , flags , ocfs2_validate_inode_block ) ;
2008-11-14 01:49:11 +03:00
/* If ocfs2_read_blocks() got us a new bh, pass it up. */
2008-11-14 01:49:19 +03:00
if ( ! rc & & ! * bh )
2008-11-14 01:49:11 +03:00
* bh = tmp ;
return rc ;
}
int ocfs2_read_inode_block ( struct inode * inode , struct buffer_head * * bh )
{
return ocfs2_read_inode_block_full ( inode , bh , 0 ) ;
}
2009-02-11 06:00:37 +03:00
static u64 ocfs2_inode_cache_owner ( struct ocfs2_caching_info * ci )
{
struct ocfs2_inode_info * oi = cache_info_to_inode ( ci ) ;
return oi - > ip_blkno ;
}
2009-02-11 07:00:41 +03:00
static struct super_block * ocfs2_inode_cache_get_super ( struct ocfs2_caching_info * ci )
{
struct ocfs2_inode_info * oi = cache_info_to_inode ( ci ) ;
return oi - > vfs_inode . i_sb ;
}
2009-02-11 06:00:37 +03:00
static void ocfs2_inode_cache_lock ( struct ocfs2_caching_info * ci )
{
struct ocfs2_inode_info * oi = cache_info_to_inode ( ci ) ;
spin_lock ( & oi - > ip_lock ) ;
}
static void ocfs2_inode_cache_unlock ( struct ocfs2_caching_info * ci )
{
struct ocfs2_inode_info * oi = cache_info_to_inode ( ci ) ;
spin_unlock ( & oi - > ip_lock ) ;
}
static void ocfs2_inode_cache_io_lock ( struct ocfs2_caching_info * ci )
{
struct ocfs2_inode_info * oi = cache_info_to_inode ( ci ) ;
mutex_lock ( & oi - > ip_io_mutex ) ;
}
static void ocfs2_inode_cache_io_unlock ( struct ocfs2_caching_info * ci )
{
struct ocfs2_inode_info * oi = cache_info_to_inode ( ci ) ;
mutex_unlock ( & oi - > ip_io_mutex ) ;
}
const struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
. co_owner = ocfs2_inode_cache_owner ,
2009-02-11 07:00:41 +03:00
. co_get_super = ocfs2_inode_cache_get_super ,
2009-02-11 06:00:37 +03:00
. co_cache_lock = ocfs2_inode_cache_lock ,
. co_cache_unlock = ocfs2_inode_cache_unlock ,
. co_io_lock = ocfs2_inode_cache_io_lock ,
. co_io_unlock = ocfs2_inode_cache_io_unlock ,
} ;