2018-09-05 01:46:30 +03:00
// SPDX-License-Identifier: GPL-2.0+
2009-04-07 06:01:35 +04:00
/*
* super . c - NILFS module and super block management .
*
* Copyright ( C ) 2005 - 2008 Nippon Telegraph and Telephone Corporation .
*
2016-05-24 02:23:09 +03:00
* Written by Ryusuke Konishi .
2009-04-07 06:01:35 +04:00
*/
/*
* linux / fs / ext2 / super . c
*
* Copyright ( C ) 1992 , 1993 , 1994 , 1995
* Remy Card ( card @ masi . ibp . fr )
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie ( Paris VI )
*
* from
*
* linux / fs / minix / inode . c
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
*
* Big - endian to little - endian byte - swapping / bitmaps by
* David S . Miller ( davem @ caip . rutgers . edu ) , 1995
*/
# include <linux/module.h>
# include <linux/string.h>
# include <linux/slab.h>
# include <linux/init.h>
# include <linux/blkdev.h>
# include <linux/parser.h>
# include <linux/crc32.h>
# include <linux/vfs.h>
# include <linux/writeback.h>
2009-06-24 15:06:34 +04:00
# include <linux/seq_file.h>
# include <linux/mount.h>
2009-04-07 06:01:35 +04:00
# include "nilfs.h"
2010-08-26 19:23:02 +04:00
# include "export.h"
2009-04-07 06:01:35 +04:00
# include "mdt.h"
# include "alloc.h"
2010-07-10 15:52:09 +04:00
# include "btree.h"
# include "btnode.h"
2009-04-07 06:01:35 +04:00
# include "page.h"
# include "cpfile.h"
2011-05-04 20:23:58 +04:00
# include "sufile.h" /* nilfs_sufile_resize(), nilfs_sufile_set_alloc_range() */
2009-04-07 06:01:35 +04:00
# include "ifile.h"
# include "dat.h"
# include "segment.h"
# include "segbuf.h"
MODULE_AUTHOR ( " NTT Corp. " ) ;
MODULE_DESCRIPTION ( " A New Implementation of the Log-structured Filesystem "
" (NILFS) " ) ;
MODULE_LICENSE ( " GPL " ) ;
2010-10-08 17:37:27 +04:00
static struct kmem_cache * nilfs_inode_cachep ;
2010-04-05 20:54:11 +04:00
struct kmem_cache * nilfs_transaction_cachep ;
struct kmem_cache * nilfs_segbuf_cachep ;
struct kmem_cache * nilfs_btree_path_cache ;
2011-03-09 05:05:08 +03:00
static int nilfs_setup_super ( struct super_block * sb , int is_mount ) ;
2009-04-07 06:01:35 +04:00
static int nilfs_remount ( struct super_block * sb , int * flags , char * data ) ;
2016-08-03 00:05:02 +03:00
void __nilfs_msg ( struct super_block * sb , const char * level , const char * fmt ,
. . . )
{
struct va_format vaf ;
va_list args ;
va_start ( args , fmt ) ;
vaf . fmt = fmt ;
vaf . va = & args ;
if ( sb )
printk ( " %sNILFS (%s): %pV \n " , level , sb - > s_id , & vaf ) ;
else
printk ( " %sNILFS: %pV \n " , level , & vaf ) ;
va_end ( args ) ;
}
2011-03-09 05:05:08 +03:00
static void nilfs_set_error ( struct super_block * sb )
2010-06-28 12:49:30 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-06-28 12:49:32 +04:00
struct nilfs_super_block * * sbp ;
2010-06-28 12:49:30 +04:00
down_write ( & nilfs - > ns_sem ) ;
if ( ! ( nilfs - > ns_mount_state & NILFS_ERROR_FS ) ) {
nilfs - > ns_mount_state | = NILFS_ERROR_FS ;
2011-03-09 05:05:08 +03:00
sbp = nilfs_prepare_super ( sb , 0 ) ;
2010-06-28 12:49:32 +04:00
if ( likely ( sbp ) ) {
sbp [ 0 ] - > s_state | = cpu_to_le16 ( NILFS_ERROR_FS ) ;
2010-06-28 12:49:33 +04:00
if ( sbp [ 1 ] )
sbp [ 1 ] - > s_state | = cpu_to_le16 ( NILFS_ERROR_FS ) ;
2011-03-09 05:05:08 +03:00
nilfs_commit_super ( sb , NILFS_SB_COMMIT_ALL ) ;
2010-06-28 12:49:32 +04:00
}
2010-06-28 12:49:30 +04:00
}
up_write ( & nilfs - > ns_sem ) ;
}
2009-04-07 06:01:35 +04:00
/**
2016-08-03 00:05:00 +03:00
* __nilfs_error ( ) - report failure condition on a filesystem
2009-04-07 06:01:35 +04:00
*
2016-08-03 00:05:00 +03:00
* __nilfs_error ( ) sets an ERROR_FS flag on the superblock as well as
* reporting an error message . This function should be called when
* NILFS detects incoherences or defects of meta data on disk .
2009-04-07 06:01:35 +04:00
*
2016-08-03 00:05:00 +03:00
* This implements the body of nilfs_error ( ) macro . Normally ,
* nilfs_error ( ) should be used . As for sustainable errors such as a
2016-08-03 00:05:14 +03:00
* single - shot I / O error , nilfs_msg ( ) should be used instead .
2016-08-03 00:05:00 +03:00
*
* Callers should not add a trailing newline since this will do it .
2009-04-07 06:01:35 +04:00
*/
2016-08-03 00:05:00 +03:00
void __nilfs_error ( struct super_block * sb , const char * function ,
const char * fmt , . . . )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-11-10 03:35:21 +03:00
struct va_format vaf ;
2009-04-07 06:01:35 +04:00
va_list args ;
va_start ( args , fmt ) ;
2010-11-10 03:35:21 +03:00
vaf . fmt = fmt ;
vaf . va = & args ;
printk ( KERN_CRIT " NILFS error (device %s): %s: %pV \n " ,
sb - > s_id , function , & vaf ) ;
2009-04-07 06:01:35 +04:00
va_end ( args ) ;
2017-07-17 10:45:34 +03:00
if ( ! sb_rdonly ( sb ) ) {
2011-03-09 05:05:08 +03:00
nilfs_set_error ( sb ) ;
2009-04-07 06:01:35 +04:00
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , ERRORS_RO ) ) {
2009-04-07 06:01:35 +04:00
printk ( KERN_CRIT " Remounting filesystem read-only \n " ) ;
2017-11-28 00:05:09 +03:00
sb - > s_flags | = SB_RDONLY ;
2009-04-07 06:01:35 +04:00
}
}
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , ERRORS_PANIC ) )
2009-04-07 06:01:35 +04:00
panic ( " NILFS (device %s): panic forced after error \n " ,
sb - > s_id ) ;
}
2010-09-05 08:35:53 +04:00
struct inode * nilfs_alloc_inode ( struct super_block * sb )
2009-04-07 06:01:35 +04:00
{
struct nilfs_inode_info * ii ;
ii = kmem_cache_alloc ( nilfs_inode_cachep , GFP_NOFS ) ;
if ( ! ii )
return NULL ;
ii - > i_bh = NULL ;
ii - > i_state = 0 ;
2010-08-20 16:20:29 +04:00
ii - > i_cno = 0 ;
2015-01-14 12:42:37 +03:00
nilfs_mapping_init ( & ii - > i_btnode_cache , & ii - > vfs_inode ) ;
2009-04-07 06:01:35 +04:00
return & ii - > vfs_inode ;
}
2011-01-07 09:49:49 +03:00
static void nilfs_i_callback ( struct rcu_head * head )
2009-04-07 06:01:35 +04:00
{
2011-01-07 09:49:49 +03:00
struct inode * inode = container_of ( head , struct inode , i_rcu ) ;
2010-08-20 18:46:06 +04:00
2016-05-24 02:23:20 +03:00
if ( nilfs_is_metadata_file_inode ( inode ) )
nilfs_mdt_destroy ( inode ) ;
2009-04-07 06:01:35 +04:00
kmem_cache_free ( nilfs_inode_cachep , NILFS_I ( inode ) ) ;
}
2011-01-07 09:49:49 +03:00
void nilfs_destroy_inode ( struct inode * inode )
{
call_rcu ( & inode - > i_rcu , nilfs_i_callback ) ;
}
2011-03-09 05:05:08 +03:00
static int nilfs_sync_super ( struct super_block * sb , int flag )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:35 +04:00
int err ;
retry :
2009-04-07 06:01:59 +04:00
set_buffer_dirty ( nilfs - > ns_sbh [ 0 ] ) ;
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , BARRIER ) ) {
2010-08-11 19:05:45 +04:00
err = __sync_dirty_buffer ( nilfs - > ns_sbh [ 0 ] ,
2016-11-01 16:40:10 +03:00
REQ_SYNC | REQ_PREFLUSH | REQ_FUA ) ;
2010-08-11 19:05:45 +04:00
} else {
err = sync_dirty_buffer ( nilfs - > ns_sbh [ 0 ] ) ;
2009-04-07 06:01:35 +04:00
}
2010-08-11 19:05:45 +04:00
2009-04-07 06:01:59 +04:00
if ( unlikely ( err ) ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR , " unable to write superblock: err=%d " ,
err ) ;
2009-04-07 06:01:59 +04:00
if ( err = = - EIO & & nilfs - > ns_sbh [ 1 ] ) {
2010-06-28 12:49:33 +04:00
/*
* sbp [ 0 ] points to newer log than sbp [ 1 ] ,
* so copy sbp [ 0 ] to sbp [ 1 ] to take over sbp [ 0 ] .
*/
memcpy ( nilfs - > ns_sbp [ 1 ] , nilfs - > ns_sbp [ 0 ] ,
nilfs - > ns_sbsize ) ;
2009-04-07 06:01:59 +04:00
nilfs_fall_back_super_block ( nilfs ) ;
goto retry ;
}
} else {
struct nilfs_super_block * sbp = nilfs - > ns_sbp [ 0 ] ;
2010-06-28 12:49:33 +04:00
nilfs - > ns_sbwcount + + ;
2009-04-07 06:01:59 +04:00
/*
* The latest segment becomes trailable from the position
* written in superblock .
*/
2009-04-07 06:01:35 +04:00
clear_nilfs_discontinued ( nilfs ) ;
2009-04-07 06:01:59 +04:00
/* update GC protection for recent segments */
if ( nilfs - > ns_sbh [ 1 ] ) {
2010-06-28 12:49:33 +04:00
if ( flag = = NILFS_SB_COMMIT_ALL ) {
2009-04-07 06:01:59 +04:00
set_buffer_dirty ( nilfs - > ns_sbh [ 1 ] ) ;
2010-06-28 12:49:33 +04:00
if ( sync_dirty_buffer ( nilfs - > ns_sbh [ 1 ] ) < 0 )
goto out ;
2009-04-07 06:01:59 +04:00
}
2010-06-28 12:49:33 +04:00
if ( le64_to_cpu ( nilfs - > ns_sbp [ 1 ] - > s_last_cno ) <
le64_to_cpu ( nilfs - > ns_sbp [ 0 ] - > s_last_cno ) )
sbp = nilfs - > ns_sbp [ 1 ] ;
2009-04-07 06:01:59 +04:00
}
2009-04-07 06:01:35 +04:00
2010-06-28 12:49:33 +04:00
spin_lock ( & nilfs - > ns_last_segment_lock ) ;
nilfs - > ns_prot_seq = le64_to_cpu ( sbp - > s_last_seq ) ;
spin_unlock ( & nilfs - > ns_last_segment_lock ) ;
}
out :
2009-04-07 06:01:35 +04:00
return err ;
}
2010-06-28 12:49:31 +04:00
void nilfs_set_log_cursor ( struct nilfs_super_block * sbp ,
struct the_nilfs * nilfs )
{
sector_t nfreeblocks ;
/* nilfs->ns_sem must be locked by the caller. */
nilfs_count_free_blocks ( nilfs , & nfreeblocks ) ;
sbp - > s_free_blocks_count = cpu_to_le64 ( nfreeblocks ) ;
spin_lock ( & nilfs - > ns_last_segment_lock ) ;
sbp - > s_last_seq = cpu_to_le64 ( nilfs - > ns_last_seq ) ;
sbp - > s_last_pseg = cpu_to_le64 ( nilfs - > ns_last_pseg ) ;
sbp - > s_last_cno = cpu_to_le64 ( nilfs - > ns_last_cno ) ;
spin_unlock ( & nilfs - > ns_last_segment_lock ) ;
}
2011-03-09 05:05:08 +03:00
struct nilfs_super_block * * nilfs_prepare_super ( struct super_block * sb ,
2010-06-28 12:49:33 +04:00
int flip )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:59 +04:00
struct nilfs_super_block * * sbp = nilfs - > ns_sbp ;
2009-04-07 06:01:35 +04:00
2010-06-28 12:49:32 +04:00
/* nilfs->ns_sem must be locked by the caller. */
2010-05-01 05:07:07 +04:00
if ( sbp [ 0 ] - > s_magic ! = cpu_to_le16 ( NILFS_SUPER_MAGIC ) ) {
2010-06-28 12:49:32 +04:00
if ( sbp [ 1 ] & &
sbp [ 1 ] - > s_magic = = cpu_to_le16 ( NILFS_SUPER_MAGIC ) ) {
2010-06-28 12:49:33 +04:00
memcpy ( sbp [ 0 ] , sbp [ 1 ] , nilfs - > ns_sbsize ) ;
2010-06-28 12:49:32 +04:00
} else {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_CRIT , " superblock broke " ) ;
2010-06-28 12:49:32 +04:00
return NULL ;
2009-04-07 06:01:59 +04:00
}
2010-06-28 12:49:33 +04:00
} else if ( sbp [ 1 ] & &
sbp [ 1 ] - > s_magic ! = cpu_to_le16 ( NILFS_SUPER_MAGIC ) ) {
2016-05-24 02:23:36 +03:00
memcpy ( sbp [ 1 ] , sbp [ 0 ] , nilfs - > ns_sbsize ) ;
2009-04-07 06:01:59 +04:00
}
2010-06-28 12:49:33 +04:00
if ( flip & & sbp [ 1 ] )
nilfs_swap_super_block ( nilfs ) ;
2010-06-28 12:49:32 +04:00
return sbp ;
}
2011-03-09 05:05:08 +03:00
int nilfs_commit_super ( struct super_block * sb , int flag )
2010-06-28 12:49:32 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-06-28 12:49:32 +04:00
struct nilfs_super_block * * sbp = nilfs - > ns_sbp ;
2018-02-07 02:39:21 +03:00
time64_t t ;
2010-06-28 12:49:32 +04:00
/* nilfs->ns_sem must be locked by the caller. */
2018-02-07 02:39:21 +03:00
t = ktime_get_real_seconds ( ) ;
2010-06-28 12:49:33 +04:00
nilfs - > ns_sbwtime = t ;
2009-04-07 06:01:59 +04:00
sbp [ 0 ] - > s_wtime = cpu_to_le64 ( t ) ;
sbp [ 0 ] - > s_sum = 0 ;
sbp [ 0 ] - > s_sum = cpu_to_le32 ( crc32_le ( nilfs - > ns_crc_seed ,
( unsigned char * ) sbp [ 0 ] ,
nilfs - > ns_sbsize ) ) ;
2010-06-28 12:49:33 +04:00
if ( flag = = NILFS_SB_COMMIT_ALL & & sbp [ 1 ] ) {
sbp [ 1 ] - > s_wtime = sbp [ 0 ] - > s_wtime ;
sbp [ 1 ] - > s_sum = 0 ;
sbp [ 1 ] - > s_sum = cpu_to_le32 ( crc32_le ( nilfs - > ns_crc_seed ,
( unsigned char * ) sbp [ 1 ] ,
nilfs - > ns_sbsize ) ) ;
2009-04-07 06:01:59 +04:00
}
2009-12-08 18:57:52 +03:00
clear_nilfs_sb_dirty ( nilfs ) ;
2014-10-14 02:53:20 +04:00
nilfs - > ns_flushed_device = 1 ;
/* make sure store to ns_flushed_device cannot be reordered */
smp_wmb ( ) ;
2011-03-09 05:05:08 +03:00
return nilfs_sync_super ( sb , flag ) ;
2009-04-07 06:01:35 +04:00
}
2010-06-28 12:49:29 +04:00
/**
* nilfs_cleanup_super ( ) - write filesystem state for cleanup
2011-03-09 05:05:08 +03:00
* @ sb : super block instance to be unmounted or degraded to read - only
2010-06-28 12:49:29 +04:00
*
* This function restores state flags in the on - disk super block .
* This will set " clean " flag ( i . e . NILFS_VALID_FS ) unless the
* filesystem was not clean previously .
*/
2011-03-09 05:05:08 +03:00
int nilfs_cleanup_super ( struct super_block * sb )
2010-06-28 12:49:29 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-06-28 12:49:32 +04:00
struct nilfs_super_block * * sbp ;
2010-06-28 12:49:33 +04:00
int flag = NILFS_SB_COMMIT ;
2010-06-28 12:49:32 +04:00
int ret = - EIO ;
2010-06-28 12:49:29 +04:00
2011-03-09 05:05:08 +03:00
sbp = nilfs_prepare_super ( sb , 0 ) ;
2010-06-28 12:49:32 +04:00
if ( sbp ) {
2011-03-09 05:05:08 +03:00
sbp [ 0 ] - > s_state = cpu_to_le16 ( nilfs - > ns_mount_state ) ;
nilfs_set_log_cursor ( sbp [ 0 ] , nilfs ) ;
2010-06-28 12:49:33 +04:00
if ( sbp [ 1 ] & & sbp [ 0 ] - > s_last_cno = = sbp [ 1 ] - > s_last_cno ) {
/*
* make the " clean " flag also to the opposite
* super block if both super blocks point to
* the same checkpoint .
*/
sbp [ 1 ] - > s_state = sbp [ 0 ] - > s_state ;
flag = NILFS_SB_COMMIT_ALL ;
}
2011-03-09 05:05:08 +03:00
ret = nilfs_commit_super ( sb , flag ) ;
2010-06-28 12:49:32 +04:00
}
2010-06-28 12:49:29 +04:00
return ret ;
}
2011-05-04 20:23:57 +04:00
/**
* nilfs_move_2nd_super - relocate secondary super block
* @ sb : super block instance
* @ sb2off : new offset of the secondary super block ( in bytes )
*/
static int nilfs_move_2nd_super ( struct super_block * sb , loff_t sb2off )
{
struct the_nilfs * nilfs = sb - > s_fs_info ;
struct buffer_head * nsbh ;
struct nilfs_super_block * nsbp ;
sector_t blocknr , newblocknr ;
unsigned long offset ;
2015-11-07 03:32:16 +03:00
int sb2i ; /* array index of the secondary superblock */
2011-05-04 20:23:57 +04:00
int ret = 0 ;
/* nilfs->ns_sem must be locked by the caller. */
if ( nilfs - > ns_sbh [ 1 ] & &
nilfs - > ns_sbh [ 1 ] - > b_blocknr > nilfs - > ns_first_data_block ) {
sb2i = 1 ;
blocknr = nilfs - > ns_sbh [ 1 ] - > b_blocknr ;
} else if ( nilfs - > ns_sbh [ 0 ] - > b_blocknr > nilfs - > ns_first_data_block ) {
sb2i = 0 ;
blocknr = nilfs - > ns_sbh [ 0 ] - > b_blocknr ;
2015-11-07 03:32:16 +03:00
} else {
sb2i = - 1 ;
blocknr = 0 ;
2011-05-04 20:23:57 +04:00
}
if ( sb2i > = 0 & & ( u64 ) blocknr < < nilfs - > ns_blocksize_bits = = sb2off )
goto out ; /* super block location is unchanged */
/* Get new super block buffer */
newblocknr = sb2off > > nilfs - > ns_blocksize_bits ;
offset = sb2off & ( nilfs - > ns_blocksize - 1 ) ;
nsbh = sb_getblk ( sb , newblocknr ) ;
if ( ! nsbh ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_WARNING ,
" unable to move secondary superblock to block %llu " ,
( unsigned long long ) newblocknr ) ;
2011-05-04 20:23:57 +04:00
ret = - EIO ;
goto out ;
}
nsbp = ( void * ) nsbh - > b_data + offset ;
memset ( nsbp , 0 , nilfs - > ns_blocksize ) ;
if ( sb2i > = 0 ) {
memcpy ( nsbp , nilfs - > ns_sbp [ sb2i ] , nilfs - > ns_sbsize ) ;
brelse ( nilfs - > ns_sbh [ sb2i ] ) ;
nilfs - > ns_sbh [ sb2i ] = nsbh ;
nilfs - > ns_sbp [ sb2i ] = nsbp ;
} else if ( nilfs - > ns_sbh [ 0 ] - > b_blocknr < nilfs - > ns_first_data_block ) {
/* secondary super block will be restored to index 1 */
nilfs - > ns_sbh [ 1 ] = nsbh ;
nilfs - > ns_sbp [ 1 ] = nsbp ;
} else {
brelse ( nsbh ) ;
}
out :
return ret ;
}
2011-05-04 20:23:58 +04:00
/**
* nilfs_resize_fs - resize the filesystem
* @ sb : super block instance
* @ newsize : new size of the filesystem ( in bytes )
*/
int nilfs_resize_fs ( struct super_block * sb , __u64 newsize )
{
struct the_nilfs * nilfs = sb - > s_fs_info ;
struct nilfs_super_block * * sbp ;
__u64 devsize , newnsegs ;
loff_t sb2off ;
int ret ;
ret = - ERANGE ;
devsize = i_size_read ( sb - > s_bdev - > bd_inode ) ;
if ( newsize > devsize )
goto out ;
/*
* Write lock is required to protect some functions depending
* on the number of segments , the number of reserved segments ,
* and so forth .
*/
down_write ( & nilfs - > ns_segctor_sem ) ;
sb2off = NILFS_SB2_OFFSET_BYTES ( newsize ) ;
newnsegs = sb2off > > nilfs - > ns_blocksize_bits ;
do_div ( newnsegs , nilfs - > ns_blocks_per_segment ) ;
ret = nilfs_sufile_resize ( nilfs - > ns_sufile , newnsegs ) ;
up_write ( & nilfs - > ns_segctor_sem ) ;
if ( ret < 0 )
goto out ;
ret = nilfs_construct_segment ( sb ) ;
if ( ret < 0 )
goto out ;
down_write ( & nilfs - > ns_sem ) ;
nilfs_move_2nd_super ( sb , sb2off ) ;
ret = - EIO ;
sbp = nilfs_prepare_super ( sb , 0 ) ;
if ( likely ( sbp ) ) {
nilfs_set_log_cursor ( sbp [ 0 ] , nilfs ) ;
/*
* Drop NILFS_RESIZE_FS flag for compatibility with
* mount - time resize which may be implemented in a
* future release .
*/
sbp [ 0 ] - > s_state = cpu_to_le16 ( le16_to_cpu ( sbp [ 0 ] - > s_state ) &
~ NILFS_RESIZE_FS ) ;
sbp [ 0 ] - > s_dev_size = cpu_to_le64 ( newsize ) ;
sbp [ 0 ] - > s_nsegments = cpu_to_le64 ( nilfs - > ns_nsegments ) ;
if ( sbp [ 1 ] )
memcpy ( sbp [ 1 ] , sbp [ 0 ] , nilfs - > ns_sbsize ) ;
ret = nilfs_commit_super ( sb , NILFS_SB_COMMIT_ALL ) ;
}
up_write ( & nilfs - > ns_sem ) ;
/*
* Reset the range of allocatable segments last . This order
* is important in the case of expansion because the secondary
* superblock must be protected from log write until migration
* completes .
*/
if ( ! ret )
nilfs_sufile_set_alloc_range ( nilfs - > ns_sufile , 0 , newnsegs - 1 ) ;
out :
return ret ;
}
2009-04-07 06:01:35 +04:00
static void nilfs_put_super ( struct super_block * sb )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:35 +04:00
2011-03-09 05:05:08 +03:00
nilfs_detach_log_writer ( sb ) ;
2009-04-07 06:01:35 +04:00
2017-07-17 10:45:34 +03:00
if ( ! sb_rdonly ( sb ) ) {
2009-04-07 06:01:35 +04:00
down_write ( & nilfs - > ns_sem ) ;
2011-03-09 05:05:08 +03:00
nilfs_cleanup_super ( sb ) ;
2009-04-07 06:01:35 +04:00
up_write ( & nilfs - > ns_sem ) ;
}
2010-09-05 07:20:59 +04:00
iput ( nilfs - > ns_sufile ) ;
iput ( nilfs - > ns_cpfile ) ;
iput ( nilfs - > ns_dat ) ;
2010-09-08 21:07:56 +04:00
destroy_nilfs ( nilfs ) ;
2009-04-07 06:01:35 +04:00
sb - > s_fs_info = NULL ;
}
static int nilfs_sync_fs ( struct super_block * sb , int wait )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-06-28 12:49:32 +04:00
struct nilfs_super_block * * sbp ;
2009-04-07 06:01:35 +04:00
int err = 0 ;
/* This function is called when super block should be written back */
if ( wait )
err = nilfs_construct_segment ( sb ) ;
2009-07-22 20:26:33 +04:00
down_write ( & nilfs - > ns_sem ) ;
2010-06-28 12:49:32 +04:00
if ( nilfs_sb_dirty ( nilfs ) ) {
2011-03-09 05:05:08 +03:00
sbp = nilfs_prepare_super ( sb , nilfs_sb_will_flip ( nilfs ) ) ;
2010-06-28 12:49:33 +04:00
if ( likely ( sbp ) ) {
nilfs_set_log_cursor ( sbp [ 0 ] , nilfs ) ;
2011-03-09 05:05:08 +03:00
nilfs_commit_super ( sb , NILFS_SB_COMMIT ) ;
2010-06-28 12:49:33 +04:00
}
2010-06-28 12:49:32 +04:00
}
2009-07-22 20:26:33 +04:00
up_write ( & nilfs - > ns_sem ) ;
2014-10-14 02:53:20 +04:00
if ( ! err )
err = nilfs_flush_device ( nilfs ) ;
2009-04-07 06:01:35 +04:00
return err ;
}
2011-03-09 05:05:08 +03:00
int nilfs_attach_checkpoint ( struct super_block * sb , __u64 cno , int curr_mnt ,
2010-08-25 12:45:44 +04:00
struct nilfs_root * * rootp )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-08-25 12:45:44 +04:00
struct nilfs_root * root ;
2009-04-07 06:01:35 +04:00
struct nilfs_checkpoint * raw_cp ;
struct buffer_head * bh_cp ;
2010-08-25 12:45:44 +04:00
int err = - ENOMEM ;
2009-04-07 06:01:35 +04:00
2010-08-25 12:45:44 +04:00
root = nilfs_find_or_create_root (
nilfs , curr_mnt ? NILFS_CPTREE_CURRENT_CNO : cno ) ;
if ( ! root )
return err ;
2009-04-07 06:01:35 +04:00
2010-08-14 08:07:15 +04:00
if ( root - > ifile )
goto reuse ; /* already attached checkpoint */
2009-04-07 06:01:35 +04:00
2009-08-18 10:58:24 +04:00
down_read ( & nilfs - > ns_segctor_sem ) ;
2009-04-07 06:01:35 +04:00
err = nilfs_cpfile_get_checkpoint ( nilfs - > ns_cpfile , cno , 0 , & raw_cp ,
& bh_cp ) ;
2009-08-18 10:58:24 +04:00
up_read ( & nilfs - > ns_segctor_sem ) ;
2009-04-07 06:01:35 +04:00
if ( unlikely ( err ) ) {
if ( err = = - ENOENT | | err = = - EINVAL ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR ,
" Invalid checkpoint (checkpoint number=%llu) " ,
( unsigned long long ) cno ) ;
2009-04-07 06:01:35 +04:00
err = - EINVAL ;
}
goto failed ;
}
2010-09-05 07:20:59 +04:00
2011-03-09 05:05:08 +03:00
err = nilfs_ifile_read ( sb , root , nilfs - > ns_inode_size ,
2010-09-05 07:20:59 +04:00
& raw_cp - > cp_ifile_inode , & root - > ifile ) ;
if ( err )
2009-04-07 06:01:35 +04:00
goto failed_bh ;
2010-08-14 09:48:32 +04:00
2013-07-04 02:08:06 +04:00
atomic64_set ( & root - > inodes_count ,
le64_to_cpu ( raw_cp - > cp_inodes_count ) ) ;
atomic64_set ( & root - > blocks_count ,
le64_to_cpu ( raw_cp - > cp_blocks_count ) ) ;
2009-04-07 06:01:35 +04:00
nilfs_cpfile_put_checkpoint ( nilfs - > ns_cpfile , cno , bh_cp ) ;
2010-08-25 12:45:44 +04:00
2010-08-14 08:07:15 +04:00
reuse :
2010-08-25 12:45:44 +04:00
* rootp = root ;
2009-04-07 06:01:35 +04:00
return 0 ;
failed_bh :
nilfs_cpfile_put_checkpoint ( nilfs - > ns_cpfile , cno , bh_cp ) ;
failed :
2010-08-25 12:45:44 +04:00
nilfs_put_root ( root ) ;
2009-04-07 06:01:35 +04:00
return err ;
}
2010-09-20 13:19:06 +04:00
static int nilfs_freeze ( struct super_block * sb )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-09-20 13:19:06 +04:00
int err ;
2017-07-17 10:45:34 +03:00
if ( sb_rdonly ( sb ) )
2010-09-20 13:19:06 +04:00
return 0 ;
2009-04-07 06:01:35 +04:00
2010-09-20 13:19:06 +04:00
/* Mark super block clean */
down_write ( & nilfs - > ns_sem ) ;
2011-03-09 05:05:08 +03:00
err = nilfs_cleanup_super ( sb ) ;
2010-09-20 13:19:06 +04:00
up_write ( & nilfs - > ns_sem ) ;
2009-04-07 06:01:35 +04:00
return err ;
}
2010-09-20 13:19:06 +04:00
static int nilfs_unfreeze ( struct super_block * sb )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:35 +04:00
2017-07-17 10:45:34 +03:00
if ( sb_rdonly ( sb ) )
2010-09-20 13:19:06 +04:00
return 0 ;
down_write ( & nilfs - > ns_sem ) ;
2011-03-09 05:05:08 +03:00
nilfs_setup_super ( sb , false ) ;
2010-09-20 13:19:06 +04:00
up_write ( & nilfs - > ns_sem ) ;
return 0 ;
2009-04-07 06:01:35 +04:00
}
static int nilfs_statfs ( struct dentry * dentry , struct kstatfs * buf )
{
struct super_block * sb = dentry - > d_sb ;
2015-03-18 01:25:59 +03:00
struct nilfs_root * root = NILFS_I ( d_inode ( dentry ) ) - > i_root ;
2010-08-14 09:48:32 +04:00
struct the_nilfs * nilfs = root - > nilfs ;
2009-03-26 04:16:57 +03:00
u64 id = huge_encode_dev ( sb - > s_bdev - > bd_dev ) ;
2009-04-07 06:01:35 +04:00
unsigned long long blocks ;
unsigned long overhead ;
unsigned long nrsvblocks ;
sector_t nfreeblocks ;
2013-07-04 02:08:05 +04:00
u64 nmaxinodes , nfreeinodes ;
2009-04-07 06:01:35 +04:00
int err ;
/*
* Compute all of the segment blocks
*
* The blocks before first segment and after last segment
* are excluded .
*/
blocks = nilfs - > ns_blocks_per_segment * nilfs - > ns_nsegments
- nilfs - > ns_first_data_block ;
nrsvblocks = nilfs - > ns_nrsvsegs * nilfs - > ns_blocks_per_segment ;
/*
* Compute the overhead
*
2010-03-13 21:32:40 +03:00
* When distributing meta data blocks outside segment structure ,
2009-04-07 06:01:35 +04:00
* We must count them as the overhead .
*/
overhead = 0 ;
err = nilfs_count_free_blocks ( nilfs , & nfreeblocks ) ;
if ( unlikely ( err ) )
return err ;
2013-07-04 02:08:05 +04:00
err = nilfs_ifile_count_free_inodes ( root - > ifile ,
& nmaxinodes , & nfreeinodes ) ;
if ( unlikely ( err ) ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_WARNING ,
" failed to count free inodes: err=%d " , err ) ;
2013-07-04 02:08:05 +04:00
if ( err = = - ERANGE ) {
/*
* If nilfs_palloc_count_max_entries ( ) returns
* - ERANGE error code then we simply treat
* curent inodes count as maximum possible and
* zero as free inodes value .
*/
2013-07-04 02:08:06 +04:00
nmaxinodes = atomic64_read ( & root - > inodes_count ) ;
2013-07-04 02:08:05 +04:00
nfreeinodes = 0 ;
err = 0 ;
} else
return err ;
}
2009-04-07 06:01:35 +04:00
buf - > f_type = NILFS_SUPER_MAGIC ;
buf - > f_bsize = sb - > s_blocksize ;
buf - > f_blocks = blocks - overhead ;
buf - > f_bfree = nfreeblocks ;
buf - > f_bavail = ( buf - > f_bfree > = nrsvblocks ) ?
( buf - > f_bfree - nrsvblocks ) : 0 ;
2013-07-04 02:08:05 +04:00
buf - > f_files = nmaxinodes ;
buf - > f_ffree = nfreeinodes ;
2009-04-07 06:01:35 +04:00
buf - > f_namelen = NILFS_NAME_LEN ;
2009-03-26 04:16:57 +03:00
buf - > f_fsid . val [ 0 ] = ( u32 ) id ;
buf - > f_fsid . val [ 1 ] = ( u32 ) ( id > > 32 ) ;
2009-04-07 06:01:35 +04:00
return 0 ;
}
2011-12-09 06:32:45 +04:00
static int nilfs_show_options ( struct seq_file * seq , struct dentry * dentry )
2009-06-24 15:06:34 +04:00
{
2011-12-09 06:32:45 +04:00
struct super_block * sb = dentry - > d_sb ;
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2015-03-18 01:25:59 +03:00
struct nilfs_root * root = NILFS_I ( d_inode ( dentry ) ) - > i_root ;
2009-06-24 15:06:34 +04:00
2011-03-09 05:05:07 +03:00
if ( ! nilfs_test_opt ( nilfs , BARRIER ) )
2010-07-05 09:40:27 +04:00
seq_puts ( seq , " ,nobarrier " ) ;
2010-08-15 20:54:52 +04:00
if ( root - > cno ! = NILFS_CPTREE_CURRENT_CNO )
seq_printf ( seq , " ,cp=%llu " , ( unsigned long long ) root - > cno ) ;
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , ERRORS_PANIC ) )
2010-07-05 09:40:27 +04:00
seq_puts ( seq , " ,errors=panic " ) ;
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , ERRORS_CONT ) )
2010-07-05 09:40:27 +04:00
seq_puts ( seq , " ,errors=continue " ) ;
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , STRICT_ORDER ) )
2010-07-05 09:40:27 +04:00
seq_puts ( seq , " ,order=strict " ) ;
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , NORECOVERY ) )
2010-07-05 09:40:27 +04:00
seq_puts ( seq , " ,norecovery " ) ;
2011-03-09 05:05:07 +03:00
if ( nilfs_test_opt ( nilfs , DISCARD ) )
2010-07-05 09:40:27 +04:00
seq_puts ( seq , " ,discard " ) ;
2009-06-24 15:06:34 +04:00
return 0 ;
}
2009-09-22 04:01:09 +04:00
static const struct super_operations nilfs_sops = {
2009-04-07 06:01:35 +04:00
. alloc_inode = nilfs_alloc_inode ,
. destroy_inode = nilfs_destroy_inode ,
. dirty_inode = nilfs_dirty_inode ,
2010-06-07 19:55:00 +04:00
. evict_inode = nilfs_evict_inode ,
2009-04-07 06:01:35 +04:00
. put_super = nilfs_put_super ,
. sync_fs = nilfs_sync_fs ,
2010-09-20 13:19:06 +04:00
. freeze_fs = nilfs_freeze ,
. unfreeze_fs = nilfs_unfreeze ,
2009-04-07 06:01:35 +04:00
. statfs = nilfs_statfs ,
. remount_fs = nilfs_remount ,
2009-06-24 15:06:34 +04:00
. show_options = nilfs_show_options
2009-04-07 06:01:35 +04:00
} ;
enum {
Opt_err_cont , Opt_err_panic , Opt_err_ro ,
2010-07-05 08:00:08 +04:00
Opt_barrier , Opt_nobarrier , Opt_snapshot , Opt_order , Opt_norecovery ,
2010-07-05 09:27:04 +04:00
Opt_discard , Opt_nodiscard , Opt_err ,
2009-04-07 06:01:35 +04:00
} ;
static match_table_t tokens = {
{ Opt_err_cont , " errors=continue " } ,
{ Opt_err_panic , " errors=panic " } ,
{ Opt_err_ro , " errors=remount-ro " } ,
2010-07-05 08:00:08 +04:00
{ Opt_barrier , " barrier " } ,
2009-11-12 08:07:26 +03:00
{ Opt_nobarrier , " nobarrier " } ,
2009-04-07 06:01:35 +04:00
{ Opt_snapshot , " cp=%u " } ,
{ Opt_order , " order=%s " } ,
2009-11-19 21:28:01 +03:00
{ Opt_norecovery , " norecovery " } ,
2010-01-30 12:06:35 +03:00
{ Opt_discard , " discard " } ,
2010-07-05 09:27:04 +04:00
{ Opt_nodiscard , " nodiscard " } ,
2009-04-07 06:01:35 +04:00
{ Opt_err , NULL }
} ;
2010-07-05 15:08:33 +04:00
static int parse_options ( char * options , struct super_block * sb , int is_remount )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:35 +04:00
char * p ;
substring_t args [ MAX_OPT_ARGS ] ;
if ( ! options )
return 1 ;
while ( ( p = strsep ( & options , " , " ) ) ! = NULL ) {
int token ;
2016-05-24 02:23:25 +03:00
2009-04-07 06:01:35 +04:00
if ( ! * p )
continue ;
token = match_token ( p , tokens , args ) ;
switch ( token ) {
2010-07-05 08:00:08 +04:00
case Opt_barrier :
2011-03-09 05:05:07 +03:00
nilfs_set_opt ( nilfs , BARRIER ) ;
2010-07-05 08:00:08 +04:00
break ;
2009-11-12 08:07:26 +03:00
case Opt_nobarrier :
2011-03-09 05:05:07 +03:00
nilfs_clear_opt ( nilfs , BARRIER ) ;
2009-04-07 06:01:35 +04:00
break ;
case Opt_order :
if ( strcmp ( args [ 0 ] . from , " relaxed " ) = = 0 )
/* Ordered data semantics */
2011-03-09 05:05:07 +03:00
nilfs_clear_opt ( nilfs , STRICT_ORDER ) ;
2009-04-07 06:01:35 +04:00
else if ( strcmp ( args [ 0 ] . from , " strict " ) = = 0 )
/* Strict in-order semantics */
2011-03-09 05:05:07 +03:00
nilfs_set_opt ( nilfs , STRICT_ORDER ) ;
2009-04-07 06:01:35 +04:00
else
return 0 ;
break ;
case Opt_err_panic :
2011-03-09 05:05:07 +03:00
nilfs_write_opt ( nilfs , ERROR_MODE , ERRORS_PANIC ) ;
2009-04-07 06:01:35 +04:00
break ;
case Opt_err_ro :
2011-03-09 05:05:07 +03:00
nilfs_write_opt ( nilfs , ERROR_MODE , ERRORS_RO ) ;
2009-04-07 06:01:35 +04:00
break ;
case Opt_err_cont :
2011-03-09 05:05:07 +03:00
nilfs_write_opt ( nilfs , ERROR_MODE , ERRORS_CONT ) ;
2009-04-07 06:01:35 +04:00
break ;
case Opt_snapshot :
2010-07-05 15:08:33 +04:00
if ( is_remount ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR ,
" \" %s \" option is invalid for remount " ,
p ) ;
2009-04-07 06:01:35 +04:00
return 0 ;
2010-07-05 15:08:33 +04:00
}
2009-04-07 06:01:35 +04:00
break ;
2009-11-19 21:28:01 +03:00
case Opt_norecovery :
2011-03-09 05:05:07 +03:00
nilfs_set_opt ( nilfs , NORECOVERY ) ;
2009-11-19 21:28:01 +03:00
break ;
2010-01-30 12:06:35 +03:00
case Opt_discard :
2011-03-09 05:05:07 +03:00
nilfs_set_opt ( nilfs , DISCARD ) ;
2010-01-30 12:06:35 +03:00
break ;
2010-07-05 09:27:04 +04:00
case Opt_nodiscard :
2011-03-09 05:05:07 +03:00
nilfs_clear_opt ( nilfs , DISCARD ) ;
2010-07-05 09:27:04 +04:00
break ;
2009-04-07 06:01:35 +04:00
default :
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR ,
" unrecognized mount option \" %s \" " , p ) ;
2009-04-07 06:01:35 +04:00
return 0 ;
}
}
return 1 ;
}
static inline void
2011-03-09 05:05:07 +03:00
nilfs_set_default_options ( struct super_block * sb ,
2009-04-07 06:01:35 +04:00
struct nilfs_super_block * sbp )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2011-03-09 05:05:07 +03:00
nilfs - > ns_mount_opt =
2010-04-02 13:02:33 +04:00
NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER ;
2009-04-07 06:01:35 +04:00
}
2011-03-09 05:05:08 +03:00
static int nilfs_setup_super ( struct super_block * sb , int is_mount )
2009-04-07 06:01:35 +04:00
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-06-28 12:49:32 +04:00
struct nilfs_super_block * * sbp ;
int max_mnt_count ;
int mnt_count ;
/* nilfs->ns_sem must be locked by the caller. */
2011-03-09 05:05:08 +03:00
sbp = nilfs_prepare_super ( sb , 0 ) ;
2010-06-28 12:49:32 +04:00
if ( ! sbp )
return - EIO ;
2010-09-20 13:19:06 +04:00
if ( ! is_mount )
goto skip_mount_setup ;
2010-06-28 12:49:32 +04:00
max_mnt_count = le16_to_cpu ( sbp [ 0 ] - > s_max_mnt_count ) ;
mnt_count = le16_to_cpu ( sbp [ 0 ] - > s_mnt_count ) ;
2009-04-07 06:01:35 +04:00
2009-11-19 10:58:40 +03:00
if ( nilfs - > ns_mount_state & NILFS_ERROR_FS ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_WARNING , " mounting fs with errors " ) ;
2009-04-07 06:01:35 +04:00
#if 0
} else if ( max_mnt_count > = 0 & & mnt_count > = max_mnt_count ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_WARNING , " maximal mount count reached " ) ;
2009-04-07 06:01:35 +04:00
# endif
}
if ( ! max_mnt_count )
2010-06-28 12:49:32 +04:00
sbp [ 0 ] - > s_max_mnt_count = cpu_to_le16 ( NILFS_DFL_MAX_MNT_COUNT ) ;
2009-04-07 06:01:35 +04:00
2010-06-28 12:49:32 +04:00
sbp [ 0 ] - > s_mnt_count = cpu_to_le16 ( mnt_count + 1 ) ;
2018-08-22 07:59:05 +03:00
sbp [ 0 ] - > s_mtime = cpu_to_le64 ( ktime_get_real_seconds ( ) ) ;
2010-09-20 13:19:06 +04:00
skip_mount_setup :
2010-06-28 12:49:32 +04:00
sbp [ 0 ] - > s_state =
cpu_to_le16 ( le16_to_cpu ( sbp [ 0 ] - > s_state ) & ~ NILFS_VALID_FS ) ;
2010-06-28 12:49:33 +04:00
/* synchronize sbp[1] with sbp[0] */
2011-01-21 10:40:31 +03:00
if ( sbp [ 1 ] )
memcpy ( sbp [ 1 ] , sbp [ 0 ] , nilfs - > ns_sbsize ) ;
2011-03-09 05:05:08 +03:00
return nilfs_commit_super ( sb , NILFS_SB_COMMIT_ALL ) ;
2009-04-07 06:01:35 +04:00
}
2009-04-07 06:01:59 +04:00
struct nilfs_super_block * nilfs_read_super_block ( struct super_block * sb ,
u64 pos , int blocksize ,
struct buffer_head * * pbh )
2009-04-07 06:01:35 +04:00
{
2009-04-07 06:01:59 +04:00
unsigned long long sb_index = pos ;
unsigned long offset ;
2009-04-07 06:01:35 +04:00
2009-04-07 06:01:59 +04:00
offset = do_div ( sb_index , blocksize ) ;
2009-04-07 06:01:35 +04:00
* pbh = sb_bread ( sb , sb_index ) ;
2009-04-07 06:01:59 +04:00
if ( ! * pbh )
2009-04-07 06:01:35 +04:00
return NULL ;
return ( struct nilfs_super_block * ) ( ( char * ) ( * pbh ) - > b_data + offset ) ;
}
int nilfs_store_magic_and_option ( struct super_block * sb ,
struct nilfs_super_block * sbp ,
char * data )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:35 +04:00
sb - > s_magic = le16_to_cpu ( sbp - > s_magic ) ;
/* FS independent flags */
# ifdef NILFS_ATIME_DISABLE
2017-11-28 00:05:09 +03:00
sb - > s_flags | = SB_NOATIME ;
2009-04-07 06:01:35 +04:00
# endif
2011-03-09 05:05:07 +03:00
nilfs_set_default_options ( sb , sbp ) ;
2009-04-07 06:01:35 +04:00
2011-03-09 05:05:07 +03:00
nilfs - > ns_resuid = le16_to_cpu ( sbp - > s_def_resuid ) ;
nilfs - > ns_resgid = le16_to_cpu ( sbp - > s_def_resgid ) ;
nilfs - > ns_interval = le32_to_cpu ( sbp - > s_c_interval ) ;
nilfs - > ns_watermark = le32_to_cpu ( sbp - > s_c_block_max ) ;
2009-04-07 06:01:35 +04:00
2016-05-24 02:23:34 +03:00
return ! parse_options ( data , sb , 0 ) ? - EINVAL : 0 ;
2009-04-07 06:01:35 +04:00
}
2010-07-21 22:22:20 +04:00
int nilfs_check_feature_compatibility ( struct super_block * sb ,
struct nilfs_super_block * sbp )
{
__u64 features ;
features = le64_to_cpu ( sbp - > s_feature_incompat ) &
~ NILFS_FEATURE_INCOMPAT_SUPP ;
if ( features ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR ,
" couldn't mount because of unsupported optional features (%llx) " ,
( unsigned long long ) features ) ;
2010-07-21 22:22:20 +04:00
return - EINVAL ;
}
features = le64_to_cpu ( sbp - > s_feature_compat_ro ) &
~ NILFS_FEATURE_COMPAT_RO_SUPP ;
2017-07-17 10:45:34 +03:00
if ( ! sb_rdonly ( sb ) & & features ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR ,
" couldn't mount RDWR because of unsupported optional features (%llx) " ,
( unsigned long long ) features ) ;
2010-07-21 22:22:20 +04:00
return - EINVAL ;
}
return 0 ;
}
2010-08-25 20:52:51 +04:00
static int nilfs_get_root_dentry ( struct super_block * sb ,
struct nilfs_root * root ,
struct dentry * * root_dentry )
{
struct inode * inode ;
struct dentry * dentry ;
int ret = 0 ;
inode = nilfs_iget ( sb , root , NILFS_ROOT_INO ) ;
if ( IS_ERR ( inode ) ) {
ret = PTR_ERR ( inode ) ;
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR , " error %d getting root inode " , ret ) ;
2010-08-25 20:52:51 +04:00
goto out ;
}
if ( ! S_ISDIR ( inode - > i_mode ) | | ! inode - > i_blocks | | ! inode - > i_size ) {
iput ( inode ) ;
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR , " corrupt root inode " ) ;
2010-08-25 20:52:51 +04:00
ret = - EINVAL ;
goto out ;
}
2010-08-15 20:54:52 +04:00
if ( root - > cno = = NILFS_CPTREE_CURRENT_CNO ) {
dentry = d_find_alias ( inode ) ;
if ( ! dentry ) {
2012-01-09 07:15:13 +04:00
dentry = d_make_root ( inode ) ;
2010-08-15 20:54:52 +04:00
if ( ! dentry ) {
ret = - ENOMEM ;
goto failed_dentry ;
}
} else {
iput ( inode ) ;
}
} else {
2014-02-15 02:35:37 +04:00
dentry = d_obtain_root ( inode ) ;
2010-08-15 20:54:52 +04:00
if ( IS_ERR ( dentry ) ) {
ret = PTR_ERR ( dentry ) ;
goto failed_dentry ;
}
2010-08-25 20:52:51 +04:00
}
* root_dentry = dentry ;
out :
return ret ;
2010-08-15 20:54:52 +04:00
failed_dentry :
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR , " error %d getting root dentry " , ret ) ;
2010-08-15 20:54:52 +04:00
goto out ;
2010-08-25 20:52:51 +04:00
}
2010-08-25 21:15:41 +04:00
static int nilfs_attach_snapshot ( struct super_block * s , __u64 cno ,
struct dentry * * root_dentry )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = s - > s_fs_info ;
2010-08-25 21:15:41 +04:00
struct nilfs_root * root ;
int ret ;
2012-07-31 01:42:07 +04:00
mutex_lock ( & nilfs - > ns_snapshot_mount_mutex ) ;
2010-08-25 21:15:41 +04:00
down_read ( & nilfs - > ns_segctor_sem ) ;
ret = nilfs_cpfile_is_snapshot ( nilfs - > ns_cpfile , cno ) ;
up_read ( & nilfs - > ns_segctor_sem ) ;
if ( ret < 0 ) {
ret = ( ret = = - ENOENT ) ? - EINVAL : ret ;
goto out ;
} else if ( ! ret ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( s , KERN_ERR ,
" The specified checkpoint is not a snapshot (checkpoint number=%llu) " ,
( unsigned long long ) cno ) ;
2010-08-25 21:15:41 +04:00
ret = - EINVAL ;
goto out ;
}
2011-03-09 05:05:08 +03:00
ret = nilfs_attach_checkpoint ( s , cno , false , & root ) ;
2010-08-25 21:15:41 +04:00
if ( ret ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( s , KERN_ERR ,
" error %d while loading snapshot (checkpoint number=%llu) " ,
ret , ( unsigned long long ) cno ) ;
2010-08-25 21:15:41 +04:00
goto out ;
}
ret = nilfs_get_root_dentry ( s , root , root_dentry ) ;
nilfs_put_root ( root ) ;
out :
2012-07-31 01:42:07 +04:00
mutex_unlock ( & nilfs - > ns_snapshot_mount_mutex ) ;
2010-08-25 21:15:41 +04:00
return ret ;
}
2010-08-15 20:54:52 +04:00
/**
2013-08-24 20:06:16 +04:00
* nilfs_tree_is_busy ( ) - try to shrink dentries of a checkpoint
2010-08-15 20:54:52 +04:00
* @ root_dentry : root dentry of the tree to be shrunk
*
* This function returns true if the tree was in - use .
*/
2013-08-24 20:06:16 +04:00
static bool nilfs_tree_is_busy ( struct dentry * root_dentry )
2010-08-15 20:54:52 +04:00
{
shrink_dcache_parent ( root_dentry ) ;
2013-08-24 20:06:16 +04:00
return d_count ( root_dentry ) > 1 ;
2010-08-15 20:54:52 +04:00
}
2010-09-13 06:16:34 +04:00
int nilfs_checkpoint_is_mounted ( struct super_block * sb , __u64 cno )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2010-09-13 06:16:34 +04:00
struct nilfs_root * root ;
struct inode * inode ;
struct dentry * dentry ;
int ret ;
2015-04-16 22:46:45 +03:00
if ( cno > nilfs - > ns_cno )
2010-09-13 06:16:34 +04:00
return false ;
if ( cno > = nilfs_last_cno ( nilfs ) )
return true ; /* protect recent checkpoints */
ret = false ;
2011-03-09 05:05:08 +03:00
root = nilfs_lookup_root ( nilfs , cno ) ;
2010-09-13 06:16:34 +04:00
if ( root ) {
inode = nilfs_ilookup ( sb , root , NILFS_ROOT_INO ) ;
if ( inode ) {
dentry = d_find_alias ( inode ) ;
if ( dentry ) {
2013-08-24 20:06:16 +04:00
ret = nilfs_tree_is_busy ( dentry ) ;
2010-09-13 06:16:34 +04:00
dput ( dentry ) ;
}
iput ( inode ) ;
}
nilfs_put_root ( root ) ;
}
return ret ;
}
2009-04-07 06:01:35 +04:00
/**
* nilfs_fill_super ( ) - initialize a super block instance
* @ sb : super_block
* @ data : mount options
* @ silent : silent mode flag
*
2009-06-07 20:39:33 +04:00
* This function is called exclusively by nilfs - > ns_mount_mutex .
2009-04-07 06:01:35 +04:00
* So , the recovery process is protected from other simultaneous mounts .
*/
static int
2010-09-08 21:07:56 +04:00
nilfs_fill_super ( struct super_block * sb , void * data , int silent )
2009-04-07 06:01:35 +04:00
{
2010-09-08 21:07:56 +04:00
struct the_nilfs * nilfs ;
2010-08-25 12:45:44 +04:00
struct nilfs_root * fsroot ;
2009-04-07 06:01:35 +04:00
__u64 cno ;
int err ;
2016-08-03 00:05:06 +03:00
nilfs = alloc_nilfs ( sb ) ;
2011-03-09 05:05:08 +03:00
if ( ! nilfs )
2009-04-07 06:01:35 +04:00
return - ENOMEM ;
2011-03-09 05:05:08 +03:00
sb - > s_fs_info = nilfs ;
2009-04-07 06:01:35 +04:00
2011-03-09 05:05:08 +03:00
err = init_nilfs ( nilfs , sb , ( char * ) data ) ;
2009-04-07 06:01:35 +04:00
if ( err )
2010-09-08 21:07:56 +04:00
goto failed_nilfs ;
2009-04-07 06:01:35 +04:00
sb - > s_op = & nilfs_sops ;
sb - > s_export_op = & nilfs_export_ops ;
sb - > s_root = NULL ;
2009-04-07 06:02:00 +04:00
sb - > s_time_gran = 1 ;
2012-02-06 21:45:27 +04:00
sb - > s_max_links = NILFS_LINK_MAX ;
2010-10-07 09:19:48 +04:00
2017-04-12 13:24:43 +03:00
sb - > s_bdi = bdi_get ( sb - > s_bdev - > bd_bdi ) ;
2009-04-07 06:01:35 +04:00
2011-03-09 05:05:08 +03:00
err = load_nilfs ( nilfs , sb ) ;
2009-11-19 10:58:40 +03:00
if ( err )
2010-09-08 21:07:56 +04:00
goto failed_nilfs ;
2009-11-19 10:58:40 +03:00
2009-04-07 06:01:35 +04:00
cno = nilfs_last_cno ( nilfs ) ;
2011-03-09 05:05:08 +03:00
err = nilfs_attach_checkpoint ( sb , cno , true , & fsroot ) ;
2009-04-07 06:01:35 +04:00
if ( err ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_ERR ,
" error %d while loading last checkpoint (checkpoint number=%llu) " ,
err , ( unsigned long long ) cno ) ;
2010-09-05 07:20:59 +04:00
goto failed_unload ;
2009-04-07 06:01:35 +04:00
}
2017-07-17 10:45:34 +03:00
if ( ! sb_rdonly ( sb ) ) {
2011-03-09 05:05:08 +03:00
err = nilfs_attach_log_writer ( sb , fsroot ) ;
2009-04-07 06:01:35 +04:00
if ( err )
goto failed_checkpoint ;
}
2010-08-25 20:52:51 +04:00
err = nilfs_get_root_dentry ( sb , fsroot , & sb - > s_root ) ;
if ( err )
2009-04-07 06:01:35 +04:00
goto failed_segctor ;
2010-08-25 12:45:44 +04:00
nilfs_put_root ( fsroot ) ;
2009-04-07 06:01:35 +04:00
2017-07-17 10:45:34 +03:00
if ( ! sb_rdonly ( sb ) ) {
2009-04-07 06:01:35 +04:00
down_write ( & nilfs - > ns_sem ) ;
2011-03-09 05:05:08 +03:00
nilfs_setup_super ( sb , true ) ;
2009-04-07 06:01:35 +04:00
up_write ( & nilfs - > ns_sem ) ;
}
return 0 ;
failed_segctor :
2011-03-09 05:05:08 +03:00
nilfs_detach_log_writer ( sb ) ;
2009-04-07 06:01:35 +04:00
failed_checkpoint :
2010-08-25 12:45:44 +04:00
nilfs_put_root ( fsroot ) ;
2009-04-07 06:01:35 +04:00
2010-09-05 07:20:59 +04:00
failed_unload :
iput ( nilfs - > ns_sufile ) ;
iput ( nilfs - > ns_cpfile ) ;
iput ( nilfs - > ns_dat ) ;
2010-09-08 21:07:56 +04:00
failed_nilfs :
destroy_nilfs ( nilfs ) ;
2009-04-07 06:01:35 +04:00
return err ;
}
static int nilfs_remount ( struct super_block * sb , int * flags , char * data )
{
2011-03-09 05:05:08 +03:00
struct the_nilfs * nilfs = sb - > s_fs_info ;
2009-04-07 06:01:35 +04:00
unsigned long old_sb_flags ;
2010-12-26 18:04:06 +03:00
unsigned long old_mount_opt ;
2010-08-15 20:54:52 +04:00
int err ;
2009-04-07 06:01:35 +04:00
2014-03-13 18:14:33 +04:00
sync_filesystem ( sb ) ;
2009-04-07 06:01:35 +04:00
old_sb_flags = sb - > s_flags ;
2011-03-09 05:05:07 +03:00
old_mount_opt = nilfs - > ns_mount_opt ;
2009-04-07 06:01:35 +04:00
2010-07-05 15:08:33 +04:00
if ( ! parse_options ( data , sb , 1 ) ) {
2009-04-07 06:01:35 +04:00
err = - EINVAL ;
goto restore_opts ;
}
2017-11-28 00:05:09 +03:00
sb - > s_flags = ( sb - > s_flags & ~ SB_POSIXACL ) ;
2009-04-07 06:01:35 +04:00
2010-05-09 16:51:53 +04:00
err = - EINVAL ;
2009-04-07 06:01:35 +04:00
2009-11-19 21:28:01 +03:00
if ( ! nilfs_valid_fs ( nilfs ) ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_WARNING ,
" couldn't remount because the filesystem is in an incomplete recovery state " ) ;
2009-11-19 21:28:01 +03:00
goto restore_opts ;
}
2017-11-28 00:05:09 +03:00
if ( ( bool ) ( * flags & SB_RDONLY ) = = sb_rdonly ( sb ) )
2009-04-07 06:01:35 +04:00
goto out ;
2017-11-28 00:05:09 +03:00
if ( * flags & SB_RDONLY ) {
2011-03-09 05:05:08 +03:00
/* Shutting down log writer */
nilfs_detach_log_writer ( sb ) ;
2017-11-28 00:05:09 +03:00
sb - > s_flags | = SB_RDONLY ;
2009-04-07 06:01:35 +04:00
/*
* Remounting a valid RW partition RDONLY , so set
* the RDONLY flag and then mark the partition as valid again .
*/
down_write ( & nilfs - > ns_sem ) ;
2011-03-09 05:05:08 +03:00
nilfs_cleanup_super ( sb ) ;
2009-04-07 06:01:35 +04:00
up_write ( & nilfs - > ns_sem ) ;
} else {
2010-07-21 22:22:20 +04:00
__u64 features ;
2010-08-14 08:07:15 +04:00
struct nilfs_root * root ;
2010-07-21 22:22:20 +04:00
2009-04-07 06:01:35 +04:00
/*
* Mounting a RDONLY partition read - write , so reread and
* store the current valid flag . ( It may have been changed
* by fsck since we originally mounted the partition . )
*/
2010-07-21 22:22:20 +04:00
down_read ( & nilfs - > ns_sem ) ;
features = le64_to_cpu ( nilfs - > ns_sbp [ 0 ] - > s_feature_compat_ro ) &
~ NILFS_FEATURE_COMPAT_RO_SUPP ;
up_read ( & nilfs - > ns_sem ) ;
if ( features ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( sb , KERN_WARNING ,
" couldn't remount RDWR because of unsupported optional features (%llx) " ,
( unsigned long long ) features ) ;
2010-07-21 22:22:20 +04:00
err = - EROFS ;
goto restore_opts ;
}
2017-11-28 00:05:09 +03:00
sb - > s_flags & = ~ SB_RDONLY ;
2009-04-07 06:01:35 +04:00
2015-03-18 01:25:59 +03:00
root = NILFS_I ( d_inode ( sb - > s_root ) ) - > i_root ;
2011-03-09 05:05:08 +03:00
err = nilfs_attach_log_writer ( sb , root ) ;
2009-04-07 06:01:35 +04:00
if ( err )
2009-06-07 20:39:32 +04:00
goto restore_opts ;
2009-04-07 06:01:35 +04:00
down_write ( & nilfs - > ns_sem ) ;
2011-03-09 05:05:08 +03:00
nilfs_setup_super ( sb , true ) ;
2009-04-07 06:01:35 +04:00
up_write ( & nilfs - > ns_sem ) ;
}
out :
return 0 ;
restore_opts :
sb - > s_flags = old_sb_flags ;
2011-03-09 05:05:07 +03:00
nilfs - > ns_mount_opt = old_mount_opt ;
2009-04-07 06:01:35 +04:00
return err ;
}
struct nilfs_super_data {
struct block_device * bdev ;
__u64 cno ;
int flags ;
} ;
2016-08-03 00:05:22 +03:00
static int nilfs_parse_snapshot_option ( const char * option ,
const substring_t * arg ,
struct nilfs_super_data * sd )
{
unsigned long long val ;
const char * msg = NULL ;
int err ;
2017-11-28 00:05:09 +03:00
if ( ! ( sd - > flags & SB_RDONLY ) ) {
2016-08-03 00:05:22 +03:00
msg = " read-only option is not specified " ;
goto parse_error ;
}
err = kstrtoull ( arg - > from , 0 , & val ) ;
if ( err ) {
if ( err = = - ERANGE )
msg = " too large checkpoint number " ;
else
msg = " malformed argument " ;
goto parse_error ;
} else if ( val = = 0 ) {
msg = " invalid checkpoint number 0 " ;
goto parse_error ;
}
sd - > cno = val ;
return 0 ;
parse_error :
nilfs_msg ( NULL , KERN_ERR , " invalid option \" %s \" : %s " , option , msg ) ;
return 1 ;
}
2009-04-07 06:01:35 +04:00
/**
* nilfs_identify - pre - read mount options needed to identify mount instance
* @ data : mount options
* @ sd : nilfs_super_data
*/
static int nilfs_identify ( char * data , struct nilfs_super_data * sd )
{
char * p , * options = data ;
substring_t args [ MAX_OPT_ARGS ] ;
2010-09-15 19:36:24 +04:00
int token ;
2009-04-07 06:01:35 +04:00
int ret = 0 ;
do {
p = strsep ( & options , " , " ) ;
if ( p ! = NULL & & * p ) {
token = match_token ( p , tokens , args ) ;
2016-08-03 00:05:22 +03:00
if ( token = = Opt_snapshot )
ret = nilfs_parse_snapshot_option ( p , & args [ 0 ] ,
sd ) ;
2009-04-07 06:01:35 +04:00
}
if ( ! options )
break ;
BUG_ON ( options = = data ) ;
* ( options - 1 ) = ' , ' ;
} while ( ! ret ) ;
return ret ;
}
static int nilfs_set_bdev_super ( struct super_block * s , void * data )
{
2010-08-15 20:54:52 +04:00
s - > s_bdev = data ;
2009-04-07 06:01:35 +04:00
s - > s_dev = s - > s_bdev - > bd_dev ;
return 0 ;
}
static int nilfs_test_bdev_super ( struct super_block * s , void * data )
{
2010-08-15 20:54:52 +04:00
return ( void * ) s - > s_bdev = = data ;
2009-04-07 06:01:35 +04:00
}
2010-07-26 12:19:34 +04:00
static struct dentry *
nilfs_mount ( struct file_system_type * fs_type , int flags ,
const char * dev_name , void * data )
2009-04-07 06:01:35 +04:00
{
struct nilfs_super_data sd ;
2009-06-07 20:39:29 +04:00
struct super_block * s ;
2010-11-13 13:55:18 +03:00
fmode_t mode = FMODE_READ | FMODE_EXCL ;
2010-08-15 20:54:52 +04:00
struct dentry * root_dentry ;
int err , s_new = false ;
2009-04-07 06:01:35 +04:00
2017-11-28 00:05:09 +03:00
if ( ! ( flags & SB_RDONLY ) )
2010-05-08 21:57:57 +04:00
mode | = FMODE_WRITE ;
2010-11-13 13:55:18 +03:00
sd . bdev = blkdev_get_by_path ( dev_name , mode , fs_type ) ;
2010-02-24 15:25:32 +03:00
if ( IS_ERR ( sd . bdev ) )
2010-07-26 12:19:34 +04:00
return ERR_CAST ( sd . bdev ) ;
2009-04-07 06:01:35 +04:00
sd . cno = 0 ;
sd . flags = flags ;
if ( nilfs_identify ( ( char * ) data , & sd ) ) {
err = - EINVAL ;
goto failed ;
}
2009-06-07 20:39:31 +04:00
/*
2010-09-20 13:19:06 +04:00
* once the super is inserted into the list by sget , s_umount
* will protect the lockfs code from trying to start a snapshot
* while we are mounting
2009-06-07 20:39:31 +04:00
*/
2010-09-20 13:19:06 +04:00
mutex_lock ( & sd . bdev - > bd_fsfreeze_mutex ) ;
if ( sd . bdev - > bd_fsfreeze_count > 0 ) {
mutex_unlock ( & sd . bdev - > bd_fsfreeze_mutex ) ;
err = - EBUSY ;
goto failed ;
}
2012-06-25 15:55:37 +04:00
s = sget ( fs_type , nilfs_test_bdev_super , nilfs_set_bdev_super , flags ,
sd . bdev ) ;
2010-09-20 13:19:06 +04:00
mutex_unlock ( & sd . bdev - > bd_fsfreeze_mutex ) ;
2009-06-07 20:39:29 +04:00
if ( IS_ERR ( s ) ) {
err = PTR_ERR ( s ) ;
2010-09-08 21:07:56 +04:00
goto failed ;
2009-04-07 06:01:35 +04:00
}
if ( ! s - > s_root ) {
2016-05-24 02:23:00 +03:00
s_new = true ;
2010-08-15 20:54:52 +04:00
2009-06-07 20:39:29 +04:00
/* New superblock instance created */
2010-05-08 22:01:32 +04:00
s - > s_mode = mode ;
2015-04-13 15:31:37 +03:00
snprintf ( s - > s_id , sizeof ( s - > s_id ) , " %pg " , sd . bdev ) ;
2009-04-07 06:01:35 +04:00
sb_set_blocksize ( s , block_size ( sd . bdev ) ) ;
2017-11-28 00:05:09 +03:00
err = nilfs_fill_super ( s , data , flags & SB_SILENT ? 1 : 0 ) ;
2009-04-07 06:01:35 +04:00
if ( err )
2010-09-08 21:07:56 +04:00
goto failed_super ;
2009-04-07 06:01:35 +04:00
2017-11-28 00:05:09 +03:00
s - > s_flags | = SB_ACTIVE ;
2010-08-15 20:54:52 +04:00
} else if ( ! sd . cno ) {
2013-08-24 20:06:16 +04:00
if ( nilfs_tree_is_busy ( s - > s_root ) ) {
2017-11-28 00:05:09 +03:00
if ( ( flags ^ s - > s_flags ) & SB_RDONLY ) {
2016-08-03 00:05:10 +03:00
nilfs_msg ( s , KERN_ERR ,
" the device already has a %s mount. " ,
2017-07-17 10:45:34 +03:00
sb_rdonly ( s ) ? " read-only " : " read/write " ) ;
2010-08-15 20:54:52 +04:00
err = - EBUSY ;
goto failed_super ;
}
2013-08-24 20:06:16 +04:00
} else {
2010-08-15 20:54:52 +04:00
/*
* Try remount to setup mount states if the current
* tree is not mounted and only snapshots use this sb .
*/
err = nilfs_remount ( s , & flags , data ) ;
if ( err )
goto failed_super ;
}
2009-04-07 06:01:35 +04:00
}
2010-08-15 20:54:52 +04:00
if ( sd . cno ) {
err = nilfs_attach_snapshot ( s , sd . cno , & root_dentry ) ;
2010-09-08 21:07:56 +04:00
if ( err )
2010-08-15 20:54:52 +04:00
goto failed_super ;
} else {
root_dentry = dget ( s - > s_root ) ;
2009-04-07 06:01:35 +04:00
}
2010-08-15 20:54:52 +04:00
if ( ! s_new )
2010-11-13 13:55:18 +03:00
blkdev_put ( sd . bdev , mode ) ;
2009-04-07 06:01:35 +04:00
2010-07-26 12:19:34 +04:00
return root_dentry ;
2009-04-07 06:01:35 +04:00
2010-08-15 20:54:52 +04:00
failed_super :
2009-08-09 00:52:02 +04:00
deactivate_locked_super ( s ) ;
2009-04-07 06:01:35 +04:00
2010-09-08 21:07:56 +04:00
failed :
if ( ! s_new )
2010-11-13 13:55:18 +03:00
blkdev_put ( sd . bdev , mode ) ;
2010-07-26 12:19:34 +04:00
return ERR_PTR ( err ) ;
2009-04-07 06:01:35 +04:00
}
struct file_system_type nilfs_fs_type = {
. owner = THIS_MODULE ,
. name = " nilfs2 " ,
2010-07-26 12:19:34 +04:00
. mount = nilfs_mount ,
2009-04-07 06:01:35 +04:00
. kill_sb = kill_block_super ,
. fs_flags = FS_REQUIRES_DEV ,
} ;
2013-03-03 07:39:14 +04:00
MODULE_ALIAS_FS ( " nilfs2 " ) ;
2009-04-07 06:01:35 +04:00
2010-04-05 20:54:11 +04:00
static void nilfs_inode_init_once ( void * obj )
2009-04-07 06:01:35 +04:00
{
2010-04-05 20:54:11 +04:00
struct nilfs_inode_info * ii = obj ;
2009-04-07 06:01:35 +04:00
2010-04-05 20:54:11 +04:00
INIT_LIST_HEAD ( & ii - > i_dirty ) ;
# ifdef CONFIG_NILFS_XATTR
init_rwsem ( & ii - > xattr_sem ) ;
# endif
2011-02-23 15:49:47 +03:00
address_space_init_once ( & ii - > i_btnode_cache ) ;
2010-07-10 15:52:09 +04:00
ii - > i_bmap = & ii - > i_bmap_data ;
2010-04-05 20:54:11 +04:00
inode_init_once ( & ii - > vfs_inode ) ;
}
2009-04-07 06:01:35 +04:00
2010-04-05 20:54:11 +04:00
static void nilfs_segbuf_init_once ( void * obj )
{
memset ( obj , 0 , sizeof ( struct nilfs_segment_buffer ) ) ;
}
2009-04-07 06:01:35 +04:00
2010-04-05 20:54:11 +04:00
static void nilfs_destroy_cachep ( void )
{
2012-09-26 05:33:07 +04:00
/*
* Make sure all delayed rcu free inodes are flushed before we
* destroy cache .
*/
rcu_barrier ( ) ;
2015-11-07 03:31:40 +03:00
kmem_cache_destroy ( nilfs_inode_cachep ) ;
kmem_cache_destroy ( nilfs_transaction_cachep ) ;
kmem_cache_destroy ( nilfs_segbuf_cachep ) ;
kmem_cache_destroy ( nilfs_btree_path_cache ) ;
2010-04-05 20:54:11 +04:00
}
2009-04-07 06:01:35 +04:00
2010-04-05 20:54:11 +04:00
static int __init nilfs_init_cachep ( void )
{
nilfs_inode_cachep = kmem_cache_create ( " nilfs2_inode_cache " ,
sizeof ( struct nilfs_inode_info ) , 0 ,
2016-01-15 02:18:21 +03:00
SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT ,
nilfs_inode_init_once ) ;
2010-04-05 20:54:11 +04:00
if ( ! nilfs_inode_cachep )
goto fail ;
nilfs_transaction_cachep = kmem_cache_create ( " nilfs2_transaction_cache " ,
sizeof ( struct nilfs_transaction_info ) , 0 ,
SLAB_RECLAIM_ACCOUNT , NULL ) ;
if ( ! nilfs_transaction_cachep )
goto fail ;
nilfs_segbuf_cachep = kmem_cache_create ( " nilfs2_segbuf_cache " ,
sizeof ( struct nilfs_segment_buffer ) , 0 ,
SLAB_RECLAIM_ACCOUNT , nilfs_segbuf_init_once ) ;
if ( ! nilfs_segbuf_cachep )
goto fail ;
nilfs_btree_path_cache = kmem_cache_create ( " nilfs2_btree_path_cache " ,
sizeof ( struct nilfs_btree_path ) * NILFS_BTREE_LEVEL_MAX ,
0 , 0 , NULL ) ;
if ( ! nilfs_btree_path_cache )
goto fail ;
2009-04-07 06:01:35 +04:00
return 0 ;
2010-04-05 20:54:11 +04:00
fail :
nilfs_destroy_cachep ( ) ;
return - ENOMEM ;
}
static int __init init_nilfs_fs ( void )
{
int err ;
2009-04-07 06:01:35 +04:00
2010-04-05 20:54:11 +04:00
err = nilfs_init_cachep ( ) ;
if ( err )
goto fail ;
2009-04-07 06:01:35 +04:00
2014-08-09 01:20:55 +04:00
err = nilfs_sysfs_init ( ) ;
2010-04-05 20:54:11 +04:00
if ( err )
goto free_cachep ;
2009-04-07 06:01:35 +04:00
2014-08-09 01:20:55 +04:00
err = register_filesystem ( & nilfs_fs_type ) ;
if ( err )
goto deinit_sysfs_entry ;
2010-04-09 19:09:53 +04:00
printk ( KERN_INFO " NILFS version 2 loaded \n " ) ;
2010-04-05 20:54:11 +04:00
return 0 ;
2009-04-07 06:01:35 +04:00
2014-08-09 01:20:55 +04:00
deinit_sysfs_entry :
nilfs_sysfs_exit ( ) ;
2010-04-05 20:54:11 +04:00
free_cachep :
nilfs_destroy_cachep ( ) ;
fail :
2009-04-07 06:01:35 +04:00
return err ;
}
static void __exit exit_nilfs_fs ( void )
{
2010-04-05 20:54:11 +04:00
nilfs_destroy_cachep ( ) ;
2014-08-09 01:20:55 +04:00
nilfs_sysfs_exit ( ) ;
2009-04-07 06:01:35 +04:00
unregister_filesystem ( & nilfs_fs_type ) ;
}
module_init ( init_nilfs_fs )
module_exit ( exit_nilfs_fs )