2018-09-05 01:46:30 +03:00
// SPDX-License-Identifier: GPL-2.0+
2009-04-07 06:01:30 +04:00
/*
* ifile . c - NILFS inode file
*
* Copyright ( C ) 2006 - 2008 Nippon Telegraph and Telephone Corporation .
*
2016-05-24 02:23:09 +03:00
* Written by Amagai Yoshiji .
* Revised by Ryusuke Konishi .
2009-04-07 06:01:30 +04:00
*
*/
# include <linux/types.h>
# include <linux/buffer_head.h>
# include "nilfs.h"
# include "mdt.h"
# include "alloc.h"
# include "ifile.h"
2012-07-31 01:42:10 +04:00
/**
* struct nilfs_ifile_info - on - memory private data of ifile
* @ mi : on - memory private data of metadata file
* @ palloc_cache : persistent object allocator cache of ifile
*/
2009-11-14 10:44:22 +03:00
struct nilfs_ifile_info {
struct nilfs_mdt_info mi ;
struct nilfs_palloc_cache palloc_cache ;
} ;
static inline struct nilfs_ifile_info * NILFS_IFILE_I ( struct inode * ifile )
{
return ( struct nilfs_ifile_info * ) NILFS_MDT ( ifile ) ;
}
2009-04-07 06:01:30 +04:00
/**
* nilfs_ifile_create_inode - create a new disk inode
* @ ifile : ifile inode
* @ out_ino : pointer to a variable to store inode number
* @ out_bh : buffer_head contains newly allocated disk inode
*
* Return Value : On success , 0 is returned and the newly allocated inode
* number is stored in the place pointed by @ ino , and buffer_head pointer
* that contains newly allocated disk inode structure is stored in the
* place pointed by @ out_bh
* On error , one of the following negative error codes is returned .
*
* % - EIO - I / O error .
*
* % - ENOMEM - Insufficient amount of memory available .
*
* % - ENOSPC - No inode left .
*/
int nilfs_ifile_create_inode ( struct inode * ifile , ino_t * out_ino ,
struct buffer_head * * out_bh )
{
struct nilfs_palloc_req req ;
int ret ;
2016-05-24 02:23:48 +03:00
req . pr_entry_nr = 0 ; /*
* 0 says find free inode from beginning
* of a group . dull code ! !
*/
2009-04-07 06:01:30 +04:00
req . pr_entry_bh = NULL ;
ret = nilfs_palloc_prepare_alloc_entry ( ifile , & req ) ;
if ( ! ret ) {
ret = nilfs_palloc_get_entry_block ( ifile , req . pr_entry_nr , 1 ,
& req . pr_entry_bh ) ;
if ( ret < 0 )
nilfs_palloc_abort_alloc_entry ( ifile , & req ) ;
}
if ( ret < 0 ) {
brelse ( req . pr_entry_bh ) ;
return ret ;
}
nilfs_palloc_commit_alloc_entry ( ifile , & req ) ;
2011-05-05 07:56:51 +04:00
mark_buffer_dirty ( req . pr_entry_bh ) ;
2009-04-07 06:01:30 +04:00
nilfs_mdt_mark_dirty ( ifile ) ;
* out_ino = ( ino_t ) req . pr_entry_nr ;
* out_bh = req . pr_entry_bh ;
return 0 ;
}
/**
* nilfs_ifile_delete_inode - delete a disk inode
* @ ifile : ifile inode
* @ ino : inode number
*
* Return Value : On success , 0 is returned . On error , one of the following
* negative error codes is returned .
*
* % - EIO - I / O error .
*
* % - ENOMEM - Insufficient amount of memory available .
*
* % - ENOENT - The inode number @ ino have not been allocated .
*/
int nilfs_ifile_delete_inode ( struct inode * ifile , ino_t ino )
{
struct nilfs_palloc_req req = {
. pr_entry_nr = ino , . pr_entry_bh = NULL
} ;
struct nilfs_inode * raw_inode ;
void * kaddr ;
int ret ;
ret = nilfs_palloc_prepare_free_entry ( ifile , & req ) ;
if ( ! ret ) {
ret = nilfs_palloc_get_entry_block ( ifile , req . pr_entry_nr , 0 ,
& req . pr_entry_bh ) ;
if ( ret < 0 )
nilfs_palloc_abort_free_entry ( ifile , & req ) ;
}
if ( ret < 0 ) {
brelse ( req . pr_entry_bh ) ;
return ret ;
}
2011-11-25 19:14:33 +04:00
kaddr = kmap_atomic ( req . pr_entry_bh - > b_page ) ;
2009-04-07 06:01:30 +04:00
raw_inode = nilfs_palloc_block_get_entry ( ifile , req . pr_entry_nr ,
req . pr_entry_bh , kaddr ) ;
raw_inode - > i_flags = 0 ;
2011-11-25 19:14:33 +04:00
kunmap_atomic ( kaddr ) ;
2009-04-07 06:01:30 +04:00
2011-05-05 07:56:51 +04:00
mark_buffer_dirty ( req . pr_entry_bh ) ;
2009-04-07 06:01:30 +04:00
brelse ( req . pr_entry_bh ) ;
nilfs_palloc_commit_free_entry ( ifile , & req ) ;
return 0 ;
}
int nilfs_ifile_get_inode_block ( struct inode * ifile , ino_t ino ,
struct buffer_head * * out_bh )
{
struct super_block * sb = ifile - > i_sb ;
int err ;
if ( unlikely ( ! NILFS_VALID_INODE ( sb , ino ) ) ) {
2016-08-03 00:05:00 +03:00
nilfs_error ( sb , " bad inode number: %lu " , ( unsigned long ) ino ) ;
2009-04-07 06:01:30 +04:00
return - EINVAL ;
}
err = nilfs_palloc_get_entry_block ( ifile , ino , 0 , out_bh ) ;
2010-11-19 09:26:20 +03:00
if ( unlikely ( err ) )
2016-08-03 00:05:14 +03:00
nilfs_msg ( sb , KERN_WARNING , " error %d reading inode: ino=%lu " ,
err , ( unsigned long ) ino ) ;
2009-04-07 06:01:30 +04:00
return err ;
}
2009-11-12 17:56:43 +03:00
2013-07-04 02:08:05 +04:00
/**
* nilfs_ifile_count_free_inodes - calculate free inodes count
* @ ifile : ifile inode
* @ nmaxinodes : current maximum of available inodes count [ out ]
* @ nfreeinodes : free inodes count [ out ]
*/
int nilfs_ifile_count_free_inodes ( struct inode * ifile ,
u64 * nmaxinodes , u64 * nfreeinodes )
{
u64 nused ;
int err ;
* nmaxinodes = 0 ;
* nfreeinodes = 0 ;
2013-07-04 02:08:06 +04:00
nused = atomic64_read ( & NILFS_I ( ifile ) - > i_root - > inodes_count ) ;
2013-07-04 02:08:05 +04:00
err = nilfs_palloc_count_max_entries ( ifile , nused , nmaxinodes ) ;
if ( likely ( ! err ) )
* nfreeinodes = * nmaxinodes - nused ;
return err ;
}
2009-11-12 17:56:43 +03:00
/**
2010-09-05 07:20:59 +04:00
* nilfs_ifile_read - read or get ifile inode
* @ sb : super block instance
* @ root : root object
2009-11-12 17:56:43 +03:00
* @ inode_size : size of an inode
2010-09-05 07:20:59 +04:00
* @ raw_inode : on - disk ifile inode
* @ inodep : buffer to store the inode
2009-11-12 17:56:43 +03:00
*/
2010-09-05 07:20:59 +04:00
int nilfs_ifile_read ( struct super_block * sb , struct nilfs_root * root ,
size_t inode_size , struct nilfs_inode * raw_inode ,
struct inode * * inodep )
2009-11-12 17:56:43 +03:00
{
struct inode * ifile ;
int err ;
2010-09-05 07:20:59 +04:00
ifile = nilfs_iget_locked ( sb , root , NILFS_IFILE_INO ) ;
if ( unlikely ( ! ifile ) )
return - ENOMEM ;
if ( ! ( ifile - > i_state & I_NEW ) )
goto out ;
err = nilfs_mdt_init ( ifile , NILFS_MDT_GFP ,
sizeof ( struct nilfs_ifile_info ) ) ;
if ( err )
goto failed ;
err = nilfs_palloc_init_blockgroup ( ifile , inode_size ) ;
if ( err )
goto failed ;
nilfs_palloc_setup_cache ( ifile , & NILFS_IFILE_I ( ifile ) - > palloc_cache ) ;
err = nilfs_read_inode_common ( ifile , raw_inode ) ;
if ( err )
goto failed ;
unlock_new_inode ( ifile ) ;
out :
* inodep = ifile ;
return 0 ;
failed :
iget_failed ( ifile ) ;
return err ;
2009-11-12 17:56:43 +03:00
}